apache / netbeans

Apache NetBeans
https://netbeans.apache.org/
Apache License 2.0
2.63k stars 840 forks source link

Fails to parse a file with incomplete switch expression #5090

Closed SBasalaev closed 1 month ago

SBasalaev commented 1 year ago

Apache NetBeans version

Apache NetBeans 16

What happened

When I add a case with a block to the switch expression, exception notification appears and completion stops working. If I try to save a file after that the whole application freezes.

How to reproduce

Suppose I have a class (requires JDK 17 with preview features enabled)

class Switch {
    public boolean test(Object value) {
        return switch (value) {
            default -> false;
        }
    }
}

Then I start adding a new case. The issue happens right after I type the opening brace

class Switch {
    public boolean test(Object value) {
        return switch (value) {
            case Boolean b -> {    // <- this line added
            default -> false;
        }
    }
}

Creating file with that contents does not always cause the issue but typing the line in editor always does. This also happened in previous versions of NetBeans and with previous JDK versions.

Did this work correctly in an earlier version?

No / Don't know

Operating System

Ubuntu Linux 22.04 amd64

JDK

OpenJDK 19 (system provided)

Apache NetBeans packaging

Apache NetBeans provided installer

Anything else

Stack trace reported by NetBeans

Caused: java.lang.NullPointerException: Cannot read field "type" because "tree" is null
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scanCond(Flow.java:2145)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitYield(Flow.java:2785)
    at com.sun.tools.javac.tree.JCTree$JCYield.accept(JCTree.java:1660)
    at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
    at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:447)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1861)
    at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scanSyntheticBreak(Flow.java:459)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.handleSwitch(Flow.java:2597)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitSwitchExpression(Flow.java:2565)
    at com.sun.tools.javac.tree.JCTree$JCSwitchExpression.accept(JCTree.java:1382)
    at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
    at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:447)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1861)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scanExpr(Flow.java:2118)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitReturn(Flow.java:2818)
    at com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1711)
    at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
    at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:447)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1861)
    at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:57)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitBlock(Flow.java:2402)
    at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1082)
    at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
    at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:447)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1861)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitMethodDef(Flow.java:2305)
    at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:912)
    at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
    at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:447)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1861)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitClassDef(Flow.java:2243)
    at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:810)
    at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
    at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:447)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:1861)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.analyzeTree(Flow.java:3031)
    at com.sun.tools.javac.comp.Flow$AssignAnalyzer.analyzeTree(Flow.java:3013)
    at com.sun.tools.javac.comp.Flow.analyzeTree(Flow.java:224)
    at com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1377)
    at com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1341)
    at com.sun.tools.javac.api.JavacTaskImpl.analyze(JavacTaskImpl.java:404)
    at com.sun.tools.javac.api.JavacTaskImpl.lambda$analyze$1(JavacTaskImpl.java:379)
    at com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
    at com.sun.tools.javac.api.JavacTaskImpl.analyze(JavacTaskImpl.java:379)
Caused: java.lang.IllegalStateException
    at com.sun.tools.javac.api.JavacTaskImpl.analyze(JavacTaskImpl.java:383)
    at org.netbeans.modules.java.source.parsing.JavacParser.moveToPhase(JavacParser.java:770)
    at org.netbeans.modules.java.source.parsing.JavacParser.getResult(JavacParser.java:540)
    at org.netbeans.modules.java.source.parsing.JavacParser.getResult(JavacParser.java:141)
    at org.netbeans.modules.parsing.impl.TaskProcessor.callGetResult(TaskProcessor.java:608)
    at org.netbeans.modules.parsing.impl.SourceCache.getResult(SourceCache.java:241)
    at org.netbeans.modules.parsing.impl.TaskProcessor$RequestPerformer.run(TaskProcessor.java:775)
    at org.openide.util.lookup.Lookups.executeWith(Lookups.java:279)
    at org.netbeans.modules.parsing.impl.TaskProcessor$RequestPerformer.execute(TaskProcessor.java:702)
[catch] at org.netbeans.modules.parsing.impl.TaskProcessor$CompilationJob.run(TaskProcessor.java:663)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:577)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
    at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1418)
    at org.netbeans.modules.openide.util.GlobalLookup.execute(GlobalLookup.java:45)
    at org.openide.util.lookup.Lookups.executeWith(Lookups.java:278)
    at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2033)

Are you willing to submit a pull request?

No

Code of Conduct

Yes

mbien commented 1 year ago

any on-save action enabled? Organize imports or formatting etc?

SBasalaev commented 1 year ago

Yes, "Remove unused imports". After disabling it I can save, so this is actually two separate issues.

mbien commented 1 year ago

right, just wanted to make sure this applies here too. The other issue is tracked under #4054.

neilcsmith-net commented 1 year ago

Is this still a valid issue?

Knusende-Ro commented 1 year ago

Yes, it's still a valid issue. I get exactly the same stack trace as SBasalaev. NetBeans 18 (binary from zip), Debian Bookworm (12.1), OpenJDK-17 (Debian supplied). LXDE desktop. Peter

mbien commented 11 months ago

i am wondering why issues like this don't show up when javac is ran from CLI. NPEs in javac seem to be more common now. Going to start using the https://github.com/apache/netbeans/labels/nb-javac label for issues like this. The good thing here is that we have a simple reproducer which other filed issues lack.

cc @lahodaj

mbien commented 4 months ago

checked and this is still reproducible with 22-rc1

updated trace since the line numbers moved:

``` Caused: java.lang.NullPointerException: Cannot read field "type" because "tree" is null at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scanCond(Flow.java:2293) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitYield(Flow.java:2913) at com.sun.tools.javac.tree.JCTree$JCYield.accept(JCTree.java:1677) at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50) at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2013) at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scanSyntheticBreak(Flow.java:475) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.handleSwitch(Flow.java:2725) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitSwitchExpression(Flow.java:2700) at com.sun.tools.javac.tree.JCTree$JCSwitchExpression.accept(JCTree.java:1399) at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50) at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2013) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scanExpr(Flow.java:2270) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitReturn(Flow.java:2946) at com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1728) at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50) at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2013) at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:58) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitBlock(Flow.java:2537) at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1092) at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50) at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2013) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitMethodDef(Flow.java:2440) at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:916) at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50) at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2013) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.visitClassDef(Flow.java:2384) at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:814) at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:50) at com.sun.tools.javac.comp.Flow$BaseAnalyzer.scan(Flow.java:463) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.scan(Flow.java:2013) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.analyzeTree(Flow.java:3174) at com.sun.tools.javac.comp.Flow$AssignAnalyzer.analyzeTree(Flow.java:3156) at com.sun.tools.javac.comp.Flow.analyzeTree(Flow.java:231) at com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1426) at com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1390) at com.sun.tools.javac.api.JavacTaskImpl.analyze(JavacTaskImpl.java:404) at com.sun.tools.javac.api.JavacTaskImpl.lambda$analyze$1(JavacTaskImpl.java:379) at com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152) at com.sun.tools.javac.api.JavacTaskImpl.analyze(JavacTaskImpl.java:379) Caused: java.lang.IllegalStateException at com.sun.tools.javac.api.JavacTaskImpl.analyze(JavacTaskImpl.java:383) at org.netbeans.modules.java.source.parsing.JavacParser.moveToPhase(JavacParser.java:765) at org.netbeans.modules.java.source.parsing.JavacParser.getResult(JavacParser.java:536) at org.netbeans.modules.java.source.parsing.JavacParser.getResult(JavacParser.java:140) at org.netbeans.modules.parsing.impl.TaskProcessor.callGetResult(TaskProcessor.java:608) at org.netbeans.modules.parsing.impl.SourceCache.getResult(SourceCache.java:241) at org.netbeans.modules.parsing.impl.TaskProcessor$RequestPerformer.run(TaskProcessor.java:775) at org.openide.util.lookup.Lookups.executeWith(Lookups.java:288) at org.netbeans.modules.parsing.impl.TaskProcessor$RequestPerformer.execute(TaskProcessor.java:702) [catch] at org.netbeans.modules.parsing.impl.TaskProcessor$CompilationJob.run(TaskProcessor.java:663) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1420) at org.netbeans.modules.openide.util.GlobalLookup.execute(GlobalLookup.java:45) at org.openide.util.lookup.Lookups.executeWith(Lookups.java:287) at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2035) ```
lahodaj commented 4 months ago

FWIW, I've filled: https://bugs.openjdk.org/browse/JDK-8331212 have a (potential) fix, will open a PR sometime soon.

mbien commented 1 month ago

the nb-javac update https://github.com/apache/netbeans/pull/7484 fixed this and is already testable in NB23rc1. There is no longer an exception and the errors are annotated as expected: image

closing