8167343: JShell: Completeness analysis infers an incomplete declaration as COMPLETE_WITH_SEMI, which is a first line of Allman style
Reviewed-by: rfield
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Fri Oct 07 20:48:39 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Tue Oct 11 00:28:49 2016 +0900
@@ -166,6 +166,7 @@
private static final int XTERM = 0b100000000; // Can terminate (last before EOF)
private static final int XSTART = 0b1000000000; // Boundary, must be XTERM before
private static final int XERRO = 0b10000000000; // Is an error
+ private static final int XBRACESNEEDED = 0b100000000000; // Expect {ANY} LBRACE
/**
* An extension of the compiler's TokenKind which adds our combined/processed
@@ -190,7 +191,7 @@
ERROR(TokenKind.ERROR, XERRO), //
IDENTIFIER(TokenKind.IDENTIFIER, XEXPR1|XDECL1|XTERM), //
UNDERSCORE(TokenKind.UNDERSCORE, XERRO), // _
- CLASS(TokenKind.CLASS, XEXPR|XDECL1), // class decl (MAPPED: DOTCLASS)
+ CLASS(TokenKind.CLASS, XEXPR|XDECL1|XBRACESNEEDED), // class decl (MAPPED: DOTCLASS)
MONKEYS_AT(TokenKind.MONKEYS_AT, XEXPR|XDECL1), // @
IMPORT(TokenKind.IMPORT, XDECL1|XSTART), // import -- consider declaration
SEMI(TokenKind.SEMI, XSTMT1|XTERM|XSTART), // ;
@@ -202,10 +203,10 @@
CUSTOM(TokenKind.CUSTOM, XERRO), // No uses
// Declarations
- ENUM(TokenKind.ENUM, XDECL1), // enum
+ ENUM(TokenKind.ENUM, XDECL1|XBRACESNEEDED), // enum
IMPLEMENTS(TokenKind.IMPLEMENTS, XDECL), // implements
- INTERFACE(TokenKind.INTERFACE, XDECL1), // interface
- THROWS(TokenKind.THROWS, XDECL), // throws
+ INTERFACE(TokenKind.INTERFACE, XDECL1|XBRACESNEEDED), // interface
+ THROWS(TokenKind.THROWS, XDECL|XBRACESNEEDED), // throws
// Primarive type names
BOOLEAN(TokenKind.BOOLEAN, XEXPR1|XDECL1), // boolean
@@ -381,6 +382,10 @@
return (belongs & XSTART) != 0;
}
+ boolean isBracesNeeded() {
+ return (belongs & XBRACESNEEDED) != 0;
+ }
+
/**
* After construction, check that all compiler TokenKind values have
* corresponding TK values.
@@ -641,7 +646,9 @@
public Completeness parseDeclaration() {
boolean isImport = token.kind == IMPORT;
+ boolean isBracesNeeded = false;
while (token.kind.isDeclaration()) {
+ isBracesNeeded |= token.kind.isBracesNeeded();
nextToken();
}
switch (token.kind) {
@@ -666,6 +673,9 @@
case SEMI:
return Completeness.COMPLETE;
case IDENTIFIER:
+ return isBracesNeeded
+ ? Completeness.DEFINITELY_INCOMPLETE
+ : Completeness.COMPLETE_WITH_SEMI;
case BRACKETS:
return Completeness.COMPLETE_WITH_SEMI;
case DOTSTAR:
--- a/langtools/test/jdk/jshell/CompletenessTest.java Fri Oct 07 20:48:39 2016 -0700
+++ b/langtools/test/jdk/jshell/CompletenessTest.java Tue Oct 11 00:28:49 2016 +0900
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8149524 8131024 8165211 8080071 8130454
+ * @bug 8149524 8131024 8165211 8080071 8130454 8167343
* @summary Test SourceCodeAnalysis
* @build KullaTesting TestingInputStream
* @run testng CompletenessTest
@@ -117,6 +117,7 @@
"bar: g()",
"baz: while (true) if (t()) printf('-'); else break baz",
"java.util.function.IntFunction<int[]> ggg = int[]::new",
+ "List<? extends Object> l",
};
static final String[] considered_incomplete = new String[] {
@@ -162,7 +163,19 @@
"enum TK { EOF(TokenKind.EOF, 0),",
"enum TK { EOF(TokenKind.EOF, 0), NEW_MIDDLE(XEXPR1|XTERM)",
"enum TK { EOF(TokenKind.EOF, 0), NEW_MIDDLE(XEXPR1|XTERM); ",
- "enum Tt { FOO, BAR, BAZ,;"
+ "enum Tt { FOO, BAR, BAZ,;",
+ "class C",
+ "class C extends D",
+ "class C implements D",
+ "class C implements D, E",
+ "interface I extends D",
+ "interface I extends D, E",
+ "enum E",
+ "enum E implements I1",
+ "enum E implements I1, I2",
+ "@interface Anno",
+ "void f()",
+ "void f() throws E",
};
static final String[] unknown = new String[] {