8223782: jshell parser should handle Text Blocks
authorjlahoda
Fri, 07 Jun 2019 10:09:41 +0200
changeset 55280 d868727d8f0b
parent 55279 d59aec2ead21
child 55281 eaa1e236f305
8223782: jshell parser should handle Text Blocks Summary: Completion analysis should detect text blocks properly. Reviewed-by: jlaskey, rfield
src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java
test/langtools/jdk/jshell/CompletenessTest.java
test/langtools/jdk/jshell/CompletionSuggestionTest.java
--- a/src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java	Thu Jun 06 09:30:00 2019 +0200
+++ b/src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java	Fri Jun 07 10:09:41 2019 +0200
@@ -139,10 +139,36 @@
         }
     }
 
+    @SuppressWarnings("fallthrough")
     private void next() {
         switch (c) {
-            case '\'':
             case '"': {
+                int pos = next - 1;
+                maskModifiers = false;
+                if (str.startsWith("\"\"\"", next - 1)) {
+                    //text block/multi-line string literal:
+                    int searchPoint = next + 2;
+                    int end;
+                    while ((end = str.indexOf("\"\"\"", searchPoint)) != (-1)) {
+                        if (str.charAt(end - 1) != '\\')
+                            break;
+                        searchPoint = end + 1;
+                    }
+                    if (end == (-1)) {
+                        openToken = true;
+                        end = str.length();
+                    } else {
+                        end += 3;
+                    }
+                    write(c);
+                    while (next < end) {
+                        write(read());
+                    }
+                    break;
+                }
+            }
+            //intentional fall-through:
+            case '\'': {
                 maskModifiers = false;
                 write(c);
                 int match = c;
@@ -155,37 +181,6 @@
                 write(c); // write match // line-end
                 break;
             }
-            case '`': { // RawString
-                maskModifiers = false;
-                int backtickCount = 0;
-                do {
-                    write(c);
-                    ++backtickCount;
-                    read();
-                } while (c == '`');
-                while (true) {
-                    if (c == '`') {
-                        int cnt = 0;
-                        do {
-                            write(c);
-                            ++cnt;
-                            read();
-                        } while (c == '`');
-                        if (cnt == backtickCount) {
-                            unread();
-                            break;
-                        }
-                    } else {
-                        write(c);
-                        if (c < 0) {
-                            openToken = true;
-                            break;
-                        }
-                        read();
-                    }
-                }
-                break;
-            }
             case '/':
                 read();
                 switch (c) {
--- a/test/langtools/jdk/jshell/CompletenessTest.java	Thu Jun 06 09:30:00 2019 +0200
+++ b/test/langtools/jdk/jshell/CompletenessTest.java	Fri Jun 07 10:09:41 2019 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8149524 8131024 8165211 8080071 8130454 8167343 8129559 8114842 8182268
+ * @bug 8149524 8131024 8165211 8080071 8130454 8167343 8129559 8114842 8182268 8223782
  * @summary Test SourceCodeAnalysis
  * @build KullaTesting TestingInputStream
  * @run testng CompletenessTest
@@ -328,6 +328,18 @@
         assertStatus("/**  test", DEFINITELY_INCOMPLETE, null);
     }
 
+    public void testTextBlocks() {
+        assertStatus("\"\"\"", DEFINITELY_INCOMPLETE, null);
+        assertStatus("\"\"\"broken", DEFINITELY_INCOMPLETE, null);
+        assertStatus("\"\"\"\ntext", DEFINITELY_INCOMPLETE, null);
+        assertStatus("\"\"\"\ntext\"\"", DEFINITELY_INCOMPLETE, "\"\"\"\ntext\"\"\"");
+        assertStatus("\"\"\"\ntext\"\"\"", COMPLETE, "\"\"\"\ntext\"\"\"");
+        assertStatus("\"\"\"\ntext\\\"\"\"\"", COMPLETE, "\"\"\"\ntext\\\"\"\"\"");
+        assertStatus("\"\"\"\ntext\\\"\"\"", DEFINITELY_INCOMPLETE, null);
+        assertStatus("\"\"\"\ntext\\\"\"\"\\\"\"\"", DEFINITELY_INCOMPLETE, null);
+        assertStatus("\"\"\"\ntext\\\"\"\"\\\"\"\"\"\"\"", COMPLETE, "\"\"\"\ntext\\\"\"\"\\\"\"\"\"\"\"");
+    }
+
     public void testMiscSource() {
         assertStatus("if (t) if ", DEFINITELY_INCOMPLETE, "if (t) if"); //Bug
         assertStatus("int m() {} dfd", COMPLETE, "int m() {}");
--- a/test/langtools/jdk/jshell/CompletionSuggestionTest.java	Thu Jun 06 09:30:00 2019 +0200
+++ b/test/langtools/jdk/jshell/CompletionSuggestionTest.java	Fri Jun 07 10:09:41 2019 +0200
@@ -107,6 +107,8 @@
         assertCompletionIncludesExcludes("new C() {}.|",
                 new HashSet<>(Arrays.asList("method()", "number")),
                 new HashSet<>(Arrays.asList("D", "E", "F", "H", "class")));
+        assertCompletion("\"\".leng|", "length()");
+        assertCompletion("\"\"\"\n\"\"\".leng|", "length()");
     }
 
     public void testStartOfExpression() {