diff --git a/java/com/google/turbine/parse/StreamLexer.java b/java/com/google/turbine/parse/StreamLexer.java index 6ae5319..a14b826 100644 --- a/java/com/google/turbine/parse/StreamLexer.java +++ b/java/com/google/turbine/parse/StreamLexer.java @@ -415,24 +415,17 @@ public Token next() { } readFrom(); StringBuilder sb = new StringBuilder(); - Token stringToken = Token.STRING_LITERAL; STRING: while (true) { switch (ch) { case '\\': eat(); - if (ch == '{') { - eat(); - stringTemplate(sb); - stringToken = Token.STRING_TEMPLATE; - } else { - sb.append(escape()); - } + sb.append(escape()); continue STRING; case '"': saveValue(sb.toString()); eat(); - return stringToken; + return Token.STRING_LITERAL; case '\n': throw error(ErrorKind.UNTERMINATED_STRING); case ASCII_SUB: @@ -457,29 +450,6 @@ public Token next() { } } - // String templates aren't compile-time constants, so they don't affect the API. Advance through - // the entire template, dropping any contained \{ ... }, and tokenize it as a single string - // literal. - private void stringTemplate(StringBuilder sb) { - sb.append("{}"); - int depth = 1; - while (depth > 0) { - Token next = next(); - switch (next) { - case LBRACE: - depth++; - break; - case RBRACE: - depth--; - break; - case EOF: - return; - default: - break; - } - } - } - private Token textBlock() { OUTER: while (true) { @@ -508,7 +478,6 @@ private Token textBlock() { } readFrom(); StringBuilder sb = new StringBuilder(); - Token stringToken = Token.STRING_LITERAL; while (true) { switch (ch) { case '"': @@ -527,23 +496,17 @@ private Token textBlock() { value = stripIndent(value); value = translateEscapes(value); saveValue(value); - return stringToken; + return Token.STRING_LITERAL; case '\\': // Escapes are handled later (after stripping indentation), but we need to ensure // that \" escapes don't count towards the closing delimiter of the text block. + sb.appendCodePoint(ch); eat(); - if (ch == '{') { - eat(); - stringTemplate(sb); - stringToken = Token.STRING_TEMPLATE; - } else { - sb.append('\\'); - if (ch == ASCII_SUB && reader.done()) { - return Token.EOF; - } - sb.appendCodePoint(ch); - eat(); + if (ch == ASCII_SUB && reader.done()) { + return Token.EOF; } + sb.appendCodePoint(ch); + eat(); continue; case ASCII_SUB: if (reader.done()) { diff --git a/java/com/google/turbine/parse/Token.java b/java/com/google/turbine/parse/Token.java index d5653c5..ec214a5 100644 --- a/java/com/google/turbine/parse/Token.java +++ b/java/com/google/turbine/parse/Token.java @@ -39,7 +39,6 @@ public enum Token { DOUBLE_LITERAL(""), CHAR_LITERAL(""), STRING_LITERAL(""), - STRING_TEMPLATE(""), AT("@"), EQ("=="), ASSIGN("="), diff --git a/javatests/com/google/turbine/lower/LowerIntegrationTest.java b/javatests/com/google/turbine/lower/LowerIntegrationTest.java index c54311f..234cd1c 100644 --- a/javatests/com/google/turbine/lower/LowerIntegrationTest.java +++ b/javatests/com/google/turbine/lower/LowerIntegrationTest.java @@ -64,11 +64,9 @@ public class LowerIntegrationTest { entry("sealed_nested.test", 17), entry("textblock.test", 15), entry("textblock2.test", 15), - entry("B306423115.test", 15), - entry("string_template.test", 21)); + entry("B306423115.test", 15)); - private static final ImmutableSet SOURCE_VERSION_PREVIEW = - ImmutableSet.of("string_template.test"); + private static final ImmutableSet SOURCE_VERSION_PREVIEW = ImmutableSet.of(); @Parameters(name = "{index}: {0}") public static Iterable parameters() { @@ -313,7 +311,6 @@ public static Iterable parameters() { "strictfp.test", "string.test", "string_const.test", - "string_template.test", "superabstract.test", "supplierfunction.test", "tbound.test", diff --git a/javatests/com/google/turbine/lower/LowerTest.java b/javatests/com/google/turbine/lower/LowerTest.java index 15d3aa5..2de4650 100644 --- a/javatests/com/google/turbine/lower/LowerTest.java +++ b/javatests/com/google/turbine/lower/LowerTest.java @@ -17,7 +17,6 @@ package com.google.turbine.lower; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.TruthJUnit.assume; import static com.google.turbine.testing.TestClassPaths.TURBINE_BOOTCLASSPATH; import static com.google.turbine.testing.TestResources.getResource; import static java.util.Objects.requireNonNull; @@ -57,7 +56,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -753,42 +751,6 @@ public FieldVisitor visitField( assertThat(fields).containsExactly("y"); } - // Ensure we don't emit bogus ConstantValues for string templates with a missing processor - @Test - public void stringTemplate() throws Exception { - assume().that(Runtime.version().feature()).isAtLeast(21); - BindingResult bound = - Binder.bind( - ImmutableList.of( - Parser.parse( - "class Test {\n" // - + " public static final String X = \"hello \\{ \"world\" }\";\n" - + "}")), - ClassPathBinder.bindClasspath(ImmutableList.of()), - TURBINE_BOOTCLASSPATH, - /* moduleVersion= */ Optional.empty()); - ImmutableMap lowered = - Lower.lowerAll( - Lower.LowerOptions.createDefault(), - bound.units(), - bound.modules(), - bound.classPathEnv()) - .bytes(); - Map fields = new HashMap<>(); - new ClassReader(lowered.get("Test")) - .accept( - new ClassVisitor(Opcodes.ASM9) { - @Override - public FieldVisitor visitField( - int access, String name, String descriptor, String signature, Object value) { - fields.put(name, value); - return null; - } - }, - 0); - assertThat(fields).containsExactly("X", null); - } - static String lines(String... lines) { return Joiner.on(System.lineSeparator()).join(lines); } diff --git a/javatests/com/google/turbine/lower/testdata/string_template.test b/javatests/com/google/turbine/lower/testdata/string_template.test deleted file mode 100644 index c24ba53..0000000 --- a/javatests/com/google/turbine/lower/testdata/string_template.test +++ /dev/null @@ -1,49 +0,0 @@ -=== StringTemplates.java === -public class StringTemplates { - interface Example { - Object foo(); - boolean test(String string); - } - void test(Example example, Example example0, Example example1, Example example2){ - var m = STR."template \{example}xxx"; - var nested = STR."template \{example.foo()+ STR."templateInner\{example}"}xxx }"; - var nestNested = STR."template \{example0. - foo() + - STR."templateInner\{example1.test(STR."\{example2 - }")}"}xxx }"; - } -} -=== Foo.java === -class Foo { - public static final int X = 42; - public static final String A = STR."\{X} = \{X}"; - public static final String B = STR.""; - public static final String C = STR."\{X}"; - public static final String D = STR."\{X}\{X}"; - public static final String E = STR."\{X}\{X}\{X}"; - public static final String F = STR." \{X}"; - public static final String G = STR."\{X} "; - public static final String H = STR."\{X} one long incredibly unbroken sentence moving from "+"topic to topic so that no-one had a chance to interrupt"; - public static final String I = STR."\{X} \uD83D\uDCA9 "; -} -=== Multiline.java === -import static java.lang.StringTemplate.STR; - -public class Multiline { - static String planet = "world"; - - static String s1 = STR."hello, \{planet}"; - - static String s2 = STR.""" - hello, \{planet} - """; - - static String s3 = STR.""" - hello, \{ - STR.""" - recursion, \{ - } - """ - } - """; -} \ No newline at end of file diff --git a/javatests/com/google/turbine/parse/LexerTest.java b/javatests/com/google/turbine/parse/LexerTest.java index 75c0901..e0f0f61 100644 --- a/javatests/com/google/turbine/parse/LexerTest.java +++ b/javatests/com/google/turbine/parse/LexerTest.java @@ -367,7 +367,6 @@ public static List lex(String input) { break; case CHAR_LITERAL: case STRING_LITERAL: - case STRING_TEMPLATE: tokenString = String.format( "%s(%s)", @@ -424,38 +423,4 @@ public void textBlockEOF() { assertThat(lexer.next()).isEqualTo(Token.EOF); assertThat(lexer.stringValue()).isEqualTo("\\"); } - - @Test - public void stringTemplate() { - assertThat(lex("STR.\"\\{X}\"")) - .containsExactly("IDENT(STR)", "DOT", "STRING_TEMPLATE({})", "EOF"); - } - - @Test - public void stringTemplateNested() { - assertThat(lex("STR.\"template \\{example.foo()+ STR.\"templateInner\\{example}\"}xxx }\"")) - .containsExactly("IDENT(STR)", "DOT", "STRING_TEMPLATE(template {}xxx })", "EOF"); - } - - @Test - public void stringTemplateNestedBraces() { - assertThat(lex("STR.\"\\{ new Object() {} }\" + \"\"")) - .containsExactly( - "IDENT(STR)", "DOT", "STRING_TEMPLATE({})", "PLUS", "STRING_LITERAL()", "EOF"); - } - - @Test - public void stringTemplateBraces() { - assertThat(lex("\"foo \\{'{'}\"")).containsExactly("STRING_TEMPLATE(foo {})", "EOF"); - assertThat(lex("\"foo \\{\"}\"}\"")).containsExactly("STRING_TEMPLATE(foo {})", "EOF"); - assertThat(lex("\"foo \\{new Bar[]{}}\"")).containsExactly("STRING_TEMPLATE(foo {})", "EOF"); - assertThat(lex("\"foo \\{\"bar \\{'}'}\"}\"")) - .containsExactly("STRING_TEMPLATE(foo {})", "EOF"); - } - - @Test - public void textBlockStringTemplate() { - assertThat(lex("STR.\"\"\"\n\\{X}\"\"\"")) - .containsExactly("IDENT(STR)", "DOT", "STRING_TEMPLATE({})", "EOF"); - } }