OpenJDK / amber / amber
changeset 56489:61353bf4e96d string-tapas
Update to date
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 = """ + * ..............<html> + * .............. <body> + * .............. <p>Hello, world</p> + * .............. </body> + * ..............</html> + * .............."""; + * </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> + * |<html> + * | <body> + * | <p>Hello, world</p> + * | </body> + * |</html> + * </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™ 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++)