How do I create custom instance templates in IntelliJ IDEA? - intellij-idea

Intellij supports 'instance templates' i.e. templates usable with expression followed by a period, such as cast, new etc. So MyClass.new expands to new MyClass(I) where I is the cursor.
Now I want to create my own template, expression.orElse which expands to:
Optional.ofNullable(expression).orElse(I)
I tried looking for options in Editor > Live Templates, but couldn't find anything relevant. Is this not possible in IntelliJ IDEA, or am I missing something?

These 'instance templates' are actually called postfix completion templates in IDEA.
Starting with version 2019.2, custom postfix templates can also be created by going to Editor > General > Postfix Completion, as specified here and detailed in this blog post.
For the asked case, the values would be:
Key: orElse
Minimum language leve: 8
Applicable expression types: non void
Value:
Optional.ofNullable($EXPR$).orElse($END$)
Variables:
$EXPR$: Replaced by the target expression
$END$: Location of cursor after substitution
Enabling 'Apply to the topmost expression' disables the scope selection popup that appears on selecting the template.

Related

Kotlin - specify type explicitly in IntelliJ after extracting a variable shortcut

When coding in Java (and Kotlin!) in Intellij, I usually extract variables/fields from the expression that they are being assigned. In other words, if I want to write the following code in Kotlin:
val name = getMyString()
Then I would write getMyString, highlight it and extract the variable using a keyboard shortcut. Nice and simple.
But let's say I want the value type to be shown explicitly, meaning:
val name: String = getMyString()
If I use variable extraction, IntelliJ will offer me a checkbox, which I have to use my mouse to click, that will show the type. Another annoying option would be to set the variable name, then use Alt + Enter show the type explicitly.
Unlike previous questions (or JetBrains documentation), I do not want to have the type displayed by default. I just want to know if there is a keyboard shortcut to check the aforementioned checkbox, without disrupting the flow of writing the code.
After using the extract variable shortcut (Ctrl+Alt
+V for Windows), you can use
Alt+T to toggle Specify type explicitly
Alt+V to toggle Declare with var

PhpStorm - class names as strings suggestions

I have to write the following code (using Zend\Filter\Inflector):
$inflector = new Inflector(':string');
$inflector->setRules([
':string' => [
new StringToLower(),
new UnderscoreToSeparator(),
new DashToCamelCase(),
new UpperCaseWords(),
]
]);
As you see, it uses 4 times the new keyword, immediately instantiating classes (following Zend Filter Interface). In this case autocomplete works fine, PhpStorm easily found what I wanted typing after new.
But better notation, using factories, is using strings, instead of direct instantiation using new:
$inflector = new Inflector(':string');
$inflector->setRules([
':string' => [
'StringToLower',
'UnderscoreToSeparator',
'DashToCamelCase',
'UpperCaseWords',
]
]);
Is there a way to have autocomplete for those strings? Maybe some annotation hint or something?
Why don't you use UpperCaseWords::class? The resulting value (that will be available during runtime) will be FQN.
I'm not familiar with Zend Framework so I'm just not sure if Zend\Filter\Inflector accepts FQN or it limited to/requires class names only (it should accept FQN ... so user-made classes would also be accepted/it's expected behaviour).
The benefit: refactoring / find usages will also be supported (since this is a piece of code and not just a string).
In any case: class name completion in strings should work since 2017.1.4 (works fine here in current stable 2017.2.4).
You just invoke code completion one more time (e.g. Ctrl + Space twice (or whatever else shortcut you have there on your computer/OS for Code | Completion | Basic)) .. or just use Ctrl + Alt + Space straight away (class name completion).
Obviously, it will work if completion is invoked on the beginning of the string. If it's in the middle/end of it (e.g. "use [CLASS_NAME_EXPECTED_HERE]") -- type whole thing manually or try other completion methods (e.g. Cyclic Expand Word if such class name was already mentioned in current file).

Intellij - is there autocomplete for the type of a for loop?

like in eclipse, if you wrote a for loop like this:
for (name : names)
eclipse auto complete would let you add the type, so you'll get:
for (String name : names)
is there a similar feature in IntelliJ?
normal auto complete CTRL+SHIFT+SPACE or CTRL+SPACE aren't working.
You can type "iter" and then press Tab. Then you can select in the suggested list of all iterable variables which one to use for the loop.
This type of code generation is also available for other loops. See this answer for a list of live templates for loops.
I'm not familiar with the equivalent eclipse feature, but the closest thing I can think of (or alternative solution) is to use postfix completion.
if you type
names.for
and select the first suggestion, it will auto-expand into
for (Object name : names) {
}
and it will automatically add the type of name for you, based on what the collection type of names is.

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.

String arrays as command line arguments for maven plugin

I'm writing a maven plugin that has a parameter that's a String[].
Like this:
/**
* #parameter expression="${args}"
*/
protected String[] args;
This can be utilized through the POM like this:
<args>
<arg>arg1</arg>
<arg>arg2</arg>
<args>
But I want to send it in from the command line
-Dargs={arg1, arg2}
Is this possible?
You can't do it directly as far as I know, but it is pretty common practice to accept a delimited String and split that into an array yourself.
For example the maven-site-plugin allows you to specify a comma-delimited String of locales, while the maven-scala-plugin handles this by allowing you to define the arguments with a pipe separator. You can look at the relevant Mojos to see how the argument is processed.
Some example usages below:
site-plugin:
-Dlocales=enGB,frFR
scala-plugin:
-DaddArgs=arg1|arg2|arg3
Update: if you want to handle this more elegantly, you could use maven-shared-io to allow definition of an external descriptor file, then pass the descriptor location as a property. This means a single command-line argument can reference a structure of configuration.
If this sounds like it might work for you, have a look at this answer that describes how to use external descriptors in the properties plugin, or this answer that does similar for the xml-maven-plugin. Or you can just look at the assembly-plugin for ideas.
Latest maven (3.0.3) should works with:
-DaddArgs=arg1,arg2,arg3
To update on #nybon’s answer a bit, it seems
#Parameter(property="your.param")
private List<String> yourParam;
works, at least when using maven-plugin-annotations:3.5 in Maven 3.5.0. Running with
-Dyour.param=val1,val2
sets the list.
According to Sonatype's blog here, if you are a plugin developer and
use Maven 3
and annotate your array/collection type plugin parameter using annotation like:
/** #parameter expression="${args}" */
In this way, the plugin parameter can be processed by Maven automatically and plugin users can provide the plugin array/collection type parameters via CLI using a comma separated system property like mvn myplugin:mygoal -Dargs=a,b,c
The way to specify a list of values via system property, for a plugin depends on how up to date the plugin is.
However, if you are dealing with a proper implemented plugin that is up to date, then the correct way of specifying an array of values to a plugin is via comma separated strings.
Here is a reference:
http://blog.sonatype.com/2011/03/configuring-plugin-goals-in-maven-3/
Here is a quote from the reference:
For many plugin parameters it is occasionally convenient to specify
their values from the command line via system properties. In the past,
this was limited to parameters of simple types like String or Boolean.
The latest Maven release finally allows plugin users to configure
collections or arrays from the command line via comma-separated
strings. Take for example a plugin parameter like this:
Going a little bit further, we can look at more concrete example.
Consider, the Wildfly maven plugin.
This plugin has a deprecated configuration property called:
jvmArgs.
This was expected to be passed in as a space separated list of values.
As we all know, in the command line, messing around with spaces is not adorable.
So if we look at the definition of this paramter in the plugin mojo code, you will find something like this (here goes another quote).
/**
* A space delimited list of JVM arguments.
*
* #deprecated use {#link #javaOpts}
*/
#Parameter(alias = "jvm-args", property = PropertyNames.JVM_ARGS)
#Deprecated
private String jvmArgs;
So this is the old way of doing stuff.
Now, if you are using the latest version of this plugin (e.g. Alpha6).
Then the source code will have a nice new field called javaOpts.
Let us look at what the field looks like in the code.
/**
* The JVM options to use.
*/
#Parameter(alias = "java-opts", property = PropertyNames.JAVA_OPTS)
private String[] javaOpts;
So what we see is that we have a nice array field in the StartMojo.
This array field is properly annoted.
And the maven engine will do the heavy lifting of setting the values into the Mojo.
When you want to pump data into this field via the command line, you would in you batch file specify something of the form:
-Dwildfly.javaOpts="-Xmx1536M,-Xms1536M,-XX:MaxMetaspaceSize=512M,-XX:-HeapDumpOnOutOfMemoryError"
If you try the samething using sapces instead of commans.
I will show you what happens:
[INFO] STANDALONE server is starting up. Invalid maximum heap size:
-Xmx1536M -XX:MaxMetaspaceSize=512m -XX:-HeapDumpOnOutOfMemoryError
So you see, maven when it with swallowed my system property full of spaces it did not do a string split. So Wildfly tried to setup the jvm memory settings as if the max memory was that full string.
On the other hand, when I use commas to separate it, the Mojo is properly enriched and I can take control of the memory settings of the app server when it starts up.
And of course, you want to use system properties and not pom.xml XML configuration, for tasks like setting up Jenkins jobs. With system properties you are rather more flexible.
That is it.