Skip to content

Commit 84425a6

Browse files
committed
8315452: Erroneous AST missing modifiers for partial input
Reviewed-by: vromero
1 parent 3094fd1 commit 84425a6

File tree

2 files changed

+64
-4
lines changed

2 files changed

+64
-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

+60-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
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 8310326 8312093 8312204
26+
* @bug 7073631 7159445 7156633 8028235 8065753 8205418 8205913 8228451 8237041 8253584 8246774 8256411 8256149 8259050 8266436 8267221 8271928 8275097 8293897 8295401 8304671 8310326 8312093 8312204 8315452
2727
* @summary tests error and diagnostics positions
2828
* @author Jan Lahoda
2929
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -60,6 +60,8 @@
6060
import com.sun.tools.javac.tree.JCTree;
6161
import java.io.IOException;
6262
import java.io.StringWriter;
63+
import java.io.UncheckedIOException;
64+
import java.io.Writer;
6365
import java.lang.annotation.ElementType;
6466
import java.lang.annotation.Retention;
6567
import java.lang.annotation.RetentionPolicy;
@@ -70,6 +72,7 @@
7072
import java.util.Arrays;
7173
import java.util.LinkedList;
7274
import java.util.List;
75+
import java.util.Objects;
7376
import java.util.regex.Pattern;
7477
import javax.lang.model.element.Modifier;
7578
import javax.lang.model.type.TypeKind;
@@ -88,7 +91,8 @@
8891
import com.sun.source.util.TreePathScanner;
8992
import com.sun.tools.javac.api.JavacTaskPool;
9093
import com.sun.tools.javac.api.JavacTaskPool.Worker;
91-
import java.util.Objects;
94+
import com.sun.tools.javac.tree.JCTree.JCErroneous;
95+
import com.sun.tools.javac.tree.Pretty;
9296

9397
public class JavacParserTest extends TestCase {
9498
static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
@@ -2486,6 +2490,28 @@ void main() {
24862490
codes);
24872491
}
24882492

2493+
@Test //JDK-8315452
2494+
void testPartialTopLevelModifiers() throws IOException {
2495+
String code = """
2496+
package test;
2497+
public
2498+
""";
2499+
DiagnosticCollector<JavaFileObject> coll =
2500+
new DiagnosticCollector<>();
2501+
JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll,
2502+
List.of("--enable-preview", "--source", SOURCE_VERSION),
2503+
null, Arrays.asList(new MyFileObject(code)));
2504+
CompilationUnitTree cut = ct.parse().iterator().next();
2505+
2506+
String result = toStringWithErrors(cut).replaceAll("\\R", "\n");
2507+
System.out.println("RESULT\n" + result);
2508+
assertEquals("incorrect AST",
2509+
result,
2510+
"""
2511+
package test;
2512+
(ERROR: public )""");
2513+
}
2514+
24892515
void run(String[] args) throws Exception {
24902516
int passed = 0, failed = 0;
24912517
final Pattern p = (args != null && args.length > 0)
@@ -2515,6 +2541,38 @@ void run(String[] args) throws Exception {
25152541
passed + ", failed = " + failed + " ??????????");
25162542
}
25172543
}
2544+
2545+
private String toStringWithErrors(Tree tree) {
2546+
StringWriter s = new StringWriter();
2547+
try {
2548+
new PrettyWithErrors(s, false).printExpr((JCTree) tree);
2549+
} catch (IOException e) {
2550+
// should never happen, because StringWriter is defined
2551+
// never to throw any IOExceptions
2552+
throw new AssertionError(e);
2553+
}
2554+
return s.toString();
2555+
}
2556+
2557+
private static final class PrettyWithErrors extends Pretty {
2558+
2559+
public PrettyWithErrors(Writer out, boolean sourceOutput) {
2560+
super(out, sourceOutput);
2561+
}
2562+
2563+
@Override
2564+
public void visitErroneous(JCErroneous tree) {
2565+
try {
2566+
print("(ERROR: ");
2567+
print(tree.errs);
2568+
print(")");
2569+
} catch (IOException e) {
2570+
throw new UncheckedIOException(e);
2571+
}
2572+
}
2573+
2574+
}
2575+
25182576
}
25192577

25202578
abstract class TestCase {

0 commit comments

Comments
 (0)