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

VS Code extension fails Spring Boot update #1142

Closed
pappnase99 opened this issue Nov 7, 2023 · 14 comments
Closed

VS Code extension fails Spring Boot update #1142

pappnase99 opened this issue Nov 7, 2023 · 14 comments
Assignees
Labels
for: eclipse something that is specific for Eclipse for: vscode something that is specific for VSCode theme: refactoring type: bug

Comments

@pappnase99
Copy link

Describe the bug
I try to use the VS Code extension for an update of an outdated Spring Boot project that's on 2.7.7. When I try to update either to the latest 2.7 patch version or the latest major version 3.1.5, it fails with an exception like this:

Activating 'vscode-spring-boot' extension
Trying to use "spring-boot.ls.java.home" value: c:\Program Files\Java\jdk-17
Found java executable: c:\Program Files\Java\jdk-17\bin\java.exe
isJavaEightOrHigher => true
Redirecting server logs to /dev/null
Disabling server log output. No more output will be sent after this.
[Error - 5:29:37 PM] Request workspace/executeCommand failed.
Message: Internal error.
Code: -32603
java.util.concurrent.CompletionException: java.lang.ClassCastException: Cannot cast org.openrewrite.tree.ParseError to org.openrewrite.java.tree.J$CompilationUnit
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315)
at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1159)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1773)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Caused by: java.lang.ClassCastException: Cannot cast org.openrewrite.tree.ParseError to org.openrewrite.java.tree.J$CompilationUnit
at java.base/java.lang.Class.cast(Class.java:3889)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at org.springframework.ide.vscode.commons.rewrite.java.ProjectParser.parseModule(ProjectParser.java:68)
at org.springframework.ide.vscode.commons.rewrite.java.ProjectParser.parse(ProjectParser.java:50)
at org.springframework.ide.vscode.boot.java.rewrite.RewriteRecipeRepository.computeWorkspaceEdit(RewriteRecipeRepository.java:370)
at org.springframework.ide.vscode.boot.java.rewrite.RewriteRecipeRepository.lambda$apply$18(RewriteRecipeRepository.java:331)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150)
... 8 more

OS: Win10, VS Code 1.84.1
Spring Boot Tools 1.50.0
I've set "spring-boot.ls.java.home" to a JDK 17 path in the settings.json.

Maybe there's something weird with this project, but I've no idea what to make of this error.

@BoykoAlex
Copy link
Contributor

Basically OpenRewrite fails to parse one or more of your java source files. We should definitely do better reporting the issue properly... A little popup window in the bottom-right corner showing a warning for example with the path of the source file that failed to parse would be very helpful i think. Also I think we could skip the file with the compilation error and perhaps try and upgrade everything else...

Any chance you can share your project? Or a simplified version of it?

You could also try 1.49 or 1.48 version of Spring Boot Tools for VSCode... It might just work since org.openrewrite.tree.ParseError is rather new in Rewrite. It used to be the CompilationUnit with the ParseError marker on it thus no ClassCastException.

@pappnase99
Copy link
Author

Thanks for the quick answer, since this is a company project I am not able to share it unfortunately. But the project tests and packages successfully, so I'm surprised that it's a source code issue. From a quick glance there are the usual deprecation warnings, but I see no serious issues.

With extension v1.49 same thing happens, however with 1.48 the patch version update is indeed successful. Updating to 3.1 does something, but it looks like the process crashed midway, he did a lot of changes, but now there are compilation issues with Spring Security classes.

@BoykoAlex
Copy link
Contributor

I have pushed bb1cac8 to report the failed to parsed sources and to let the upgrade continue ignoring sources that failed to parse (if possible). The list of sources failed to parse would be shown in the small notification popup in the bottom-right corner. The spring boot language server log file would have more details with the exact errors and parsers that threw exception. There is a setting to output spring boot language server log to file.

You can either find VSIX file here: https://dist.springsource.com/snapshot/STS4/nightly-distributions.html and install it into your VSCode or wait for the new 1.51 pre-release version that will become available on Thursday.

Please try the fix let us know what happens.

@pappnase99
Copy link
Author

I've installed the VSIX-file from the given location and I've redirected the log into a file. The popup shows a single file failed to parse, and this is the related error from the log file:

16:03:26.772 [ForkJoinPool.commonPool-worker-1] WARN o.s.i.v.b.j.r.RewriteRecipeRepository - OpenRewrite parser 'ReloadableJava17Parser' failed to parse 'src\main\java\com\xy\cart\application\XYService.java' with error:
java.lang.IllegalStateException: src\main\java\com\xy\cart\application\XYService.java is not print idempotent.

Then a git diff follows that spans several hundreds of lines, but the important part seems to be this:

-	protected static Item createItem(final com.acme.model.@NonNull CartItem item,
+	protected static Item createItem(final com.acme.model.@NonNulldeartItem item,

So there's a method param with a fully qualified type name and a @NonNull annotation in between, and the parser doesn't seem to like that. When I remove the annotation, the error disappears.

@BoykoAlex
Copy link
Contributor

@pappnase99 I suspect that the syntax com.acme.model.@NonNull isn't valid for this location hence parser throws an error... It should probably be: @com.acme.model.NonNull instead. Not sure why the compiler does not complain... Likely because annotations aren't checked strictly...

@pappnase99
Copy link
Author

pappnase99 commented Nov 9, 2023

No the syntax is strange but correct, the fully qualified name path belongs to the Item, not the Annotation. As a simplified example, this is valid code:

java.lang.@NonNull String test

And this creates a compilation error:
@NonNull java.lang.String test

The compiler says

scoping construct cannot be annotated with type-use annotation: @org.eclipse.jdt.annotation.NonNull

On a different discussion I found a link to this:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.7.4

For example, assume an annotation type TA which is meta-annotated with just @Target(ElementType.TYPE_USE). The terms @TA java.lang.Object and java.@TA lang.Object are illegal because the simple name to which @TA is closest is classified as a package name. On the other hand, java.lang.@TA Object is legal.

@BoykoAlex
Copy link
Contributor

Rewrite Java Parser issue: openrewrite/rewrite#3683

@martinlippert martinlippert added for: eclipse something that is specific for Eclipse and removed status: needs-investigation labels Nov 13, 2023
@Bananeweizen
Copy link

I don't want to rain on your parade, but I think you are working with false assumptions. The quoted JLS sentence says

For example, assume an annotation type TA which is meta-annotated with just Target(ElementType.TYPE_USE).

Note the "just" in there. All the annotations mentioned here and in the openrewrite issue are annotated with more than just TYPE_USE, so that sentence doesn't apply. To me the syntax remains illegal. Also ecj doesn't compile it, so it might be more pragmatic to change the original code.

@pappnase99
Copy link
Author

The org.eclipse.jdt.annotation.NonNull annotation has indeed @Target](value=TYPE_USE) set, so as I said earlier, this is not illegal code, it's a valid use case.

@Bananeweizen
Copy link

Sorry, my fault. You are right. Confused it with rewrites NonNull definition when I checked. :) The openrewrite PR with Deprecated would not fit IMO, however.

@BoykoAlex
Copy link
Contributor

BoykoAlex commented Nov 19, 2023

@Bananeweizen I have corrected the unit test in Rewrite to have annotation with TYPE_USE only:

        String annotationSource = """
            package example;
            
            import java.lang.annotation.ElementType;
            import java.lang.annotation.Retention;
            import java.lang.annotation.RetentionPolicy;
            import java.lang.annotation.Target;
            
            @Retention(RetentionPolicy.CLASS)
            @Target({ TYPE_USE })
            public @interface NonNull {
                // marker annotation with no members
            }
          """;
        String source = """
              package example;
              
              import example.NonNull;
              
              public class A {
                java.lang.@NonNull String a;
              }
              """;

If this still does not fir the purpose feel free to propose corrections :-)

@martinlippert
Copy link
Member

Moving this to the next release (4.21.1) while waiting for the fix to appear in open rewrite.

@BoykoAlex
Copy link
Contributor

Fixed in OR. Latest OR jar adopted with 8a74023 hence should be fixed. Please try in snapshots found on https://dist.springsource.com/snapshot/STS4/nightly-distributions.html

@pappnase99
Copy link
Author

Yeah tried v1.52.0-202401091454 and worked for me. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: eclipse something that is specific for Eclipse for: vscode something that is specific for VSCode theme: refactoring type: bug
Projects
None yet
Development

No branches or pull requests

4 participants