changeset 56489:61353bf4e96d string-tapas

Update to date
author jlaskey
date Mon, 03 Jun 2019 09:19:18 -0300
parents fef30a42d788
children f90b1c5baa1d
files src/java.base/share/classes/java/lang/String.java src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java src/jdk.compiler/share/classes/com/sun/tools/javac/parser/UnicodeReader.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties test/jdk/java/lang/String/Formatted.java test/jdk/java/lang/String/StripIndent.java test/jdk/java/lang/String/TranslateEscapes.java test/langtools/tools/javac/diags/examples/TextBlockCloseDelimiter.java test/langtools/tools/javac/diags/examples/TextBlockOpenDelimiter.java test/langtools/tools/javac/diags/examples/TextBlockWhitespace.java test/langtools/tools/javap/WhitespaceTest.java
diffstat 12 files changed, 442 insertions(+), 108 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/String.java	Thu May 30 19:51:24 2019 +0200
+++ b/src/java.base/share/classes/java/lang/String.java	Mon Jun 03 09:19:18 2019 -0300
@@ -2895,50 +2895,69 @@
     }
 
     /**
-     * Removes horizontal white space margins from the essential body of a
-     * Text Block originated string, while preserving relative indentation.
+     * Returns a string whose value is this string, with incidental
+     * {@linkplain Character#isWhitespace(int) white space} removed from
+     * the beginning and end of every line.
      * <p>
-     * This string is first conceptually separated into lines as if by
+     * Incidental {@linkplain Character#isWhitespace(int) white space}
+     * is often present in a text block to align the content with the opening
+     * delimiter. For example, in the following code, dots represent incidental
+     * {@linkplain Character#isWhitespace(int) white space}:
+     * <blockquote><pre>
+     * String html = """
+     * ..............&lt;html&gt;
+     * ..............    &lt;body&gt;
+     * ..............        &lt;p&gt;Hello, world&lt;/p&gt;
+     * ..............    &lt;/body&gt;
+     * ..............&lt;/html&gt;
+     * ..............""";
+     * </pre></blockquote>
+     * This method treats the incidental
+     * {@linkplain Character#isWhitespace(int) white space} as indentation to be
+     * stripped, producing a string that preserves the relative indentation of
+     * the content. Using | to visualize the start of each line of the string:
+     * <blockquote><pre>
+     * |&lt;html&gt;
+     * |    &lt;body&gt;
+     * |        &lt;p&gt;Hello, world&lt;/p&gt;
+     * |    &lt;/body&gt;
+     * |&lt;/html&gt;
+     * </pre></blockquote>
+     * First, the individual lines of this string are extracted as if by using
      * {@link String#lines()}.
      * <p>
-     * Then, the <i>minimum indentation</i> (min) is determined as follows. For
-     * each non-blank line (as defined by {@link String#isBlank()}), the
-     * leading {@link Character#isWhitespace(int) white space} characters are
-     * counted. The
-     * leading {@link Character#isWhitespace(int) white space} characters on
-     * the last line are are also counted even if blank.
-     * The <i>min</i> value is the smallest of these counts.
+     * Then, the <i>minimum indentation</i> (min) is determined as follows.
+     * For each non-blank line (as defined by {@link String#isBlank()}), the
+     * leading {@linkplain Character#isWhitespace(int) white space} characters are
+     * counted. The leading {@linkplain Character#isWhitespace(int) white space}
+     * characters on the last line are also counted even if
+     * {@linkplain String#isBlank() blank}. The <i>min</i> value is the smallest
+     * of these counts.
      * <p>
-     * For each non-blank line, <i>min</i> leading white space characters are
-     * removed. Each white space character is treated as a single character. In
-     * particular, the tab character {@code "\t"} (U+0009) is considered a
-     * single character; it is not expanded.
+     * For each {@linkplain String#isBlank() non-blank} line, <i>min</i> leading
+     * {@linkplain Character#isWhitespace(int) white space} characters are removed,
+     * and any trailing {@linkplain Character#isWhitespace(int) white space}
+     * characters are removed. {@linkplain String#isBlank() Blank} lines are
+     * replaced with the empty string.
+     *
      * <p>
-     * The trailing white space of each line is also removed.
-     * </p>
-     * <p>
-     * Each line is suffixed with a line feed character {@code "\n"} (U+000A),
-     * except for the last line. The last line is suffixed with a line feed
-     * character {@code "\n"} (U+000A) only if the original last line was blank.
-     * <p>
-     * Finally, the lines are concatenated into a single string and returned.
+     * Finally, the lines are joined into a new string, using the LF character
+     * {@code "\n"} (U+000A) to separate lines.
      *
      * @apiNote
      * This method's primary purpose is to shift a block of lines as far as
      * possible to the left, while preserving relative indentation. Lines
-     * that were indented the least will thus have no leading white space.
-     *
-     * Example:
-     * <blockquote><pre>
-     * String s = ("   This is the first line\n" +
-     *             "       This is the second line\n").stripIndent();
-     *
-     * returns
-     * This is the first line
-     *     This is the second line
-     * </pre></blockquote>
-     *
-     * @return string with margins removed and line terminators normalized
+     * that were indented the least will thus have no leading
+     * {@linkplain Character#isWhitespace(int) white space}.
+     *
+     * @implNote
+     * This method treats all {@linkplain Character#isWhitespace(int) white space}
+     * characters as having equal width. As long as the indentation on every
+     * line is consistently composed of the same character sequences, then the
+     * result will be as described above.
+     *
+     * @return string with incidental indentation removed and line
+     *         terminators normalized
      *
      * @see String#lines()
      * @see String#isBlank()
@@ -2947,8 +2966,8 @@
      *
      * @since 13
      *
-     * @deprecated  Preview feature associated with Text Blocks.
-     *              Use at your own risk.
+     * @deprecated  This method is associated with text blocks, a preview language feature.
+     *              Text blocks and/or this method may be changed or removed in a future release.
      */
     @Deprecated(forRemoval=true, since="13")
     public String stripIndent() {
@@ -2964,8 +2983,9 @@
             .map(line -> {
                 int firstNonWhitespace = line.indexOfNonWhitespace();
                 int lastNonWhitespace = line.lastIndexOfNonWhitespace();
+                int incidentalWhitespace = Math.min(outdent, firstNonWhitespace);
                 return firstNonWhitespace > lastNonWhitespace
-                    ? "" : line.substring(Math.min(outdent, firstNonWhitespace), lastNonWhitespace);
+                    ? "" : line.substring(incidentalWhitespace, lastNonWhitespace);
             })
             .collect(Collectors.joining("\n", "", optOut ? "\n" : ""));
     }
@@ -2985,16 +3005,15 @@
             outdent = Integer.min(outdent, lastLine.length());
         }
         return outdent;
-   }
+    }
 
     /**
-     * Translates all escape sequences in the string into characters
-     * represented by those escapes specified in section
-     * 3.10.6 of the <cite>The Java&trade; Language Specification</cite>.
+     * Returns a string whose value is this string, with escape sequences
+     * translated as if in a string literal.
      * <p>
      * Escape sequences are translated as follows;
      * <table class="plain">
-     *   <caption style="display:none">Escape sequences</caption>
+     *   <caption style="display:none">Translation</caption>
      *   <thead>
      *   <tr>
      *     <th scope="col">Escape</th>
@@ -3005,42 +3024,42 @@
      *   <tr>
      *     <td>{@code \u005Cb}</td>
      *     <td>backspace</td>
-     *     <td>{@code \u005Cu0008}</td>
+     *     <td>{@code U+0008}</td>
      *   </tr>
      *   <tr>
      *     <td>{@code \u005Ct}</td>
      *     <td>horizontal tab</td>
-     *     <td>{@code \u005Cu0009}</td>
+     *     <td>{@code U+0009}</td>
      *   </tr>
      *   <tr>
      *     <td>{@code \u005Cn}</td>
      *     <td>line feed</td>
-     *     <td>{@code \u005Cu000A}</td>
+     *     <td>{@code U+000A}</td>
      *   </tr>
      *   <tr>
      *     <td>{@code \u005Cf}</td>
      *     <td>form feed</td>
-     *     <td>{@code \u005Cu000C}</td>
+     *     <td>{@code U+000C}</td>
      *   </tr>
      *   <tr>
      *     <td>{@code \u005Cr}</td>
      *     <td>carriage return</td>
-     *     <td>{@code \u005Cu000D}</td>
+     *     <td>{@code U+000D}</td>
      *   </tr>
      *   <tr>
      *     <td>{@code \u005C"}</td>
      *     <td>double quote</td>
-     *     <td>{@code \u005Cu0022}</td>
+     *     <td>{@code U+0022}</td>
      *   </tr>
      *   <tr>
      *     <td>{@code \u005C'}</td>
      *     <td>single quote</td>
-     *     <td>{@code \u005Cu0027}</td>
+     *     <td>{@code U+0027}</td>
      *   </tr>
      *   <tr>
      *     <td>{@code \u005C\u005C}</td>
      *     <td>backslash</td>
-     *     <td>{@code \u005Cu005C}</td>
+     *     <td>{@code U+005C}</td>
      *   </tr>
      *   <tr>
      *     <td>{@code \u005C0 - \u005C377}</td>
@@ -3048,21 +3067,25 @@
      *     <td>code point equivalents</td>
      *   </tr>
      * </table>
-     * <p>
-     * Octal escapes \u005C0 - \u005C377 are translated to their code
-     * point equivalents.
-     *
-     * @throws MalformedEscapeException when an escape sequence is malformed.
-     *
-     * @return String with all escapes translated.
+     *
+     * @implNote
+     * This method does <em>not</em> translate Unicode escapes such as "{@code \u005cu2022}".
+     * Unicode escapes are translated by the Java compiler when reading input characters and
+     * are not part of the string literal specification.
+     *
+     * @throws IllegalArgumentException when an escape sequence is malformed.
+     *
+     * @return String with escape sequences translated.
+     *
+     * @jls 3.10.7 Escape Sequences
      *
      * @since 13
      *
-     * @deprecated  Preview feature associated with Text Blocks.
-     *              Use at your own risk.
+     * @deprecated  This method is associated with text blocks, a preview language feature.
+     *              Text blocks and/or this method may be changed or removed in a future release.
      */
     @Deprecated(forRemoval=true, since="13")
-    public String translateEscapes() throws MalformedEscapeException {
+    public String translateEscapes() {
         if (isEmpty()) {
             return "";
         }
@@ -3091,34 +3114,30 @@
                     ch = '\t';
                     break;
                 case '\'':
-                    ch = '\'';
-                    break;
                 case '\"':
-                    ch = '\"';
-                    break;
                 case '\\':
-                    // ch = '\\';
+                    // as is
                     break;
                 case '0': case '1': case '2': case '3':
                 case '4': case '5': case '6': case '7':
-                    int limit = ch <= '3' ? 2 : 1;
-                    int code = Character.digit(ch, 8);
-                    for (int i = 0; i < limit && from < length; i++) {
+                    int limit = Integer.min(from + (ch <= '3' ? 2 : 1), length);
+                    int code = ch - '0';
+                    while (from < limit) {
                         ch = chars[from];
-                        int digit = Character.digit(ch, 8);
-                        if (digit < 0) {
+                        if (ch < '0' || '7' < ch) {
                             break;
                         }
                         from++;
-                        code = code << 3 | digit;
-                    }
-                    if (0377 < code) {
-                        throw new MalformedEscapeException(from);
+                        code = (code << 3) | (ch - '0');
                     }
                     ch = (char)code;
                     break;
-                default:
-                    throw new MalformedEscapeException(from);
+                default: {
+                    String msg = String.format(
+                        "Invalid escape sequence: \\%c \\\\u%04X",
+                        ch, (int)ch);
+                    throw new IllegalArgumentException(msg);
+                }
                 }
             }
 
@@ -3291,6 +3310,30 @@
     }
 
     /**
+     * Formats using this string as the format string, and the supplied
+     * arguments.
+     *
+     * @implSpec This method is equivalent to {@code String.format(this, args)}.
+     *
+     * @param  args
+     *         Arguments referenced by the format specifiers in this string.
+     *
+     * @return  A formatted string
+     *
+     * @see  java.lang.String#format(String,Object...)
+     * @see  java.util.Formatter
+     *
+     * @since 13
+     *
+     * @deprecated  This method is associated with text blocks, a preview language feature.
+     *              Text blocks and/or this method may be changed or removed in a future release.
+     */
+    @Deprecated(forRemoval=true, since="13")
+    public String formatted(Object... args) {
+        return new Formatter().format(this, args).toString();
+    }
+
+    /**
      * Returns the string representation of the {@code Object} argument.
      *
      * @param   obj   an {@code Object}.
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Thu May 30 19:51:24 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java	Mon Jun 03 09:19:18 2019 -0300
@@ -34,8 +34,9 @@
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
 import com.sun.tools.javac.util.*;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
+import com.sun.tools.javac.util.JCDiagnostic.*;
 
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.nio.CharBuffer;
 
@@ -168,8 +169,9 @@
         errPos = pos;
     }
 
-    protected void lexWarning(int pos, JCDiagnostic.Warning key) {
-        log.warning(pos, key);
+    protected void lexWarning(LintCategory lc, int pos, JCDiagnostic.Warning key) {
+        DiagnosticPosition dp = new SimpleDiagnosticPosition(pos) ;
+        log.warning(lc, dp, key);
     }
 
     /** Read next character in character or string literal and copy into sbuf.
@@ -223,7 +225,8 @@
     }
 
     /** Read next character in character or string literal and copy into sbuf
-     * without translating escapes.
+     *  without translating escapes. Used by text blocks to preflight verify
+     *  escapes sequences.
      */
     private void scanLitCharRaw(int pos) {
         if (reader.ch == '\\') {
@@ -245,6 +248,7 @@
                         }
                     }
                     break;
+                // Effectively list of valid escape sequences.
                 case 'b':
                 case 't':
                 case 'n':
@@ -263,48 +267,77 @@
         }
     }
 
+    /** Interim access to String methods used to support text blocks.
+     *  Required to handle bootstrapping with pre-text block jdks.
+     *  Could be reworked in the 'next' jdk.
+     */
     static class TextBlockSupport {
+        /** Reflection method to remove incidental indentation.
+         */
         private static final Method stripIndent;
+
+        /** Reflection method to translate escape sequences.
+         */
         private static final Method translateEscapes;
+
+        /** true if stripIndent and translateEscapes are available in the bootstrap jdk.
+         */
         private static final boolean hasSupport;
 
-        private static Method getStringMethod(String name) {
+        /** Get a string method via refection or null if not available.
+         */
+        private static Method getStringMethodOrNull(String name) {
             try {
                 return String.class.getMethod(name);
             } catch (Exception ex) {
-                // Bootstrapping issue, do nothing.
+                // Method not available, return null.
             }
             return null;
         }
 
         static {
-            stripIndent = getStringMethod("stripIndent");
-            translateEscapes = getStringMethod("translateEscapes");
+            // Get text block string methods.
+            stripIndent = getStringMethodOrNull("stripIndent");
+            translateEscapes = getStringMethodOrNull("translateEscapes");
+            // true if stripIndent and translateEscapes are available in the bootstrap jdk.
             hasSupport = stripIndent != null && translateEscapes != null;
         }
 
+        /** Return true if stripIndent and translateEscapes are available in the bootstrap jdk.
+         */
         static boolean hasSupport() {
             return hasSupport;
         }
 
+        /** Return the leading whitespace count (indentation) of the line.
+         */
         private static int indent(String line) {
             return line.length() - line.stripLeading().length();
         }
 
+        /** Verify that the incidental indentation of all lines in the string
+         *  is identical.
+         */
         static boolean checkIncidentalWhitespace(String string) {
+            // No need to check empty strings.
             if (string.isEmpty()) {
                 return true;
             }
+            // No need to check if opting out (last line is empty.)
             char lastChar = string.charAt(string.length() - 1);
             boolean optOut = lastChar == '\n' || lastChar == '\r';
             if (optOut)       {
                 return true;
             }
+            // Split string based at line terminators.
             String[] lines = string.split("\\R");
             int length = lines.length;
+            // Prime with the last line indentation (may be blank.)
             String lastLine = lines[length - 1];
+            // Maximum common indentation.
             int outdent = indent(lastLine);
             for (String line : lines) {
+                // Blanks lines have no influence (last line accounted.)
                 if (!line.isBlank()) {
                     outdent = Integer.min(outdent, indent(line));
                     if (outdent == 0) {
@@ -312,9 +345,12 @@
                     }
                 }
             }
+            // If any line has no indentation then same as opting out.
             if (outdent != 0) {
+                // Last line is representative.
                 String start = lastLine.substring(0, outdent);
                 for (String line : lines) {
+                    // Fail if a line does not have the same indentation.
                     if (!line.isBlank() && !line.startsWith(start)) {
                         return false;
                     }
@@ -323,20 +359,24 @@
             return true;
         }
 
+        /** Invoke String::stripIndent through reflection.
+         */
         static String stripIndent(String string) {
             try {
                 string = (String)stripIndent.invoke(string);
-            } catch (Exception ex) {
-                // Bootstrapping issue, do nothing.
+            } catch (InvocationTargetException | IllegalAccessException ex) {
+                throw new RuntimeException(ex);
             }
             return string;
         }
 
+        /** Invoke String::translateEscapes through reflection.
+         */
         static String translateEscapes(String string) {
             try {
                 string = (String)translateEscapes.invoke(string);
-            } catch (Exception ex) {
-                // Bootstrapping issue, do nothing.
+            } catch (InvocationTargetException | IllegalAccessException ex) {
+                throw new RuntimeException(ex);
             }
             return string;
         }
@@ -364,23 +404,34 @@
         return count;
     }
 
-    /** Scan a string literal.
+    /** Scan a string literal or text block.
      */
-    private void scanStringLiteral(int pos) {
+    private void scanString(int pos) {
+        // Clear flags.
+        shouldStripIndent = false;
+        shouldTranslateEscapes = false;
+        // Check if text block string methods are present.
         boolean hasTextBlockSupport = TextBlockSupport.hasSupport();
+        // Track the end of first line for error recovery.
         int firstEOLN = -1;
+        // Attempt to scan for up to 3 double quotes.
         int openCount = countChar('\"', 3);
         switch (openCount) {
-        case 1: // traditional string
+        case 1: // Starting a string literal.
             break;
-        case 2: // empty string
+        case 2: // Starting an empty string literal.
+            // Start again but only consume one quote.
             reader.reset(pos);
             openCount = countChar('\"', 1);
             break;
-        case 3: // text block
+        case 3: // Starting a text block.
+            // Check if preview feature is enabled for text blocks.
             checkSourceLevel(pos, Feature.TEXT_BLOCKS);
+            // Only proceed if text block string methods are present.
             if (hasTextBlockSupport) {
+                // Indicate that the final string should have incidental indentation removed.
                 shouldStripIndent = true;
+                // Verify the open delimiter sequence.
                 boolean hasOpenEOLN = false;
                 while (reader.bp < reader.buflen && Character.isWhitespace(reader.ch)) {
                     hasOpenEOLN = isEOLN();
@@ -389,54 +440,75 @@
                     }
                     reader.scanChar();
                 }
+                // Error if the open delimiter sequence not is """<Whitespace>*<LineTerminator>.
                 if (!hasOpenEOLN) {
                     lexError(reader.bp, Errors.IllegalTextBlockOpen);
                     return;
                 }
+                // Skip line terminator.
+                int start = reader.bp;
                 if (isCRLF()) {
                     reader.scanChar();
                 }
                 reader.scanChar();
+                processLineTerminator(start, reader.bp);
             } else {
+                // No text block string methods are present, so reset and treat like string literal.
                 reader.reset(pos);
                 openCount = countChar('\"', 1);
             }
             break;
         }
+        // While characters are available.
         while (reader.bp < reader.buflen) {
+            // If possible close delimiter sequence.
             if (reader.ch == '\"') {
+                // Check to see if enough double quotes are present.
                 int closeCount = countChar('\"', openCount);
                 if (openCount == closeCount) {
+                    // Good result.
                     tk = Tokens.TokenKind.STRINGLITERAL;
                     return;
                 }
+                // False alarm, add double quotes to string buffer.
                 reader.repeat('\"', closeCount);
             } else if (isEOLN()) {
+                // Line terminator in string literal is an error.
+                // Fall out to unclosed string literal error.
                 if (openCount == 1) {
                     break;
                 }
-                if (firstEOLN == -1) {
-                    firstEOLN = reader.bp;
-                }
+                 // Add line terminator to string buffer.
                 int start = reader.bp;
                 if (isCRLF()) {
                     reader.scanChar();
                 }
                 reader.putChar('\n', true);
                 processLineTerminator(start, reader.bp);
+                // Record first line terminator for error recovery.
+                if (firstEOLN == -1) {
+                    firstEOLN = reader.bp;
+                }
             } else if (reader.ch == '\\') {
+                // Handle escape sequences.
                 if (hasTextBlockSupport) {
+                    // Indicate that the final string should have escapes translated.
                     shouldTranslateEscapes = true;
+                    // Validate escape sequence and add to string buffer.
                     scanLitCharRaw(pos);
                 } else {
+                    // Translate escape sequence and add result to string buffer.
                     scanLitChar(pos);
                 }
             } else {
+                // Add character to string buffer.
                 reader.putChar(true);
             }
         }
-        lexError(pos, Errors.UnclosedStrLit);
+        // String ended without close delimiter sequence.
+        lexError(pos, openCount == 1 ? Errors.UnclosedStrLit : Errors.UnclosedTextBlock);
         if (firstEOLN  != -1) {
+            // Reset recovery position to point after open delimiter sequence.
             reader.reset(firstEOLN);
         }
     }
@@ -877,7 +949,7 @@
                     }
                     break loop;
                 case '\"':
-                    scanStringLiteral(pos);
+                    scanString(pos);
                     break loop;
                 default:
                     if (isSpecial(reader.ch)) {
@@ -929,19 +1001,24 @@
                 case DEFAULT: return new Token(tk, pos, endPos, comments);
                 case NAMED: return new NamedToken(tk, pos, endPos, name, comments);
                 case STRING: {
+                    // Get characters from string buffer.
                     String string = reader.chars();
+                    // If a text block.
                     if (shouldStripIndent) {
+                        // Verify that the incidental indentation is consistent.
                         if (lint.isEnabled(LintCategory.TEXT_BLOCKS) &&
                             !TextBlockSupport.checkIncidentalWhitespace(string)) {
-                            lexWarning(pos, Warnings.IncidentalWhitespaceInconsistent);
+                            lexWarning(LintCategory.TEXT_BLOCKS, pos,
+                                       Warnings.InconsistentWhiteSpaceIndentation);
                         }
+                        // Remove incidental indentation.
                         string = TextBlockSupport.stripIndent(string);
-                        shouldStripIndent = false;
                     }
+                    // Translate escape sequences if present.
                     if (shouldTranslateEscapes) {
                         string = TextBlockSupport.translateEscapes(string);
-                        shouldTranslateEscapes = false;
                     }
+                    // Build string token.
                     return new StringToken(tk, pos, endPos, string, comments);
                 }
                 case NUMERIC: return new NumericToken(tk, pos, endPos, reader.chars(), radix, comments);
@@ -964,7 +1041,6 @@
                     comments.prepend(comment);
         }
 
-
     /** Return the position where a lexical error occurred;
      */
     public int errPos() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/UnicodeReader.java	Thu May 30 19:51:24 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/UnicodeReader.java	Mon Jun 03 09:19:18 2019 -0300
@@ -154,12 +154,16 @@
         return new String(sbuf, 0, sp);
     }
 
+    /** Add 'count' copies of the character 'ch' to the string buffer.
+     */
     protected void repeat(char ch, int count) {
         for ( ; 0 < count; count--) {
             putChar(ch, false);
         }
     }
 
+    /** Reset the scan buffer pointer to 'pos'.
+     */
     protected void reset(int pos) {
         bp = pos - 1;
         scanChar();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu May 30 19:51:24 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Jun 03 09:19:18 2019 -0300
@@ -626,7 +626,7 @@
 compiler.err.illegal.text.block.open=\
     illegal text block open delimiter sequence, missing line terminator
 
-compiler.warn.incidental.whitespace.inconsistent=\
+compiler.warn.inconsistent.white.space.indentation=\
     inconsistent white space indentation
 
 compiler.err.illegal.nonascii.digit=\
@@ -1250,6 +1250,9 @@
 compiler.err.unclosed.str.lit=\
     unclosed string literal
 
+compiler.err.unclosed.text.block=\
+    unclosed text block
+
 # 0: string
 compiler.err.unsupported.encoding=\
     unsupported encoding: {0}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties	Thu May 30 19:51:24 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties	Mon Jun 03 09:19:18 2019 -0300
@@ -243,6 +243,9 @@
 javac.opt.Xlint.desc.static=\
     Warn about accessing a static member using an instance.
 
+javac.opt.Xlint.desc.text-blocks=\
+    Warn about inconsistent white space characters in text block indentation.
+
 javac.opt.Xlint.desc.try=\
     Warn about issues relating to use of try blocks (i.e. try-with-resources).
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/String/Formatted.java	Mon Jun 03 09:19:18 2019 -0300
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Unit tests for instance versions of String#format
+ * @run main Formatted
+ */
+
+import java.util.Locale;
+
+public class Formatted {
+    public static void main(String[] args) {
+        test1();
+    }
+
+    /*
+     * Test String#formatted(Object... args) functionality.
+     */
+    static void test1() {
+        check("formatted(Object... args)",
+                "Test this %s".formatted("and that"),
+                String.format("Test this %s", "and that"));
+    }
+
+    static void check(String test, String output, String expected) {
+        if (output != expected && (output == null || !output.equals(expected))) {
+            System.err.println("Testing " + test + ": unexpected result");
+            System.err.println("Output: " + output);
+            System.err.println("Expected: " + expected);
+            throw new RuntimeException();
+        }
+    }
+}
--- a/test/jdk/java/lang/String/StripIndent.java	Thu May 30 19:51:24 2019 +0200
+++ b/test/jdk/java/lang/String/StripIndent.java	Mon Jun 03 09:19:18 2019 -0300
@@ -24,7 +24,7 @@
 /*
  * @test
  * @summary This exercises String#stripIndent patterns and limits.
- * @run main/othervm -Xmx2g StripIndent
+ * @run main StripIndent
  */
 
 public class StripIndent {
--- a/test/jdk/java/lang/String/TranslateEscapes.java	Thu May 30 19:51:24 2019 +0200
+++ b/test/jdk/java/lang/String/TranslateEscapes.java	Mon Jun 03 09:19:18 2019 -0300
@@ -24,12 +24,14 @@
 /*
  * @test
  * @summary This exercises String#translateEscapes patterns and limits.
- * @run main/othervm -Xmx2g TranslateEscapes
+ * @run main TranslateEscapes
  */
 
 public class TranslateEscapes {
     public static void main(String... arg) {
         test1();
+        test2();
+        test3();
     }
 
     /*
@@ -46,6 +48,31 @@
         verifyEscape("\\", '\\');
     }
 
+    /*
+     * Octal escapes.
+     */
+    static void test2() {
+        verifyOctalEscape("0", 0);
+        verifyOctalEscape("3", 03);
+        verifyOctalEscape("7", 07);
+        verifyOctalEscape("07", 07);
+        verifyOctalEscape("17", 017);
+        verifyOctalEscape("27", 027);
+        verifyOctalEscape("37", 037);
+        verifyOctalEscape("377", 0377);
+
+        verifyOctalEscape("777", 077);
+        verifyOctalEscape("78", 07);
+    }
+
+    /*
+     * Exceptions.
+     */
+    static void test3() {
+        exceptionThrown("+");
+        exceptionThrown("\n");
+    }
+
     static void verifyEscape(String string, char ch) {
         String escapes = "\\" + string;
         if (escapes.translateEscapes().charAt(0) != ch) {
@@ -53,4 +80,24 @@
             throw new RuntimeException();
         }
     }
+
+    static void verifyOctalEscape(String string, int octal) {
+        String escapes = "\\" + string;
+        if (escapes.translateEscapes().charAt(0) != octal) {
+            System.err.format("\"%s\" not octal %o%n", string, octal);
+            throw new RuntimeException();
+        }
+    }
+
+    static void exceptionThrown(String string) {
+        String escapes = "\\" + string;
+        try {
+            escapes.translateEscapes();
+            System.err.format("escape not thrown for %s%n", string);
+            throw new RuntimeException();
+
+        } catch (IllegalArgumentException ex) {
+            // okay
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/TextBlockCloseDelimiter.java	Mon Jun 03 09:19:18 2019 -0300
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ // key: compiler.warn.preview.feature.use.plural
+ // key: compiler.misc.feature.text.blocks
+ // key: compiler.err.unclosed.text.block
+ // options: --enable-preview -source 13 -Xlint:preview
+
+class TextBlockCloseDelimiter {
+    String m() {
+        return """
+               ;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/TextBlockOpenDelimiter.java	Mon Jun 03 09:19:18 2019 -0300
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ // key: compiler.warn.preview.feature.use.plural
+ // key: compiler.misc.feature.text.blocks
+ // key: compiler.err.illegal.text.block.open
+ // options: --enable-preview -source 13 -Xlint:preview
+
+class TextBlockOpenDelimiter {
+    String m() {
+        return """xxxx
+               """;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/diags/examples/TextBlockWhitespace.java	Mon Jun 03 09:19:18 2019 -0300
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ // key: compiler.warn.preview.feature.use.plural
+ // key: compiler.misc.feature.text.blocks
+ // key: compiler.warn.inconsistent.white.space.indentation
+ // options: --enable-preview -source 13 -Xlint:preview,text-blocks
+
+class TextBlockWhitespace {
+    String m() {
+        return """
+\u0009\u0009\u0009\u0009tab indentation
+\u0020\u0020\u0020\u0020space indentation
+\u0020\u0020\u0020\u0020""";
+    }
+}
--- a/test/langtools/tools/javap/WhitespaceTest.java	Thu May 30 19:51:24 2019 +0200
+++ b/test/langtools/tools/javap/WhitespaceTest.java	Mon Jun 03 09:19:18 2019 -0300
@@ -37,8 +37,8 @@
     }
 
     void run() throws Exception {
-        test("-v", "java.lang.String");
-        test("-XDtab:1", "-v", "java.lang.String");
+        test("-v", "java.lang.Object");
+        test("-XDtab:1", "-v", "java.lang.Object");
 
         String testClasses = System.getProperty("test.classes");
         for (int i = 10; i < 40; i++)