Skip to content

Commit aef25fc

Browse files
committed
8315452: Erroneous AST missing modifiers for partial input
Reviewed-by: asotona, vromero Backport-of: 84425a62904f84601affc9710eefece88665374a
1 parent 6e54e82 commit aef25fc

File tree

2 files changed

+65
-4
lines changed

2 files changed

+65
-4
lines changed

Diff for: src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -3918,7 +3918,7 @@ public JCTree.JCCompilationUnit parseCompilationUnit() {
39183918

39193919
boolean firstTypeDecl = true; // have we see a class, enum, or interface declaration yet?
39203920
boolean isUnnamedClass = false;
3921-
while (token.kind != EOF) {
3921+
OUTER: while (token.kind != EOF) {
39223922
if (token.pos <= endPosTable.errorEndPos) {
39233923
// error recovery
39243924
skip(firstTypeDecl, false, false, false);
@@ -3933,6 +3933,8 @@ public JCTree.JCCompilationUnit parseCompilationUnit() {
39333933
while (firstTypeDecl && mods == null && token.kind == SEMI) {
39343934
semiList.append(toP(F.at(token.pos).Skip()));
39353935
nextToken();
3936+
if (token.kind == EOF)
3937+
break OUTER;
39363938
}
39373939
if (firstTypeDecl && mods == null && token.kind == IMPORT) {
39383940
if (!semiList.isEmpty()) {
@@ -3999,7 +4001,7 @@ public JCTree.JCCompilationUnit parseCompilationUnit() {
39994001
checkSourceLevel(token.pos, Feature.UNNAMED_CLASSES);
40004002
defs.appendList(topLevelMethodOrFieldDeclaration(mods));
40014003
isUnnamedClass = true;
4002-
} else if (token.kind != EOF) {
4004+
} else {
40034005
JCTree def = typeDeclaration(mods, docComment);
40044006
if (def instanceof JCExpressionStatement statement)
40054007
def = statement.expr;

Diff for: test/langtools/tools/javac/parser/JavacParserTest.java

+61-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323

2424
/*
2525
* @test
26-
* @bug 7073631 7159445 7156633 8028235 8065753 8205418 8205913 8228451 8237041 8253584 8246774 8256411 8256149 8259050 8266436 8267221 8271928 8275097 8293897 8295401 8304671 8312093
26+
* @bug 7073631 7159445 7156633 8028235 8065753 8205418 8205913 8228451 8237041 8253584 8246774 8256411 8256149 8259050 8266436 8267221 8271928 8275097 8293897 8295401 8304671 8312093 8315452
27+
2728
* @summary tests error and diagnostics positions
2829
* @author Jan Lahoda
2930
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -60,6 +61,8 @@
6061
import com.sun.tools.javac.tree.JCTree;
6162
import java.io.IOException;
6263
import java.io.StringWriter;
64+
import java.io.UncheckedIOException;
65+
import java.io.Writer;
6366
import java.lang.annotation.ElementType;
6467
import java.lang.annotation.Retention;
6568
import java.lang.annotation.RetentionPolicy;
@@ -70,6 +73,7 @@
7073
import java.util.Arrays;
7174
import java.util.LinkedList;
7275
import java.util.List;
76+
import java.util.Objects;
7377
import java.util.regex.Pattern;
7478
import javax.lang.model.element.Modifier;
7579
import javax.lang.model.type.TypeKind;
@@ -88,7 +92,8 @@
8892
import com.sun.source.util.TreePathScanner;
8993
import com.sun.tools.javac.api.JavacTaskPool;
9094
import com.sun.tools.javac.api.JavacTaskPool.Worker;
91-
import java.util.Objects;
95+
import com.sun.tools.javac.tree.JCTree.JCErroneous;
96+
import com.sun.tools.javac.tree.Pretty;
9297

9398
public class JavacParserTest extends TestCase {
9499
static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
@@ -2423,6 +2428,28 @@ public Void visitMethod(MethodTree node, Void p) {
24232428
}.scan(cut, null);
24242429
}
24252430

2431+
@Test //JDK-8315452
2432+
void testPartialTopLevelModifiers() throws IOException {
2433+
String code = """
2434+
package test;
2435+
public
2436+
""";
2437+
DiagnosticCollector<JavaFileObject> coll =
2438+
new DiagnosticCollector<>();
2439+
JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll,
2440+
List.of("--enable-preview", "--source", SOURCE_VERSION),
2441+
null, Arrays.asList(new MyFileObject(code)));
2442+
CompilationUnitTree cut = ct.parse().iterator().next();
2443+
2444+
String result = toStringWithErrors(cut).replaceAll("\\R", "\n");
2445+
System.out.println("RESULT\n" + result);
2446+
assertEquals("incorrect AST",
2447+
result,
2448+
"""
2449+
package test;
2450+
(ERROR: public )""");
2451+
}
2452+
24262453
void run(String[] args) throws Exception {
24272454
int passed = 0, failed = 0;
24282455
final Pattern p = (args != null && args.length > 0)
@@ -2452,6 +2479,38 @@ void run(String[] args) throws Exception {
24522479
passed + ", failed = " + failed + " ??????????");
24532480
}
24542481
}
2482+
2483+
private String toStringWithErrors(Tree tree) {
2484+
StringWriter s = new StringWriter();
2485+
try {
2486+
new PrettyWithErrors(s, false).printExpr((JCTree) tree);
2487+
} catch (IOException e) {
2488+
// should never happen, because StringWriter is defined
2489+
// never to throw any IOExceptions
2490+
throw new AssertionError(e);
2491+
}
2492+
return s.toString();
2493+
}
2494+
2495+
private static final class PrettyWithErrors extends Pretty {
2496+
2497+
public PrettyWithErrors(Writer out, boolean sourceOutput) {
2498+
super(out, sourceOutput);
2499+
}
2500+
2501+
@Override
2502+
public void visitErroneous(JCErroneous tree) {
2503+
try {
2504+
print("(ERROR: ");
2505+
print(tree.errs);
2506+
print(")");
2507+
} catch (IOException e) {
2508+
throw new UncheckedIOException(e);
2509+
}
2510+
}
2511+
2512+
}
2513+
24552514
}
24562515

24572516
abstract class TestCase {

0 commit comments

Comments
 (0)