Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The type javax.annotation.Nonnull cannot be resolved #2264

Merged
merged 1 commit into from
Oct 12, 2022

Conversation

snjeza
Copy link
Contributor

@snjeza snjeza commented Oct 6, 2022

}
IJavaProject javaProject = JavaCore.create(project);
Map<String, String> options = javaProject.getOptions(true);
assertEquals(options.get(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS), JavaCore.DISABLED);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reverse the arguments here. It's expected, actual.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@CsCherrYY
Copy link
Contributor

The changes LGTM, as for the test part, I suggest to add a test case not including jsr 305 in the pom (in any scope), and test this project would be imported successfully. e.g., sample project in redhat-developer/vscode-java#2712 (comment)

@@ -2057,6 +2060,10 @@ private String getAnnotationType(IJavaProject javaProject, List<String> annotati
if (classpathStorage.keySet().contains(annotationType)) {
// for known types, check the classpath to achieve a better performance
for (String classpath : result.classpaths) {
IClasspathEntry classpathEntry = javaProject.getClasspathEntryFor(new Path(classpath));
if (isTest(classpathEntry, javaProject)) {
Copy link
Contributor

@CsCherrYY CsCherrYY Oct 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about directly use ClasspathOptions.scope = "runtime" in https://github.com/eclipse/eclipse.jdt.ls/blob/f8452b422add64f9bbc80d0e22b48ed71797e563/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java#L2055

in this way, we can avoid checking classpath entry attribute here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. We could exclude test scope directly when getting the project classpaths.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems that using ClasspathOptions.scope = "runtime" doesn't work in this case. I just tested sample project in redhat-developer/vscode-java#2712 (comment) and see the introduced artifact jsr 305 is in runtime scope:

image

So the scope filter won't filter this dependency. However, in the classpath entry, it has test attribute:

image

So the new introduced method isTest() works. it will check the attributes of the classpath entry.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and I also tried ProjectCommand.isTestClasspathEntry() mentioned by @jdneo , it also checks the attribute and it works well. So it seems that we don't need to add a new method.

Copy link
Contributor

@testforstephen testforstephen Oct 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems that using ClasspathOptions.scope = "runtime" doesn't work in this case. I just tested sample project in redhat-developer/vscode-java#2712 (comment) and see the introduced artifact jsr 305 is in runtime scope:

This is a bug on the utility method ProjectCommand.getClasspathsFromJavaProject, which never uses the passed scope parameter.
https://github.com/eclipse/eclipse.jdt.ls/blob/f8452b422add64f9bbc80d0e22b48ed71797e563/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/JavaLaunchConfigurationInfo.java#L35-L50

In the launch configuration template JAVA_APPLICATION_LAUNCH, we could use the following attribute to exclude test code.
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE" value="true"/>

The launch configuration dynamically returns the scope value.
https://github.com/eclipse/eclipse.jdt.ls/blob/f8452b422add64f9bbc80d0e22b48ed71797e563/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/JavaApplicationLaunchConfiguration.java#L45

If the resolve logic doesn't filter the test scope directly, then it's a bug of JavaLaunchDelegate.getClasspathAndModulepath that doesn't handle the test scope well.

I'm OK to filter it on jdt.ls side.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's interesting that the test attribute is set to true but the maven.scope is runtime.

Is that a bug of m2e?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI the jsr305 dependency is declared as implementation scope, not test in spring-kafka: https://github.com/spring-projects/spring-kafka/blob/4bcb503a2fb33d20b45f4cc241c769c397bf0a7d/build.gradle#L173

@CsCherrYY
Copy link
Contributor

it seems that jsr305 introduced by spring-kafka is in runtime scope, which make the null annotation types are not avaiable in project, but the jsr305 jar still appears in default classpath we get from getClasspathsFromJavaProject():

image

maybe we can check the classpath attribute maven.scope=runtime. Besides, I'm not so sure why test tag is introduced by m2e, maybe related to eclipse-m2e/m2e-core#543, but besides checking test tag, checking maven.scope is good IMO. (Do all the runtime classpath entries are tagged by test? maybe @fbricon and @rgrunber can provide some thoughts here)

As for Gradle projects, directly use implementation 'org.springframework.kafka:spring-kafka:2.9.1' will add the dependency in both compileClasspath and runtimeClasspath (which means the null annotation types are available in the project), there will be no such error.

@snjeza
Copy link
Contributor Author

snjeza commented Oct 8, 2022

It's interesting that the test attribute is set to true but the maven.scope is runtime.
Is that a bug of m2e?

It is intentional. See https://github.com/eclipse-m2e/m2e-core/blob/master/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/DefaultClasspathManagerDelegate.java#L164

@snjeza
Copy link
Contributor Author

snjeza commented Oct 8, 2022

The changes LGTM, as for the test part, I suggest to add a test case not including jsr 305 in the pom (in any scope), and test this project would be imported successfully. e.g., sample project in redhat-developer/vscode-java#2712 (comment)

The https://github.com/yotov/vscode-nullable project includes jsr 305 indirectly. It is the same as the maven/null-analysis.

@snjeza
Copy link
Contributor Author

snjeza commented Oct 8, 2022

@rgrunber @CsCherrYY @jdneo @testforstephen I have updated the PR.

@snjeza
Copy link
Contributor Author

snjeza commented Oct 8, 2022

FYI the jsr305 dependency is declared as implementation scope, not test in spring-kafka: https://github.com/spring-projects/spring-kafka/blob/4bcb503a2fb33d20b45f4cc241c769c397bf0a7d/build.gradle#L173

maven recognizes it as runtime

$ cd vscode-nullable
$ mvn dependency:tree
[INFO] org.springframework.boot:example-app:jar:2.7.3
[INFO] +- org.springframework.boot:spring-boot-starter-jdbc:jar:2.7.3:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.7.3:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.7.3:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.7.3:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.7.3:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.11:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.11:compile
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.17.2:compile
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.17.2:compile
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.36:compile
[INFO] |  |  +- jakarta.annotation:jakarta.annotation-api:jar:1.3.5:compile
[INFO] |  |  +- org.springframework:spring-core:jar:5.3.22:compile
[INFO] |  |  |  \- org.springframework:spring-jcl:jar:5.3.22:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.30:compile
[INFO] |  +- com.zaxxer:HikariCP:jar:4.0.3:compile
[INFO] |  |  \- org.slf4j:slf4j-api:jar:1.7.36:compile
[INFO] |  \- org.springframework:spring-jdbc:jar:5.3.22:compile
[INFO] |     \- org.springframework:spring-beans:jar:5.3.22:compile
[INFO] +- mysql:mysql-connector-java:jar:8.0.30:compile
[INFO] \- org.springframework.kafka:spring-kafka:jar:2.8.8:compile
[INFO]    +- org.springframework:spring-context:jar:5.3.22:compile
[INFO]    |  +- org.springframework:spring-aop:jar:5.3.22:compile
[INFO]    |  \- org.springframework:spring-expression:jar:5.3.22:compile
[INFO]    +- org.springframework:spring-messaging:jar:5.3.22:compile
[INFO]    +- org.springframework:spring-tx:jar:5.3.22:compile
[INFO]    +- org.springframework.retry:spring-retry:jar:1.3.3:compile
[INFO]    +- org.apache.kafka:kafka-clients:jar:3.1.1:compile
[INFO]    |  +- com.github.luben:zstd-jni:jar:1.5.0-4:runtime
[INFO]    |  +- org.lz4:lz4-java:jar:1.8.0:runtime
[INFO]    |  \- org.xerial.snappy:snappy-java:jar:1.1.8.4:runtime
[INFO]    \- com.google.code.findbugs:jsr305:jar:3.0.2:runtime

@CsCherrYY
Copy link
Contributor

CsCherrYY commented Oct 8, 2022

maven recognizes it as runtime

that's what I found and suggested in #2264 (comment), if all the runtime classpath entries have test attribute, then I'm OK with this change. It seems that they are related: https://github.com/eclipse-m2e/m2e-core/blob/0223a44258a6c92ac4a1943721a983743809ac37/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/DefaultClasspathManagerDelegate.java#L125

The https://github.com/yotov/vscode-nullable project includes jsr 305 indirectly.

You're right. I just misunderstood that the project doesn't have jsr 305 dependency.

@rgrunber
Copy link
Contributor

Yeah intuitively it made sense to me. runtime is basically saying "you don't need this dependency to compile, but it should be present when running the application". But running the tests also involves running the application, so the behaviour makes sense.

Copy link
Contributor

@rgrunber rgrunber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is ready to be merged.

@rgrunber rgrunber merged commit a00458c into eclipse-jdtls:master Oct 12, 2022
@rgrunber rgrunber added this to the End October milestone Oct 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants