# HG changeset patch # User rfield # Date 1464897120 25200 # Node ID 37280d52d7231bcbb02ac4fe5b4e4ad04a92186a # Parent 0344e455d960b1962d4e8c8bc810496ff3c1b825 8131024: JShell: multi-line comment not detected as incomplete Reviewed-by: vromero diff -r 0344e455d960 -r 37280d52d723 langtools/src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java Thu Jun 02 15:39:10 2016 -0400 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java Thu Jun 02 12:52:00 2016 -0700 @@ -40,35 +40,52 @@ Stream.of( "public", "protected", "private", "static", "final" ) .collect( Collectors.toSet() ); + // Builder to accumulate non-masked characters private final StringBuilder sbCleared = new StringBuilder(); + + // Builder to accumulate masked characters private final StringBuilder sbMask = new StringBuilder(); + + // The input string private final String str; + + // Entire input string length private final int length; + + // Should leading modifiers be masked away private final boolean maskModifiers; + + // The next character private int next = 0; - private boolean wasMasked = false; + + // We have past any point where a top-level modifier could be private boolean inside = false; + // Does the string end with an unclosed '/*' style comment? + private boolean openComment = false; + @SuppressWarnings("empty-statement") - public MaskCommentsAndModifiers(String s, boolean maskModifiers) { + MaskCommentsAndModifiers(String s, boolean maskModifiers) { this.str = s; this.length = s.length(); this.maskModifiers = maskModifiers; do { } while (next()); } - public String cleared() { + String cleared() { return sbCleared.toString(); } - public String mask() { + String mask() { return sbMask.toString(); } - public boolean wasMasked() { - return wasMasked; + boolean endsWithOpenComment() { + return openComment; } + /****** private implementation methods ******/ + /** * Read the next character */ @@ -89,7 +106,6 @@ } private void writeMask(int ch) { - wasMasked = true; write(sbMask, ch); write(sbCleared, Character.isWhitespace(ch) ? ch : ' '); } @@ -147,6 +163,7 @@ int prevc = 0; while ((c = read()) != '/' || prevc != '*') { if (c < 0) { + openComment = true; return false; } writeMask(c); diff -r 0344e455d960 -r 37280d52d723 langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Thu Jun 02 15:39:10 2016 -0400 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Thu Jun 02 12:52:00 2016 -0700 @@ -130,6 +130,7 @@ import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; import static java.util.stream.Collectors.joining; +import static jdk.jshell.SourceCodeAnalysis.Completeness.DEFINITELY_INCOMPLETE; /** * The concrete implementation of SourceCodeAnalysis. @@ -165,6 +166,10 @@ @Override public CompletionInfo analyzeCompletion(String srcInput) { MaskCommentsAndModifiers mcm = new MaskCommentsAndModifiers(srcInput, false); + if (mcm.endsWithOpenComment()) { + proc.debug(DBG_COMPA, "Incomplete (open comment): %s\n", srcInput); + return new CompletionInfo(DEFINITELY_INCOMPLETE, srcInput.length(), null, srcInput + '\n'); + } String cleared = mcm.cleared(); String trimmedInput = Util.trimEnd(cleared); if (trimmedInput.isEmpty()) { diff -r 0344e455d960 -r 37280d52d723 langtools/test/jdk/jshell/CompletenessTest.java --- a/langtools/test/jdk/jshell/CompletenessTest.java Thu Jun 02 15:39:10 2016 -0400 +++ b/langtools/test/jdk/jshell/CompletenessTest.java Thu Jun 02 12:52:00 2016 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 8149524 + * @bug 8149524 8131024 * @summary Test SourceCodeAnalysis * @build KullaTesting TestingInputStream * @run testng CompletenessTest @@ -285,6 +285,11 @@ assertStatus("\"abc\\", UNKNOWN, "\"abc\\"); } + public void testOpenComment() { + assertStatus("int xx; /* hello", DEFINITELY_INCOMPLETE, null); + assertStatus("/** test", DEFINITELY_INCOMPLETE, null); + } + public void testMiscSource() { assertStatus("if (t) if ", DEFINITELY_INCOMPLETE, "if (t) if"); //Bug assertStatus("int m() {} dfd", COMPLETE, "int m() {}"); diff -r 0344e455d960 -r 37280d52d723 langtools/test/jdk/jshell/ToolSimpleTest.java --- a/langtools/test/jdk/jshell/ToolSimpleTest.java Thu Jun 02 15:39:10 2016 -0400 +++ b/langtools/test/jdk/jshell/ToolSimpleTest.java Thu Jun 02 12:52:00 2016 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 8153716 8143955 8151754 8150382 8153920 8156910 + * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 * @summary Simple jshell tool tests * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -61,6 +61,16 @@ ); } + public void testOpenComment() { + test( + (a) -> assertCommand(a, "int z = /* blah", ""), + (a) -> assertCommand(a, "baz */ 5", "z ==> 5"), + (a) -> assertCommand(a, "/** hoge ", ""), + (a) -> assertCommand(a, "baz **/", ""), + (a) -> assertCommand(a, "int v", "v ==> 0") + ); + } + public void oneLineOfError() { test( (a) -> assertCommand(a, "12+", null),