When I extract a method, IDEA generates code like this:
#NotNull
private String getSimpleName(TestInfo testInfo) {
return testInfo.getTestClass().get().getSimpleName();
}
I don't want IDEA to generate the #NotNull annotation - in my project everything is assumed to be "not null" by default.
I've added my own custom #Nullable annotation in the "Nullable/NotNull Configuration" dialog - but it seems like one of the annotations in the "NotNull Annotations" section always has to be selected.
I've looked in the "File and Code Templates" section - neither "Implemented Method Body" nor "New Method Body" template contains the #NotNull code.
How do I tell IDEA that everything is "#NotNull" be default and it should not generate an annotation?
Please try the latest version of IntelliJ IDEA: https://www.jetbrains.com/idea/nextversion/. "Generate annotations" option should be available there:
Related
We have a plugin which defines additional properties and adds them as extension properties, like:
project.extra["copyright"] = "Copyright ..."
Then in the build scripts, I can access this like:
project.extra["copyright"]
I'd like to just write:
project.copyright
Some Gradle plugins seem to do something like this. I can access project.sourceSets or project.kotlin even though those certainly aren't in the Project interface.
Using an IDE, I can drill into those convenience methods, which then lands me in some autogenerated code, so I know it's being autogenerated somewhere, but I haven't been able to find any clues to how to get this to happen for our own plugin. The Gradle docs mention type-safe accessors which is ultimately what allowed me to phrase the question, but the docs don't say how to add new ones.
How do we get this treatment for our own plugin?
Creating DSL-like APIS is documented here: https://docs.gradle.org/current/userguide/implementing_gradle_plugins.html#modeling_dsl_like_apis.
It's pretty easy to do. Here's a quick guide, and some tips.
Define an extension.
import org.gradle.api.provider.Property
interface MyExtension {
val copyright: Property<String>
}
It looks pretty boring! What's important is that it's either be an abstract class, or an interface - this is so Gradle can create a new instance (see 'Managed types'), and this is where the Gradle magic begins.
Aside: I've used Property<String> instead of String, although both will work. I recommend using types compatible with Lazy Configuration.
Register the extension.
import org.gradle.api.*
abstract class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
val myExtension: MyExtension =
project.extensions.create("myPlugin", MyExtension::class.java)
}
}
This is the magic part. Simply by registering the extension against the project, Gradle will make the extension available and automatically generate Kotlin-DSL convenience methods.
Apply the plugin
// build.gradle.kts
plugins {
id("my-plugin")
}
myPlugin {
copyright.set("blah blah 2022")
}
Just like that, Gradle will generate Kotlin DSL accessors. Here's one of them:
// Accessorsajp3oxzka99ro52ctxwv0petb.kt
/**
* Configures the [myPlugin][MyExtension] extension.
*/
fun org.gradle.api.Project.`myPlugin`(configure: Action<MyExtension>): Unit =
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("myPlugin", configure)
Use the extension values
Going back to the Plugin definition, lets say you want to register your own task:
// a demo task
abstract class MyTask : DefaultTask() {
#get:Input
abstract val copyright: Property<String>
#TaskAction
fun run() {
println("Copyright is ${copyright.get()}")
}
}
(Note that this task, like the extension, is a 'managed type').
Now the custom task can be registered, and a default value for copyright set.
abstract class MyPlugin : Plugin<Project> {
override fun apply(project: Project) {
val myExtension: MyExtension = project.extensions.create("myPlugin", MyExtension::class.java)
project.tasks.register("myCustomTask", MyTask::class.java) {
copyright.set(myExtension.copyright)
}
}
}
It's good that both MyExtension and MyTask use Property<String> - the actual value will be evaluated lazily, and only if required.
Now if I run ./gradlew :myCustomTask, I see:
> Task :myCustomTask
Copyright is blah blah 2022
Further reading
What if you want to have multiple copyrights? Then you can create a configuration container
What if MyExtension has lots of properties and you want to provide them all to MyTask? Then you can use #Nested inputs
The extension properties can have default values.
IntelliJ autoformat keeps adding a blank lines between class field declarations having annotations.
Do you know how to disable it?
This happens for kotlin files since does not work like that for java files.
Example, between each var intellij adds a blank line each time I execute autoformat.
class Resign : UnitTest() {
#InjectMocks
private lateinit var resignService: ResignServiceImpl
#Mock
private lateinit var actionAccess: ActionAccess
#Mock
private lateinit var userReportConverter: UserReportConverter
....
}
The problem was fixed in KT-37891. The option to disable this behavior should be available in the next plugin version.
You may also consider voting for KT-32185: 'More code style options for minimum blank lines'
Go to Settings > Editor > Code style > Kotlin > Wrapping and Braces.
Change Property annotations to "Do not wrap" or "Wrap if long".
No answer properly points out the exact name of the configuration. Under the Kotlin code style, it can be found on the "Blank Lines" tab, with the name "Before declaration with comment or annotation".
For me, this defaulted to 1. Setting it to 0 let's me decide myself whether I want a new line or not.
How do I get IntelliJ to auto-generate a lambda expression as the argument being passed?
What I want:
I have seen the Question How to autocomplete lambdas in IntelliJ IDEA?, but that does not seem to produce my desired result.
As Tagir Valeev already mentioned in his comment, IntelliJ will auto-generate lambda code, but only if your ClickListener is a (functional) interface.
E.g.:
#FunctionalInterface
interface ClickListener {
void listen();
}
class Clicker {
void addClickListener(ClickListener listener){
// ...
}
}
Then, Intellij suggests upon hitting Ctrl+Shift+Space
Note: As to the #FunctionalInterface annotation, Jav Doc says
This annotation is not a requirement for the compiler to recognize an interface as a functional interface
Kotlin compiler remove the Java runtime annotation annotated on a field.The annotation is shown below.
#Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
#com.fasterxml.jackson.annotation.JacksonAnnotation
public #interface JsonDeserialize
I declared it on a field, as seen below.
#JsonSerialize(using = IDEncryptJsonSerializer::class)
#JsonDeserialize(using = IDDecryptJsonDeserializer::class)
#Column(name = "sku_id", nullable = false)
open var skuId: Long = 0L
The annotation doesn't work. Then, I take a fist look at the class file, as seen below.
#field:javax.persistence.Column public open var skuId: kotlin.Long
The JsonDeserialize and JsonSerialize annotation are dismiss.
The two annotations are work well in Java.
My kotlin version is 1.1.4.
How can I fix the problem?
Finally, I found the reason that result in the phenomenon.
If I declare a variable in class constructor, some of annotations annotate on that variable may cannot be compiled correctly.
Some of annotations may be lost because of kotlin compiler bug.
Then, I move the variable in the class body. Everything work well.
Geb uses a static field called content to define the contents of a page or module. The value of the content field is a closure.
class GebishOrgHomePage extends Page {
static content = {
manualsMenu {
module MenuModule, $("#header-content ul li", 0)
}
links { $('.link-list li a') }
}
}
Intellij already has support for this content dsl, however it does not support the module and moduleList methods. This causes limited auto-complete support when working with modules.
To fix this I'd like to write a GroovyDSL script that adds the missing method definitions to the content closure and its nested closures. However, I've no idea how to add methods to a closure that is not passed to a method, since enclosingCall requires a concrete method name.
And the other thing is that those methods must have a generic return type like this:
<T extends Module> T module(Class<T> m) {
// return an instance of T
}
If you use the latest snapshot then module() calls will be understood by your IDE. This is down to moving module() to Navigator exactly for what you are after - autocompletion and strong typing.
Have a look at the current version of section 6.4 of the Book of Geb. The moduleList() will be gone in a future release and that section explains what to use instead. The module() method taking a map argument to initialise module properties will also go, you now initialise the module yourself and pass the instance to module() and there is an example of doing this in 6.4. Thanks to all that you will get autocompletion around module defintions and usage in IntelliJ.