IntelliJ suggests wrong #NotNull annotation - java

IntelliJ is suggesting to import com.sun.istack.internal.NotNull the #NotNull annotation (which is wrong) in the following program:
public class Test implements Comparable<Test> {
#Override
public int compareTo(#NotNull Test o) {
return 0;
}
}
When trying the correct import com.intellij.annotations.NotNull (I think) it looks like it can't find the class:

You can Alt+Enter on the warning before you add the annotation, press Right, choose Edit Inspection Settings, then Configure Annotations and specify the annotation you want to be inserted there.

Remove the import from the code. IntelliJ will ask you to import it again. It should suggest that there are multiple choices available. The annotation you want should be in the list.

I found I had to add the following dependency declaration to my Java project's build.gradle file before I was able to import the org.jetbrains.annotations.NotNull and org.jetbrains.annotations.Nullable annotations rather than the com.sun.istack.internal.NotNull and com.sun.istack.internal.Nullable annotations:
repositories {
mavenCentral()
}
dependencies {
compile 'org.jetbrains:annotations:15.0'
}

For later versions of Intellij, use Cmd+Shift+A (on MacOS) to bring up the Find Actions menu, then type Configure annotations, select the suggestion to bring up the Compiler preference window.
Then click on the Configure annotations button next to the option Add runtime assertions for notnull-annotated methods and parameters. It will then bring up the list of NonNull and Nullable configuration defaults. Select the one you want as default then set it as default with the check button.

Related

Lombok now applies #NonNull checks also for com.mongodb.lang.NonNull (and possibly others)

Let's have a simple MongoDB Document class with Lombok annotations
import lombok.Data;
import com.mongodb.lang.NonNull;
import org.springframework.data.mongodb.core.mapping.Document;
#Document
#Data
public class Car {
#NonNull
private String plate;
}
and simple test
#Test
public void test() {
Car c = new Car();
c.setPlate(null);
}
With Lombok v1.18.22 this worked well and test succeeded. However since v1.18.24, the test starts to fail since apparently Lombok now understands more annotations that indicate that field/param shouldn't be null
https://projectlombok.org/changelog
I'm not sure if MongoDB uses these #NonNull annotations for anything (I think not?) but at least for a documentation purposes it's nice to have them. Also the field can be null in some cases for MongoDB documents f.e. when using Spring Data's filtering using Example
repository.findByExample(Example.of(car))
where I might filter by only some specific field, leaving also mandatory fields to null.
If it'd be about #lombok.NonNull then I'd simply remove it but I don't want to remove Mongo annotations just because of Lombok. Thus my question:
Question 1: Can I avoid these checks? Or can I turn this feature off? So either that Lombok will consider only lombok.* annotations or just suppress generation of null checks in general.
Second issue is that Intellij Idea Lombok plugin apparently doesn't know about this feature yet so it considers that code to be valid. The build then fails as Lombok v1.18.24 generates constructor with all the #NonNull fields so it can't call new Car(). With #lombok.NonNull it works well in Intellij but with Mongo's NonNull it doesn't. I'm using IntelliJ IDEA 2022.1.3 (Community Edition)
Question 2: Is this a bug in Intellij Idea or its Lombok plugin? If yes is it known? I haven't found any info about it which leads me to the idea that the error is on my side

Add an annotation to a class from a place other than class definition

I need to add an annotation to a class which is in a sperate dependency (in a separate jar) of the project that I am working on. I am wondering that can I do this in Java?
As an example, I need to add an annotation HisClass without touching the source code of HisClass.
public class HisClass{
// ...
}
So, that the above class should be look like below at the build time,
#MyAnnot ( me = MyClass.class )
public class HisClass{
// ...
}
There are many ways:
Write a compiler plugin for javac, and make it add the annotations. This will be quite difficult, as the plugin API has nearly no documentation.
2.(Maybe not possible) Inject the annotation after compiling. Add an extra buildstep after compiling and use a library like ASM to add this annotation to the classfile.

Is there anyway in Idea to recognize a getter/setter generated by lombok in the same module

So looking at my class files the getters/setters are being generated just fine, but I'm trying to write a copy method that looks like this in the same jar.
#Data
public class SoftwareVersions {
private String applicationVersion;
void copyTo( MonitorFoleyConnection mfc ) {
mfc.setApplicationVersion( applicationVersion );
}
}
in gradle
annotationProcessor("org.projectlombok:lombok:1.+")
compileOnly("org.projectlombok:lombok:1.+")
is it possible to get intellij to recognize the existance of this method?
Yes, you have. You just need to do two things:
Install the Lombok Plugin for Intellij:
Enable the annotation processing:

Gradle build ignores Jetbrains annotations

Let's say we have the following test code:
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
public class NullTest {
#Test
public void testNull() {
doNothing(null);
}
private #NotNull String doNothing(#NotNull String value) {
return value;
}
}
The test will pass when running gradle test directly or if IDEA delegates the action to gradle.
But it will fail with IllegalArgumentException: Argument for #NotNull parameter 'value' must not be null exception if it runs using IDEA runner (not delegated to gradle).
The question is: how to fail the test running it with gradle?
The easiest solution I have found is to apply org.jetbrains.intellij plugin.
Because among other things this plugin "patches compile tasks to instrument code with nullability assertions".
apply plugin: 'org.jetbrains.intellij'
intellij {
instrumentCode = true
downloadSources = false
}
Try adding the following to your dependencies. It worked for me.
compile 'org.jetbrains:annotations:13.0'
With this code - no way, because you use annotations from org.jetbrains.annotations.*, that use only in intellij idea tests runner. For gradle, annotation #NotNull (or #Nullable) says nothing. Maven also doesn't see this annotation. I can advise you use Objects.requireNonNull(T obj) for null checking.
We found that Lombok's #NonNull works better. But you need to configure IDEA to prefer this one during nullability-related analysis and generation
Adding the following dependency worked for me:
compile group: 'org.jetbrains', name: 'annotations', version: '15.0'
Run the 'dependencies' task & push the refresh button in Gradle.

IntelliJ is it possible to add #Overrides to all methods of a particular interface?

I have created an interface, with about 30 methods and implemented in 30 classes.
I want to add #Override to each of the implementations, but i would like not to do it by hand.
How can IntelliJ help me?
interface looks like this:
public interface PreviewObjectTests {
void testGetName();
void testGetType();
//... 30 similar methods
}
implementation code:
public class PreviewObjectAccountTest implements PreviewObjectTests {
//I want to add #Override here!
#Test public void testGetName() {
assertThat(...);
}
//I want to add #Override here!
#Test public void testGetType() {
assertThat(...);
}
//...30 similar methods
}
Easily done with Alt+Enter intention, then press Right arrow for the sub-menu:
For IntelliJ:
Check if you have "Missing #Override annotation" checked inside Preferences -> Project Settings -> Inspections -> Inheritance issues.
Use Analyze -> Inspect Code
Find Inheritance issues -> Missing #Override annotation inside "Results for Inspection Profile" window.
Apply fix "Add #Override annotation"
For Eclipse (tested on Mars.2):
Window / Preferences (or Project Properties)
Java / Compiler
Error/Warnings
Annotations
Missing #Override annotation - Set to Error (or Warning)
After the rebuild workspace, in the Markers view, right click on one of the errors, Quick Fix (Ctrl+1) and all the errors should appear. Select all and apply the fix.
This worked for me to properly annotate a few hundreds of classes...
I found a way to do it with the simple find/replace tool.
First i changed a method name to provoke all files implementing the interface to change
Then i created a simple find/replace to look only in changed files.
This works in my particular case, because there were not really any other methods in the class files. I will assume this will be a bit more crazy if i had a lot of methods in the files belonging to other interfaces
Its not eclipse or idea specfic. Its compiler specfic and what compliance you adhere to.
In eclipse its 1.6 or higher.
And In idea I believe its for 1.5 or higher.
In the above cases it will bechecked automatically by respective IDEs.

Categories

Resources