8131024: JShell: multi-line comment not detected as incomplete
authorrfield
Thu, 02 Jun 2016 12:52:00 -0700
changeset 38835 37280d52d723
parent 38834 0344e455d960
child 38836 b09d1cfbf28c
8131024: JShell: multi-line comment not detected as incomplete Reviewed-by: vromero
langtools/src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java
langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
langtools/test/jdk/jshell/CompletenessTest.java
langtools/test/jdk/jshell/ToolSimpleTest.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);
--- 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()) {
--- 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() {}");
--- 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),