Suggest parameters in IDEA? - intellij-idea

when I type a method call into intellij it doesn't suggest parameters, is it possible to make it suggest parameters?
for example calling
void setFoo( Foo foo );
in context
Foo foo = new Foo();
dto.setFoof(...
could then either prepopulate or suggest foo (netbeans does this).
Also parameters, like boolean could suggest, true or false.
Is it possible to make it suggest them, without additional typing?

You can press CTRL+J (Parameter Info) to get a tooltip showing an abstract of all parameters for all overloaded variants of a method (place the caret on the method). When using code completion (CTRL+Space) or SmartType (CTRL+Shift+Space) inside the method's parentheses, IntelliJ tries to intelligently propose parameter values that fit in the current context (such as true or false or a method yielding true or false for a boolean parameter).
In the Settings dialog (Settings... -> Editor -> Code Completion) you can configure the Parameter Info feature by activating an autopopup or enabling showing full signatures.

Related

Kotlin construction: function call with additional body - what such construction means or how it is called (if I want to look it up in the docs)?

I am seeing the Kotlin code:
navController.navigate("sales_order/" + it.toString()) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
which I can describe as "function call" (navController.navigate) "with additional body" ({...}). How such construction is called (if I want to look it up in the docs) and what does it mean?
When I checked the type of navController.navigate(...) args, then there are 2 arguments. The first argument - string - is provided in () and I am trying to guess, that everything inside {...} is the content for the second argument which has type NavOptionsBuilder in this case. So, I can guess that NavOptionsBuilder has 3 arguments: 1 function call popUpTo that returns some object and 2 named arguments (launchSingleTop, restoreState) which are Boolean type.
Am I deciphering this construction right - just another way of passing arguments - or is there something deeper?
Am I deciphering this construction right
Almost. You got the beginning right, but the end is not exactly correct.
Let's start with what you got right, and throw in some vocabulary here for posterity. Indeed, you seem to be using the overload of navigate that takes 2 arguments: a string route and a builder function.
Functions in kotlin can be passed in multiple ways, but the most common (and the one used here) is passing a lambda expression. Because the syntax for lambda expressions is based on braces ({ ... }), it makes it look like blocks of code, so the Kotlin language went one step further and allowed to pass lambda expressions outside of the parentheses of the function call when the lambda is the last argument. The reason for this is exactly to allow this kind of constructions which look like their own configuration language. This is what is usually referred to as DSLs (Domain Specific Languages).
Now about what you got wrong:
So, I can guess that NavOptionsBuilder has 3 arguments
Not really. NavOptionsBuilder is the receiver of the function that is passed as the second argument of navigate. This means that, within the lambda that you pass, a NavOptionsBuilder instance is implicitly available as this.
This, in turn, means that you can access methods and properties of NavOptionsBuilder within that lambda block. This is what popUpTo, launchSingleTop, and restoreState are: methods and properties of NavOptionsBuilder - not "arguments".
You can find more general info about this here.

How to change a Kotlin code reference from a function to a field in an intellij plugin?

I'm writing an intellij plugin where I'm refactoring a class, changing its getters (e.g., fun name(): String) to fields (e.g., val name: String).
However, I don't know how best to update the corresponding PsiReference instances. A Kotlin caller needs to change from myObj.name() to myObj.name without the parenthesis.
Currently, I'm doing the following:
ReferencesSearch.search(function).findAll().forEach {
val nextSibling = it.element.nextSibling
if ((nextSibling as? KtValueArgumentList)?.arguments?.isEmpty() == true) {
nextSibling.delete()
}
}
The above works somewhat. That is, the conversion happens correctly. However, the IDE still thinks it is calling a function. It underlines an error in the converted myObj.name with the following message:
Expression 'name' of type String cannot be invoked as a function. The function 'invoke()' is not found
Manually rewriting name in the editor forces intellij to refresh the reference and error disappears.
What should I do instead to prevent this from happening?
You are getting that error message because you are not modifying the reference to the old method. Intellij still thinks your call myObj.name is trying to access some method called name() that doesn't exist anymore.
Also, the search result is going to point to the leaf node in the AST that uses your method. In this case name() has a parent PSI object that holds a reference to name and to (). That's why calling element.nextSibling gives you the () which you can then call delete() on. But this doesn't change the parent's reference.
I'm not sure what is the best way to do what you want but you could try to replace the parent's reference directly. Try:
element.parent.replace(<reference to your the data class field>)

Documenting parameters of a function parameter in Kotlin

Let's say I have a higher order function, which registers some sort of a click listener. I can document its purpose and the listener parameter that's passed in like so:
/**
* Adds a [listener] that's called when the item is clicked.
*
* #param listener The listener to add
*/
fun addClickListener(listener: (count: Int) -> Unit) {
...
}
My question is, is there a way to document the parameters of the listener? This would be count in this example. In my actual use case, I have multiple parameters in my listener.
What I've noticed is that the [listener] text is clickable in the documentation view where I'm using this function, but it just shows an empty dialog about it. Is there a way to describe the parameters there somehow?
For now, I've ended up describing the parameters of the listener with #param blocks at the addClickListener method, but this results in a warning in the IDE, and I'm wondering if there's a more proper way to do it.
As of Kotlin 1.1 there is no syntax for documenting the parameters or return value of a function type used as a function parameter. There is an open YouTrack issue covering this.

How do I define the #param callback {Function}'s expected parameters in IntelliJ?

I use a lot of callbacks and I want the editor to detect the type of function callback that is expected by the method, with a specific nr of parameters of specific types.
Right now it just says Function and it can be anything but I want to make it specific, this in IntelliJ.
Intellij (and the family of editors) support the Google Closure Compiler syntax.
So you'd do something like this:
/**
* #param {function(Number, String)} bar
*/
function foo(bar) {};
Note the lowercase f in function.

Can IntelliJ auto-complete constructor parameters on "new" expression?

If my class has a non-empty constructor, is it possible to auto-complete parameters in the new expression?
With Eclipse, if you press ctrl+space when the cursor is between the parenthesis:
MyClass myObject = new MyClass();
it will find the appropriate parameters.
--> MyClass myObject = new MyClass(name, value);
When I use ctrl+shift+spacebar after the new, Intellij shows me the constructors, but I can't choose one for auto-completion. Am I missing an option?
I usually start with CtrlP (Parameter Info action) to see what arguments are accepted (auto guess complete is way to error prone in my opinion). And if as in your case you want to fill in name type n a dropdown menu appears with all available variables/fields (etc) starting with n Arrow Up/Down and Tab to select name, or CtrlSpace to select a method (or even CtrlAltSpace to be killed by suggestions;-), followed by , and v Tab for value.
Well I used the eclipse key map where Parameter Info is unassigned.
Here is how to change that:
Well there's the Ctrl+Shift+Space combination, which tries to come up with a set of possible arguments. And if you press the Ctrl+Shift+Space a second time, Idea tries find arguments which fit across multiple calls & conversions.
So in your example Ctrl+Shift+Space would almost certainly bring up the 'name' as suggestion. And the next Ctrl+Shift+Space would bring up 'value' as suggestion.
In Intellij Idea 2016.3 you can use option + return. It will ask you if you want to introduce the named argument for the argument you are on and all the followers.
There's no such possibility yet. As IDEA doesn't fill the arguments automatically, distinguishing the constructors in the lookup makes no sense. There's a request for that (http://youtrack.jetbrains.net/issue/IDEABKL-5496) although I sincerely believe such a behavior is too dangerous and error-prone.