How to find where a Kotlin interface method is overridden in intellij? - kotlin

Given this Foo interface
interface Foo {
fun whereIsThisImplemented(a: String): String
}
// How do I use the above interface to find the below implementation
class Bar: Foo {
override fun whereIsThisImplemented(a: String): String {
return a
}
}
is there a simple way of finding where the whereIsThisImplemented method is overridden through intellij?
While whereIsThisImplemented is highlighted, Using edit -> Find Usages -> Find Usage Settings, none of the options will find the Override fun whereIsThisImplemented.
I could find all places the interface is implemented, then look for the method, but this is extremely cumbersome and I was hoping there was a simpler way that I was missing.

Menu: Navigate -> Implementations . Note down the shortcut besides the menu.
Alternatively, you can click on the down arrow on the left of the method declaration
Tip: Install key promoter plugin so that you get a notification of keyboard shortcut everytime you use the mouse.

Hover over the green icon next to the interface function to see a list of places where it is implemented. If you click the icon, it jumps you to that spot in the code.

Related

Structural search interface suspend function call

I have a custom function for wrapping Service api call
I want to add some warning while some api call forget adding safeApiCall{}
suspend fun <T:Any> safeApiCall(
apiCall: suspend () -> T
) {
//do something
}
interface Service {
#Get
suspend fun getUser() : User
#Put
suspend fun updateUser(name:String) : User
}
val service:Service
service.getUser() //warning "should use safeApiCall"
SafeApiCall { service.getUser() } //ok
This is my attempt , but not working
interface $Interface$ {
suspend fun $Method$ ($Parameter$ : $ParameterType$): $ReturnType$
}
$Interface$.$MethodCall$
That was tricky, but here it is:
You need to use script constraints. The idea is to filter the parent of your whole match. There are many ways to do that, e.g. to distinguish them by their type.
Here is my search:
Template:
$Service$.$method$($args$)
$Service$ variable filter:
Type = you.package.Service
$args$ (optional, though):
Count = [0: +Inf]
And the most important part, the whole template script filter:
__context__.parent.parent.class.name == "org.jetbrains.kotlin.psi.KtNamedFunction"
It's dirty, I know. For some reason I was not able to make it work with instanceof, but you may tune it.
If you do, you may ask: How do I debug that script?
Here is my advice. Open the IDEA's logs (Help -> Show Log in Explorer). Then use println() in the script, it will print it's argument to the STDOUT:
You see, here there were two matches, but the parent of the second one (which os ok as per your request) was of a different type. So, a quick guess and dirty fix here was to compare them. A more cunning way would be to get the name of the wrapping construct and check if it's safeApiCall or not. I'll leave that to you as an exercise.
Good luck!

Use extension function from different context in Kotlin

Here is an example of what I'd like to achieve:
open class A {
open fun Int.foo() {
print("foo")
}
}
object B: A() {
val number = 5;
override fun Int.foo() {
print("overriden foo");
// I want to call the A.(Int.foo())
}
}
B.number.foo(); //outputs: "foooverriden foo"
First of all, does anything like this exist? Can I somehow assume number to be in the context of class A in its override method? How would I write this?
The more I think about it the more it twists my mind. Of course, you cannot call number.super.foo() because super for number is kotlin.Number. You cannot cast it to A because Int has nothing to do with A. The only way I can think about solving this to somehow import the extension function itself and rename it with as, but I cannot do that here since it is inside a class, so I cannot just import it. Any suggestions?
My use case for this is that I have a class where I manipulate some data, then in special cases, I want to manipulate it differently, but fall back to the original code as the last option. I could use normal functions instead of extension functions of course, but in my case, it comes natural to use extension functions, so I wanted to see if this could be achieved somehow.
It looks like this is impossible so far, I'm afraid.
There's an open issue for this on JetBrains' issue-tracking system: KT-11488.  There's a Kotlin work-around there, though that needs tweaks to the class designs.
(Also discussed on the JetBrains discussion board.  That mentions another workaround requiring a Java class.)
override fun Int.foo() {
print("overriden foo")
with (A()) {
foo()
}
}
Of course this is a bit of a hack and will get worse if A has some state which foo() depends on, which you'll then need to set manually.

btn.setOnClickListener() how does it calls

I am beginner in programing, and I know how btn.setOnClickListener{} function works (curly brackets).
But there is other tipe of function btn.setOnClickListener() - brackets are not curly. I do not know how and when I should use this tipe of functions. How does such type of function calls? I would like to learn more about it but I do not know how to google it
Answer: "If a function has only one parameter, and this is a function, the parentheses can be deleted"
According to : https://antonioleiva.com/lambdas-kotlin-android/
If a function has only one parameter, and this is a function, the parentheses can be deleted
Instead of having empty parentheses, we can better delete them:
view.setOnClickListener { v -> toast("Hello") }
If the function’s last parameter is a function, it can go outside the parentheses
Therefore, we can extract the listener as follows:
view.setOnClickListener() { v -> toast("Hello") }
If we had more parameters, the rest of the parameters would go inside the parentheses, even if these were functions. Only the last parameter can be extracted.
Both types are equivalent:
button.setOnClickListener {
// ......................
}
button.setOnClickListener(View.OnClickListener {
// ......................
})
but the 1st one is the preferred way to go.
Even if you write the 2nd one, if you hover the mouse over View.OnClickListener, Android Studio will pop up this message:
Redundant SAM constructor
and if you press Alt-Enter you will be prompted:
Remove redundant SAM constructor
and if you click on it then View.OnClickListener will be removed.
Again by pressing Alt-Enter you will be prompted:
Move lambda argument out of parentheses
and if you click on it then you will get the 1st type.
So don't worry about it, use the 1st type and you will be fine.
Answer: "If a function has only one parameter, and this is a function, the parentheses can be deleted"
setOnClickListener(Interface i)
This is Method of View Class in Android.
1. setOnClickListener is method of that class which except only interface as a parameter.
2. or else you have to implement that interface in your class like given example.
Go through Anonymous Class implement process.
the thing is that. either you pass interface object or you have to implement onClick method interface OnClickListener.
1. When you want to implement in class use this
btnView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
2. Pass interface object of onClickListener
appView.setOnClickListener(); ;----> pass interface object

Kotlin DSL scope control on external non-changeable classes (similar to #DslMarker)

I have lots of external classes (generated externally; not under my control), which do not come with a builder and which are rather cumbersome to create. However using apply it is rather easy to build them, e.g.:
SomeOfTheObjects().apply {
someProperty = SomeOtherComplexObject().apply {
someOtherProperty = "..."
}
}
Now I like the way it works with the receiver, but I would like to prevent that I can set someProperty within SomeOtherComplexObject. If the classes were under my control, it would suffice to put a #DslMarker on that class, but as they aren't, the only other way that came to my mind, was to use also instead without renaming the parameter, e.g.:
SomeOfTheObjects().also {
it.someProperty = SomeOtherComplexObject().also {
it.someOtherProperty = "..."
//it.someProperty will not work if SomeOtherComplexObject has no such property
}
}
While it works, it now has tons of it. in the code and I was wondering, whether it is possible to have some similar behaviour as with the #DslMarker in place.
What I tried is a mixture of the following:
#DslMarker
annotation class DemoMarker
#DemoMarker
inline fun <T> T.build(#DemoMarker builder : T.() -> Unit) = this.apply(builder)
"mixture", because I ended up putting the annotation everywhere, but this doesn't have any effect. If I put it on a class it works as expected. Did I miss something and it is actually possible somehow? Or does anyone have an appropriate workaround for this, besides using also?
For third party classes you can use the DslMarker annotation on receiver types as explained here.
#DslMarker
#Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class TestDsl
fun build1(builder: (#TestDsl DslReceiver1).() -> Unit) {}

Kotlin Android Extensions and Menu

Is there any way to access menu_item_search menu item defined in fragment_photo_gallery layout using synthetic properties instead of using findItem method?
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
super.onCreateOptionsMenu(menu, menuInflater)
menuInflater.inflate(R.menu.fragment_photo_gallery, menu)
//is there a way to access searchItem using synthetic properties?
val searchItem = menu.findItem(R.id.menu_item_search)
}
MenuInflater serves a fundamentally different purpose than LayoutInflater.
Despite both having "Inflater" part in its name and implementing methods that are named "inflate()", they do completely different things. MenuInflater inflates Menus, where LayoutInflater inflates Views.
Kotlin Android Extensions were created to simplify usage of Android Views, not Android Menus, or anything that has inflate() method.
Long story short - it is not possible to use KAE with Android Menus.