diff --git a/src/java.base/share/classes/java/lang/StringConcatHelper.java b/src/java.base/share/classes/java/lang/StringConcatHelper.java
index 28b9b754bbd..49f556e5aa6 100644
--- a/src/java.base/share/classes/java/lang/StringConcatHelper.java
+++ b/src/java.base/share/classes/java/lang/StringConcatHelper.java
@@ -26,8 +26,6 @@
package java.lang;
import jdk.internal.misc.Unsafe;
-import jdk.internal.javac.PreviewFeature;
-import jdk.internal.util.FormatConcatItem;
import jdk.internal.vm.annotation.ForceInline;
import java.lang.invoke.MethodHandle;
@@ -127,20 +125,6 @@ final class StringConcatHelper {
return checkOverflow(lengthCoder);
}
- /**
- * Mix value length and coder into current length and coder.
- * @param lengthCoder String length with coder packed into higher bits
- * the upper word.
- * @param value value to mix in
- * @return new length and coder
- * @since 21
- */
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- static long mix(long lengthCoder, FormatConcatItem value) {
- lengthCoder = value.mix(lengthCoder);
- return checkOverflow(lengthCoder);
- }
-
/**
* Prepends the stringly representation of boolean value into buffer,
* given the coder and final index. Index is measured in chars, not in bytes!
@@ -344,48 +328,6 @@ final class StringConcatHelper {
return indexCoder;
}
- /**
- * Prepends the stringly representation of FormatConcatItem value into buffer,
- * given the coder and final index. Index is measured in chars, not in bytes!
- *
- * @param indexCoder final char index in the buffer, along with coder packed
- * into higher bits.
- * @param buf buffer to append to
- * @param value String value to encode
- * @return updated index (coder value retained)
- * @since 21
- */
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- static long prepend(long indexCoder, byte[] buf, FormatConcatItem value) {
- try {
- return value.prepend(indexCoder, buf);
- } catch (Error ex) {
- throw ex;
- } catch (Throwable ex) {
- throw new AssertionError("FormatConcatItem prepend error", ex);
- }
- }
-
- /**
- * Prepends constant and the stringly representation of value into buffer,
- * given the coder and final index. Index is measured in chars, not in bytes!
- *
- * @param indexCoder final char index in the buffer, along with coder packed
- * into higher bits.
- * @param buf buffer to append to
- * @param value boolean value to encode
- * @param prefix a constant to prepend before value
- * @return updated index (coder value retained)
- * @since 21
- */
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- static long prepend(long indexCoder, byte[] buf,
- FormatConcatItem value, String prefix) {
- indexCoder = prepend(indexCoder, buf, value);
- indexCoder = prepend(indexCoder, buf, prefix);
- return indexCoder;
- }
-
/**
* Instantiates the String with given buffer and coder
* @param buf buffer to use
@@ -517,71 +459,6 @@ final class StringConcatHelper {
return String.COMPACT_STRINGS ? LATIN1 : UTF16;
}
- /*
- * Initialize after phase1.
- */
- private static class LateInit {
- static final MethodHandle GETCHAR_LATIN1_MH;
-
- static final MethodHandle GETCHAR_UTF16_MH;
-
- static final MethodHandle PUTCHAR_LATIN1_MH;
-
- static final MethodHandle PUTCHAR_UTF16_MH;
-
- static {
- MethodType getCharMT =
- MethodType.methodType(char.class,
- byte[].class, int.class);
- MethodType putCharMT =
- MethodType.methodType(void.class,
- byte[].class, int.class, int.class);
- GETCHAR_LATIN1_MH = lookupStatic("getCharLatin1", getCharMT);
- GETCHAR_UTF16_MH = lookupStatic("getCharUTF16", getCharMT);
- PUTCHAR_LATIN1_MH = lookupStatic("putCharLatin1", putCharMT);
- PUTCHAR_UTF16_MH = lookupStatic("putCharUTF16", putCharMT);
- }
-
- }
-
- @ForceInline
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- static char getCharLatin1(byte[] buffer, int index) {
- return (char)buffer[index];
- }
-
- @ForceInline
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- static char getCharUTF16(byte[] buffer, int index) {
- return StringUTF16.getChar(buffer, index);
- }
-
- @ForceInline
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- static void putCharLatin1(byte[] buffer, int index, int ch) {
- buffer[index] = (byte)ch;
- }
-
- @ForceInline
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- static void putCharUTF16(byte[] buffer, int index, int ch) {
- StringUTF16.putChar(buffer, index, ch);
- }
-
- @ForceInline
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- static MethodHandle selectGetChar(long indexCoder) {
- return indexCoder < UTF16 ? LateInit.GETCHAR_LATIN1_MH :
- LateInit.GETCHAR_UTF16_MH;
- }
-
- @ForceInline
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- static MethodHandle selectPutChar(long indexCoder) {
- return indexCoder < UTF16 ? LateInit.PUTCHAR_LATIN1_MH :
- LateInit.PUTCHAR_UTF16_MH;
- }
-
static MethodHandle lookupStatic(String name, MethodType methodType) {
try {
return MethodHandles.lookup()
diff --git a/src/java.base/share/classes/java/lang/StringTemplate.java b/src/java.base/share/classes/java/lang/StringTemplate.java
deleted file mode 100644
index c14876130be..00000000000
--- a/src/java.base/share/classes/java/lang/StringTemplate.java
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package java.lang;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
-import java.util.FormatProcessor;
-import java.util.function.Function;
-import java.util.List;
-import java.util.Objects;
-
-import jdk.internal.access.JavaTemplateAccess;
-import jdk.internal.access.SharedSecrets;
-import jdk.internal.javac.PreviewFeature;
-
-/**
- * {@link StringTemplate} is the run-time representation of a string template or
- * text block template in a template expression.
- *
- * In the source code of a Java program, a string template or text block template
- * contains an interleaved succession of fragment literals and embedded
- * expressions . The {@link StringTemplate#fragments()} method returns the
- * fragment literals, and the {@link StringTemplate#values()} method returns the
- * results of evaluating the embedded expressions. {@link StringTemplate} does not
- * provide access to the source code of the embedded expressions themselves; it is
- * not a compile-time representation of a string template or text block template.
- *
- * {@link StringTemplate} is primarily used in conjunction with a template processor
- * to produce a string or other meaningful value. Evaluation of a template expression
- * first produces an instance of {@link StringTemplate}, representing the right hand side
- * of the template expression, and then passes the instance to the template processor
- * given by the template expression.
- *
- * For example, the following code contains a template expression that uses the template
- * processor {@code RAW}, which simply yields the {@link StringTemplate} passed to it:
- * {@snippet :
- * int x = 10;
- * int y = 20;
- * StringTemplate st = RAW."\{x} + \{y} = \{x + y}";
- * List fragments = st.fragments();
- * List values = st.values();
- * }
- * {@code fragments} will be equivalent to {@code List.of("", " + ", " = ", "")},
- * which includes the empty first and last fragments. {@code values} will be the
- * equivalent of {@code List.of(10, 20, 30)}.
- *
- * The following code contains a template expression with the same template but with a
- * different template processor, {@code STR}:
- * {@snippet :
- * int x = 10;
- * int y = 20;
- * String s = STR."\{x} + \{y} = \{x + y}";
- * }
- * When the template expression is evaluated, an instance of {@link StringTemplate} is
- * produced that returns the same lists from {@link StringTemplate#fragments()} and
- * {@link StringTemplate#values()} as shown above. The {@link StringTemplate#STR} template
- * processor uses these lists to yield an interpolated string. The value of {@code s} will
- * be equivalent to {@code "10 + 20 = 30"}.
- *
- * The {@code interpolate()} method provides a direct way to perform string interpolation
- * of a {@link StringTemplate}. Template processors can use the following code pattern:
- * {@snippet :
- * List fragments = st.fragments();
- * List values = st.values();
- * ... check or manipulate the fragments and/or values ...
- * String result = StringTemplate.interpolate(fragments, values);
- * }
- * The {@link StringTemplate#process(Processor)} method, in conjunction with
- * the {@link StringTemplate#RAW} processor, may be used to defer processing of a
- * {@link StringTemplate}.
- * {@snippet :
- * StringTemplate st = RAW."\{x} + \{y} = \{x + y}";
- * ...other steps...
- * String result = st.process(STR);
- * }
- * The factory methods {@link StringTemplate#of(String)} and
- * {@link StringTemplate#of(List, List)} can be used to construct a {@link StringTemplate}.
- *
- * @see Processor
- * @see java.util.FormatProcessor
- *
- * @implNote Implementations of {@link StringTemplate} must minimally implement the
- * methods {@link StringTemplate#fragments()} and {@link StringTemplate#values()}.
- * Instances of {@link StringTemplate} are considered immutable. To preserve the
- * semantics of string templates and text block templates, the list returned by
- * {@link StringTemplate#fragments()} must be one element larger than the list returned
- * by {@link StringTemplate#values()}.
- *
- * @since 21
- *
- * @jls 15.8.6 Process Template Expressions
- */
-@PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
-public interface StringTemplate {
- /**
- * Returns a list of fragment literals for this {@link StringTemplate}.
- * The fragment literals are the character sequences preceding each of the embedded
- * expressions in source code, plus the character sequence following the last
- * embedded expression. Such character sequences may be zero-length if an embedded
- * expression appears at the beginning or end of a template, or if two embedded
- * expressions are directly adjacent in a template.
- * In the example: {@snippet :
- * String student = "Mary";
- * String teacher = "Johnson";
- * StringTemplate st = RAW."The student \{student} is in \{teacher}'s classroom.";
- * List fragments = st.fragments(); // @highlight substring="fragments()"
- * }
- * {@code fragments} will be equivalent to
- * {@code List.of("The student ", " is in ", "'s classroom.")}
- *
- * @return list of string fragments
- *
- * @implSpec the list returned is immutable
- */
- List fragments();
-
- /**
- * Returns a list of embedded expression results for this {@link StringTemplate}.
- * In the example:
- * {@snippet :
- * String student = "Mary";
- * String teacher = "Johnson";
- * StringTemplate st = RAW."The student \{student} is in \{teacher}'s classroom.";
- * List values = st.values(); // @highlight substring="values()"
- * }
- * {@code values} will be equivalent to {@code List.of(student, teacher)}
- *
- * @return list of expression values
- *
- * @implSpec the list returned is immutable
- */
- List values();
-
- /**
- * Returns the string interpolation of the fragments and values for this
- * {@link StringTemplate}.
- * @apiNote For better visibility and when practical, it is recommended to use the
- * {@link StringTemplate#STR} processor instead of invoking the
- * {@link StringTemplate#interpolate()} method.
- * {@snippet :
- * String student = "Mary";
- * String teacher = "Johnson";
- * StringTemplate st = RAW."The student \{student} is in \{teacher}'s classroom.";
- * String result = st.interpolate(); // @highlight substring="interpolate()"
- * }
- * In the above example, the value of {@code result} will be
- * {@code "The student Mary is in Johnson's classroom."}. This is
- * produced by the interleaving concatenation of fragments and values from the supplied
- * {@link StringTemplate}. To accommodate concatenation, values are converted to strings
- * as if invoking {@link String#valueOf(Object)}.
- *
- * @return interpolation of this {@link StringTemplate}
- *
- * @implSpec The default implementation returns the result of invoking
- * {@code StringTemplate.interpolate(this.fragments(), this.values())}.
- */
- default String interpolate() {
- return StringTemplate.interpolate(fragments(), values());
- }
-
- /**
- * Returns the result of applying the specified processor to this {@link StringTemplate}.
- * This method can be used as an alternative to string template expressions. For example,
- * {@snippet :
- * String student = "Mary";
- * String teacher = "Johnson";
- * String result1 = STR."The student \{student} is in \{teacher}'s classroom.";
- * String result2 = RAW."The student \{student} is in \{teacher}'s classroom.".process(STR); // @highlight substring="process"
- * }
- * Produces an equivalent result for both {@code result1} and {@code result2}.
- *
- * @param processor the {@link Processor} instance to process
- *
- * @param Processor's process result type.
- * @param Exception thrown type.
- *
- * @return constructed object of type {@code R}
- *
- * @throws E exception thrown by the template processor when validation fails
- * @throws NullPointerException if processor is null
- *
- * @implSpec The default implementation returns the result of invoking
- * {@code processor.process(this)}. If the invocation throws an exception that
- * exception is forwarded to the caller.
- */
- default R
- process(Processor extends R, ? extends E> processor) throws E {
- Objects.requireNonNull(processor, "processor should not be null");
-
- return processor.process(this);
- }
-
- /**
- * Produces a diagnostic string that describes the fragments and values of the supplied
- * {@link StringTemplate}.
- *
- * @param stringTemplate the {@link StringTemplate} to represent
- *
- * @return diagnostic string representing the supplied string template
- *
- * @throws NullPointerException if stringTemplate is null
- */
- static String toString(StringTemplate stringTemplate) {
- Objects.requireNonNull(stringTemplate, "stringTemplate should not be null");
- return "StringTemplate{ fragments = [ \"" +
- String.join("\", \"", stringTemplate.fragments()) +
- "\" ], values = " +
- stringTemplate.values() +
- " }";
- }
-
- /**
- * Returns a {@link StringTemplate} as if constructed by invoking
- * {@code StringTemplate.of(List.of(string), List.of())}. That is, a {@link StringTemplate}
- * with one fragment and no values.
- *
- * @param string single string fragment
- *
- * @return StringTemplate composed from string
- *
- * @throws NullPointerException if string is null
- */
- static StringTemplate of(String string) {
- Objects.requireNonNull(string, "string must not be null");
- JavaTemplateAccess JTA = SharedSecrets.getJavaTemplateAccess();
- return JTA.of(List.of(string), List.of());
- }
-
- /**
- * Returns a StringTemplate with the given fragments and values.
- *
- * @implSpec The {@code fragments} list size must be one more that the
- * {@code values} list size.
- *
- * @param fragments list of string fragments
- * @param values list of expression values
- *
- * @return StringTemplate composed from string
- *
- * @throws IllegalArgumentException if fragments list size is not one more
- * than values list size
- * @throws NullPointerException if fragments is null or values is null or if any fragment is null.
- *
- * @implNote Contents of both lists are copied to construct immutable lists.
- */
- static StringTemplate of(List fragments, List> values) {
- Objects.requireNonNull(fragments, "fragments must not be null");
- Objects.requireNonNull(values, "values must not be null");
- if (values.size() + 1 != fragments.size()) {
- throw new IllegalArgumentException(
- "fragments list size is not one more than values list size");
- }
- JavaTemplateAccess JTA = SharedSecrets.getJavaTemplateAccess();
- return JTA.of(fragments, values);
- }
-
- /**
- * Creates a string that interleaves the elements of values between the
- * elements of fragments. To accommodate interpolation, values are converted to strings
- * as if invoking {@link String#valueOf(Object)}.
- *
- * @param fragments list of String fragments
- * @param values list of expression values
- *
- * @return String interpolation of fragments and values
- *
- * @throws IllegalArgumentException if fragments list size is not one more
- * than values list size
- * @throws NullPointerException fragments or values is null or if any of the fragments is null
- */
- static String interpolate(List fragments, List> values) {
- Objects.requireNonNull(fragments, "fragments must not be null");
- Objects.requireNonNull(values, "values must not be null");
- int fragmentsSize = fragments.size();
- int valuesSize = values.size();
- if (fragmentsSize != valuesSize + 1) {
- throw new IllegalArgumentException("fragments must have one more element than values");
- }
- JavaTemplateAccess JTA = SharedSecrets.getJavaTemplateAccess();
- return JTA.interpolate(fragments, values);
- }
-
- /**
- * Combine zero or more {@link StringTemplate StringTemplates} into a single
- * {@link StringTemplate}.
- * {@snippet :
- * StringTemplate st = StringTemplate.combine(RAW."\{a}", RAW."\{b}", RAW."\{c}");
- * assert st.interpolate().equals(STR."\{a}\{b}\{c}");
- * }
- * Fragment lists from the {@link StringTemplate StringTemplates} are combined end to
- * end with the last fragment from each {@link StringTemplate} concatenated with the
- * first fragment of the next. To demonstrate, if we were to take two strings and we
- * combined them as follows: {@snippet lang = "java":
- * String s1 = "abc";
- * String s2 = "xyz";
- * String sc = s1 + s2;
- * assert Objects.equals(sc, "abcxyz");
- * }
- * the last character {@code "c"} from the first string is juxtaposed with the first
- * character {@code "x"} of the second string. The same would be true of combining
- * {@link StringTemplate StringTemplates}.
- * {@snippet lang ="java":
- * StringTemplate st1 = RAW."a\{}b\{}c";
- * StringTemplate st2 = RAW."x\{}y\{}z";
- * StringTemplate st3 = RAW."a\{}b\{}cx\{}y\{}z";
- * StringTemplate stc = StringTemplate.combine(st1, st2);
- *
- * assert Objects.equals(st1.fragments(), List.of("a", "b", "c"));
- * assert Objects.equals(st2.fragments(), List.of("x", "y", "z"));
- * assert Objects.equals(st3.fragments(), List.of("a", "b", "cx", "y", "z"));
- * assert Objects.equals(stc.fragments(), List.of("a", "b", "cx", "y", "z"));
- * }
- * Values lists are simply concatenated to produce a single values list.
- * The result is a well-formed {@link StringTemplate} with n+1 fragments and n values, where
- * n is the total of number of values across all the supplied
- * {@link StringTemplate StringTemplates}.
- *
- * @param stringTemplates zero or more {@link StringTemplate}
- *
- * @return combined {@link StringTemplate}
- *
- * @throws NullPointerException if stringTemplates is null or if any of the
- * {@code stringTemplates} are null
- *
- * @implNote If zero {@link StringTemplate} arguments are provided then a
- * {@link StringTemplate} with an empty fragment and no values is returned, as if invoking
- * StringTemplate.of("") . If only one {@link StringTemplate} argument is provided
- * then it is returned unchanged.
- */
- static StringTemplate combine(StringTemplate... stringTemplates) {
- JavaTemplateAccess JTA = SharedSecrets.getJavaTemplateAccess();
- return JTA.combine(stringTemplates);
- }
-
- /**
- * Combine a list of {@link StringTemplate StringTemplates} into a single
- * {@link StringTemplate}.
- * {@snippet :
- * StringTemplate st = StringTemplate.combine(List.of(RAW."\{a}", RAW."\{b}", RAW."\{c}"));
- * assert st.interpolate().equals(STR."\{a}\{b}\{c}");
- * }
- * Fragment lists from the {@link StringTemplate StringTemplates} are combined end to
- * end with the last fragment from each {@link StringTemplate} concatenated with the
- * first fragment of the next. To demonstrate, if we were to take two strings and we
- * combined them as follows: {@snippet lang = "java":
- * String s1 = "abc";
- * String s2 = "xyz";
- * String sc = s1 + s2;
- * assert Objects.equals(sc, "abcxyz");
- * }
- * the last character {@code "c"} from the first string is juxtaposed with the first
- * character {@code "x"} of the second string. The same would be true of combining
- * {@link StringTemplate StringTemplates}.
- * {@snippet lang ="java":
- * StringTemplate st1 = RAW."a\{}b\{}c";
- * StringTemplate st2 = RAW."x\{}y\{}z";
- * StringTemplate st3 = RAW."a\{}b\{}cx\{}y\{}z";
- * StringTemplate stc = StringTemplate.combine(List.of(st1, st2));
- *
- * assert Objects.equals(st1.fragments(), List.of("a", "b", "c"));
- * assert Objects.equals(st2.fragments(), List.of("x", "y", "z"));
- * assert Objects.equals(st3.fragments(), List.of("a", "b", "cx", "y", "z"));
- * assert Objects.equals(stc.fragments(), List.of("a", "b", "cx", "y", "z"));
- * }
- * Values lists are simply concatenated to produce a single values list.
- * The result is a well-formed {@link StringTemplate} with n+1 fragments and n values, where
- * n is the total of number of values across all the supplied
- * {@link StringTemplate StringTemplates}.
- *
- * @param stringTemplates list of {@link StringTemplate}
- *
- * @return combined {@link StringTemplate}
- *
- * @throws NullPointerException if stringTemplates is null or if any of the
- * its elements are null
- *
- * @implNote If {@code stringTemplates.size() == 0} then a {@link StringTemplate} with
- * an empty fragment and no values is returned, as if invoking
- * StringTemplate.of("") . If {@code stringTemplates.size() == 1}
- * then the first element of the list is returned unchanged.
- */
- static StringTemplate combine(List stringTemplates) {
- JavaTemplateAccess JTA = SharedSecrets.getJavaTemplateAccess();
- return JTA.combine(stringTemplates.toArray(new StringTemplate[0]));
- }
-
- /**
- * This {@link Processor} instance is conventionally used for the string interpolation
- * of a supplied {@link StringTemplate}.
- *
- * For better visibility and when practical, it is recommended that users use the
- * {@link StringTemplate#STR} processor instead of invoking the
- * {@link StringTemplate#interpolate()} method.
- * Example: {@snippet :
- * int x = 10;
- * int y = 20;
- * String result = STR."\{x} + \{y} = \{x + y}"; // @highlight substring="STR"
- * }
- * In the above example, the value of {@code result} will be {@code "10 + 20 = 30"}. This is
- * produced by the interleaving concatenation of fragments and values from the supplied
- * {@link StringTemplate}. To accommodate concatenation, values are converted to strings
- * as if invoking {@link String#valueOf(Object)}.
- * @apiNote {@link StringTemplate#STR} is statically imported implicitly into every
- * Java compilation unit.
- */
- Processor STR = StringTemplate::interpolate;
-
- /**
- * This {@link Processor} instance is conventionally used to indicate that the
- * processing of the {@link StringTemplate} is to be deferred to a later time. Deferred
- * processing can be resumed by invoking the
- * {@link StringTemplate#process(Processor)} or
- * {@link Processor#process(StringTemplate)} methods.
- * {@snippet :
- * import static java.lang.StringTemplate.RAW;
- * ...
- * StringTemplate st = RAW."\{x} + \{y} = \{x + y}";
- * ...other steps...
- * String result = STR.process(st);
- * }
- * @implNote Unlike {@link StringTemplate#STR}, {@link StringTemplate#RAW} must be
- * statically imported explicitly.
- */
- Processor RAW = st -> st;
-
- /**
- * This interface describes the methods provided by a generalized string template processor. The
- * primary method {@link Processor#process(StringTemplate)} is used to validate
- * and compose a result using a {@link StringTemplate StringTemplate's} fragments and values lists.
- *
- * For example:
- * {@snippet :
- * class MyProcessor implements Processor {
- * @Override
- * public String process(StringTemplate st) throws IllegalArgumentException {
- * StringBuilder sb = new StringBuilder();
- * Iterator fragmentsIter = st.fragments().iterator();
- *
- * for (Object value : st.values()) {
- * sb.append(fragmentsIter.next());
- *
- * if (value instanceof Boolean) {
- * throw new IllegalArgumentException("I don't like Booleans");
- * }
- *
- * sb.append(value);
- * }
- *
- * sb.append(fragmentsIter.next());
- *
- * return sb.toString();
- * }
- * }
- *
- * MyProcessor myProcessor = new MyProcessor();
- * try {
- * int x = 10;
- * int y = 20;
- * String result = myProcessor."\{x} + \{y} = \{x + y}";
- * ...
- * } catch (IllegalArgumentException ex) {
- * ...
- * }
- * }
- * Implementations of this interface may provide, but are not limited to, validating
- * inputs, composing inputs into a result, and transforming an intermediate string
- * result to a non-string value before delivering the final result.
- *
- * The user has the option of validating inputs used in composition. For example an SQL
- * processor could prevent injection vulnerabilities by sanitizing inputs or throwing an
- * exception of type {@code E} if an SQL statement is a potential vulnerability.
- *
- * Composing allows user control over how the result is assembled. Most often, a
- * user will construct a new string from the string template, with placeholders
- * replaced by string representations of value list elements. These string
- * representations are created as if invoking {@link String#valueOf}.
- *
- * Transforming allows the processor to return something other than a string. For
- * instance, a JSON processor could return a JSON object, by parsing the string created
- * by composition, instead of the composed string.
- *
- * {@link Processor} is a {@link FunctionalInterface}. This permits
- * declaration of a processor using lambda expressions;
- * {@snippet :
- * Processor processor = st -> {
- * List fragments = st.fragments();
- * List values = st.values();
- * // check or manipulate the fragments and/or values
- * ...
- * return StringTemplate.interpolate(fragments, values);
- * };
- * }
- * The {@link StringTemplate#interpolate()} method is available for those processors
- * that just need to work with the string interpolation;
- * {@snippet :
- * Processor processor = StringTemplate::interpolate;
- * }
- * or simply transform the string interpolation into something other than
- * {@link String};
- * {@snippet :
- * Processor jsonProcessor = st -> new JSONObject(st.interpolate());
- * }
- * @implNote The Java compiler automatically imports {@link StringTemplate#STR}
- *
- * @param Processor's process result type
- * @param Exception thrown type
- *
- * @see StringTemplate
- * @see java.util.FormatProcessor
- *
- * @since 21
- *
- * @jls 15.8.6 Process Template Expressions
- */
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- @FunctionalInterface
- public interface Processor {
-
- /**
- * Constructs a result based on the template fragments and values in the
- * supplied {@link StringTemplate stringTemplate} object.
- * @apiNote Processing of a {@link StringTemplate} may include validation according to the particular facts relating
- * to each situation. The {@code E} type parameter indicates the type of checked exception that is thrown by
- * {@link #process} if validation fails, ex. {@code java.sql.SQLException}. If no checked exception is expected
- * then {@link RuntimeException} may be used. Note that unchecked exceptions, such as {@link RuntimeException},
- * {@link NullPointerException} or {@link IllegalArgumentException} may be thrown as part of the normal
- * method arguments processing. Details of which exceptions are thrown will be found in the documentation
- * of the specific implementation.
- *
- * @param stringTemplate a {@link StringTemplate} instance
- *
- * @return constructed object of type R
- *
- * @throws E exception thrown by the template processor when validation fails
- */
- R process(StringTemplate stringTemplate) throws E;
-
- /**
- * This factory method can be used to create a {@link Processor} containing a
- * {@link Processor#process} method derived from a lambda expression. As an example;
- * {@snippet :
- * Processor mySTR = Processor.of(StringTemplate::interpolate);
- * int x = 10;
- * int y = 20;
- * String str = mySTR."\{x} + \{y} = \{x + y}";
- * }
- * The result type of the constructed {@link Processor} may be derived from
- * the lambda expression, thus this method may be used in a var
- * statement. For example, {@code mySTR} from above can also be declared using;
- * {@snippet :
- * var mySTR = Processor.of(StringTemplate::interpolate);
- * }
- * {@link RuntimeException} is the assumed exception thrown type.
- *
- * @param process a function that takes a {@link StringTemplate} as an argument
- * and returns the inferred result type
- *
- * @return a {@link Processor}
- *
- * @param Processor's process result type
- */
- static Processor of(Function super StringTemplate, ? extends T> process) {
- return process::apply;
- }
-
- /**
- * Built-in policies using this additional interface have the flexibility to
- * specialize the composition of the templated string by returning a customized
- * {@link MethodHandle} from {@link Linkage#linkage linkage}.
- * These specializations are typically implemented to improve performance;
- * specializing value types or avoiding boxing and vararg arrays.
- *
- * @implNote This interface is sealed to only allow standard processors.
- *
- * @sealedGraph
- * @since 21
- */
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- public sealed interface Linkage permits FormatProcessor {
- /**
- * This method creates a {@link MethodHandle} that when invoked with arguments of
- * those specified in {@code type} returns a result that equals that returned by
- * the template processor's process method. The difference being that this method
- * can preview the template's fragments and value types in advance of usage and
- * thereby has the opportunity to produce a specialized implementation.
- *
- * @param fragments string template fragments
- * @param type method type, includes the StringTemplate receiver as
- * well as the value types
- *
- * @return {@link MethodHandle} for the processor applied to template
- *
- * @throws NullPointerException if any of the arguments are null
- */
- MethodHandle linkage(List fragments, MethodType type);
- }
- }
-
-}
diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java
index d6a0faa4200..3c80e82b138 100644
--- a/src/java.base/share/classes/java/lang/System.java
+++ b/src/java.base/share/classes/java/lang/System.java
@@ -80,7 +80,6 @@ import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
-import jdk.internal.javac.PreviewFeature;
import jdk.internal.logger.LoggerFinderLoader;
import jdk.internal.logger.LazyLoggers;
import jdk.internal.logger.LocalizedLoggerWrapper;
@@ -2490,6 +2489,9 @@ public final class System {
public char getUTF16Char(byte[] bytes, int index) {
return StringUTF16.getChar(bytes, index);
}
+ public void putCharUTF16(byte[] bytes, int index, int ch) {
+ StringUTF16.putChar(bytes, index, ch);
+ }
public byte[] getBytesNoRepl(String s, Charset cs) throws CharacterCodingException {
return String.getBytesNoRepl(s, cs);
}
@@ -2530,6 +2532,10 @@ public final class System {
return StringConcatHelper.lookupStatic(name, methodType);
}
+ public long stringConcatHelperPrepend(long indexCoder, byte[] buf, String value) {
+ return StringConcatHelper.prepend(indexCoder, buf, value);
+ }
+
public long stringConcatInitialCoder() {
return StringConcatHelper.initialCoder();
}
@@ -2538,21 +2544,20 @@ public final class System {
return StringConcatHelper.mix(lengthCoder, constant);
}
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- public long stringConcatCoder(char value) {
- return StringConcatHelper.coder(value);
+ public long stringConcatMix(long lengthCoder, char value) {
+ return StringConcatHelper.mix(lengthCoder, value);
}
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- public long stringBuilderConcatMix(long lengthCoder,
- StringBuilder sb) {
- return sb.mix(lengthCoder);
+ public int stringSize(long i) {
+ return Long.stringSize(i);
}
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- public long stringBuilderConcatPrepend(long lengthCoder, byte[] buf,
- StringBuilder sb) {
- return sb.prepend(lengthCoder, buf);
+ public int getCharsLatin1(long i, int index, byte[] buf) {
+ return StringLatin1.getChars(i, index, buf);
+ }
+
+ public int getCharsUTF16(long i, int index, byte[] buf) {
+ return StringUTF16.getChars(i, index, buf);
}
public String join(String prefix, String suffix, String delimiter, String[] elements, int size) {
diff --git a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
index cc0abfef97c..b918b756332 100644
--- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java
@@ -28,7 +28,6 @@ package java.lang.invoke;
import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.javac.PreviewFeature;
-import jdk.internal.util.FormatConcatItem;
import jdk.internal.vm.annotation.Stable;
import sun.invoke.util.Wrapper;
@@ -115,14 +114,8 @@ public final class StringConcatFactory {
* While the maximum number of argument slots that indy call can handle is 253,
* we do not use all those slots, to let the strategies with MethodHandle
* combinators to use some arguments.
- *
- * @since 21
*/
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- public static final int MAX_INDY_CONCAT_ARG_SLOTS;
- // Use static initialize block to avoid MAX_INDY_CONCAT_ARG_SLOTS being treating
- // as a constant for constant folding.
- static { MAX_INDY_CONCAT_ARG_SLOTS = 200; }
+ private static final int MAX_INDY_CONCAT_ARG_SLOTS = 200;
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
@@ -712,9 +705,6 @@ public final class StringConcatFactory {
int idx = classIndex(cl);
MethodHandle prepend = PREPENDERS[idx];
if (prepend == null) {
- if (idx == STRING_CONCAT_ITEM) {
- cl = FormatConcatItem.class;
- }
PREPENDERS[idx] = prepend = JLA.stringConcatHelper("prepend",
methodType(long.class, long.class, byte[].class,
Wrapper.asPrimitiveType(cl), String.class)).rebind();
@@ -726,9 +716,6 @@ public final class StringConcatFactory {
int idx = classIndex(cl);
MethodHandle prepend = NO_PREFIX_PREPENDERS[idx];
if (prepend == null) {
- if (idx == STRING_CONCAT_ITEM) {
- cl = FormatConcatItem.class;
- }
NO_PREFIX_PREPENDERS[idx] = prepend = JLA.stringConcatHelper("prepend",
methodType(long.class, long.class, byte[].class,
Wrapper.asPrimitiveType(cl))).rebind();
@@ -741,15 +728,13 @@ public final class StringConcatFactory {
LONG_IDX = 2,
BOOLEAN_IDX = 3,
STRING_IDX = 4,
- STRING_CONCAT_ITEM = 5,
- TYPE_COUNT = 6;
+ TYPE_COUNT = 5;
private static int classIndex(Class> cl) {
if (cl == String.class) return STRING_IDX;
if (cl == int.class) return INT_IDX;
if (cl == boolean.class) return BOOLEAN_IDX;
if (cl == char.class) return CHAR_IDX;
if (cl == long.class) return LONG_IDX;
- if (FormatConcatItem.class.isAssignableFrom(cl)) return STRING_CONCAT_ITEM;
throw new IllegalArgumentException("Unexpected class: " + cl);
}
@@ -1047,303 +1032,4 @@ public final class StringConcatFactory {
// no instantiation
}
- /**
- * Simplified concatenation method to facilitate {@link StringTemplate}
- * concatenation. This method returns a single concatenation method that
- * interleaves fragments and values. fragment|value|fragment|value|...|value|fragment.
- * The number of fragments must be one more that the number of ptypes.
- * The total number of slots used by the ptypes must be less than or equal
- * to {@link #MAX_INDY_CONCAT_ARG_SLOTS}.
- *
- * @param fragments list of string fragments
- * @param ptypes list of expression types
- *
- * @return the {@link MethodHandle} for concatenation
- *
- * @throws StringConcatException If any of the linkage invariants are violated.
- * @throws NullPointerException If any of the incoming arguments is null.
- * @throws IllegalArgumentException If the number of value slots exceed {@link #MAX_INDY_CONCAT_ARG_SLOTS}.
- *
- * @since 21
- */
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- public static MethodHandle makeConcatWithTemplate(
- List fragments,
- List> ptypes)
- throws StringConcatException
- {
- Objects.requireNonNull(fragments, "fragments is null");
- Objects.requireNonNull(ptypes, "ptypes is null");
- ptypes = List.copyOf(ptypes);
-
- if (fragments.size() != ptypes.size() + 1) {
- throw new IllegalArgumentException("fragments size not equal ptypes size plus one");
- }
-
- if (ptypes.isEmpty()) {
- return MethodHandles.constant(String.class, fragments.get(0));
- }
-
- Class>[] ttypes = new Class>[ptypes.size()];
- MethodHandle[] filters = new MethodHandle[ptypes.size()];
- int slots = 0;
-
- int pos = 0;
- for (Class> ptype : ptypes) {
- slots += ptype == long.class || ptype == double.class ? 2 : 1;
-
- if (MAX_INDY_CONCAT_ARG_SLOTS < slots) {
- throw new StringConcatException("Too many concat argument slots: " +
- slots + ", can only accept " + MAX_INDY_CONCAT_ARG_SLOTS);
- }
-
- boolean isSpecialized = ptype.isPrimitive();
- boolean isFormatConcatItem = FormatConcatItem.class.isAssignableFrom(ptype);
- Class> ttype = isSpecialized ? promoteToIntType(ptype) :
- isFormatConcatItem ? FormatConcatItem.class : Object.class;
- MethodHandle filter = isFormatConcatItem ? null : stringifierFor(ttype);
-
- if (filter != null) {
- filters[pos] = filter;
- ttype = String.class;
- }
-
- ttypes[pos++] = ttype;
- }
-
- MethodHandle mh = MethodHandles.dropArguments(newString(), 2, ttypes);
-
- long initialLengthCoder = INITIAL_CODER;
- pos = 0;
- for (String fragment : fragments) {
- initialLengthCoder = JLA.stringConcatMix(initialLengthCoder, fragment);
-
- if (ttypes.length <= pos) {
- break;
- }
-
- Class> ttype = ttypes[pos];
- // (long,byte[],ttype) -> long
- MethodHandle prepender = prepender(fragment, ttype);
- // (byte[],long,ttypes...) -> String (unchanged)
- mh = MethodHandles.filterArgumentsWithCombiner(mh, 1, prepender,1, 0, 2 + pos);
-
- pos++;
- }
-
- String lastFragment = fragments.getLast();
- initialLengthCoder -= lastFragment.length();
- MethodHandle newArrayCombinator = lastFragment.isEmpty() ? newArray() :
- newArrayWithSuffix(lastFragment);
- // (long,ttypes...) -> String
- mh = MethodHandles.foldArgumentsWithCombiner(mh, 0, newArrayCombinator,
- 1 // index
- );
-
- pos = 0;
- for (Class> ttype : ttypes) {
- // (long,ttype) -> long
- MethodHandle mix = mixer(ttypes[pos]);
- boolean lastPType = pos == ttypes.length - 1;
-
- if (lastPType) {
- // (ttype) -> long
- mix = MethodHandles.insertArguments(mix, 0, initialLengthCoder);
- // (ttypes...) -> String
- mh = MethodHandles.foldArgumentsWithCombiner(mh, 0, mix,
- 1 + pos // selected argument
- );
- } else {
- // (long,ttypes...) -> String
- mh = MethodHandles.filterArgumentsWithCombiner(mh, 0, mix,
- 0, // old-index
- 1 + pos // selected argument
- );
- }
-
- pos++;
- }
-
- mh = MethodHandles.filterArguments(mh, 0, filters);
- MethodType mt = MethodType.methodType(String.class, ptypes);
- mh = mh.viewAsType(mt, true);
-
- return mh;
- }
-
- /**
- * This method breaks up large concatenations into separate
- * {@link MethodHandle MethodHandles} based on the number of slots required
- * per {@link MethodHandle}. Each {@link MethodHandle} after the first will
- * have an extra {@link String} slot for the result from the previous
- * {@link MethodHandle}.
- * {@link #makeConcatWithTemplate}
- * is used to construct the {@link MethodHandle MethodHandles}. The total
- * number of slots used by the ptypes is open ended. However, care must
- * be given when combining the {@link MethodHandle MethodHandles} so that
- * the combine total does not exceed the 255 slot limit.
- *
- * @param fragments list of string fragments
- * @param ptypes list of expression types
- * @param maxSlots maximum number of slots per {@link MethodHandle}.
- *
- * @return List of {@link MethodHandle MethodHandles}
- *
- * @throws IllegalArgumentException If maxSlots is not between 1 and
- * MAX_INDY_CONCAT_ARG_SLOTS.
- * @throws StringConcatException If any of the linkage invariants are violated.
- * @throws NullPointerException If any of the incoming arguments is null.
- * @throws IllegalArgumentException If the number of value slots exceed {@link #MAX_INDY_CONCAT_ARG_SLOTS}.
- *
- * @since 21
- */
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- public static List makeConcatWithTemplateCluster(
- List fragments,
- List> ptypes,
- int maxSlots)
- throws StringConcatException
- {
- Objects.requireNonNull(fragments, "fragments is null");
- Objects.requireNonNull(ptypes, "ptypes is null");
-
- if (fragments.size() != ptypes.size() + 1) {
- throw new StringConcatException("fragments size not equal ptypes size plus one");
- }
-
- if (maxSlots < 1 || MAX_INDY_CONCAT_ARG_SLOTS < maxSlots) {
- throw new IllegalArgumentException("maxSlots must be between 1 and " +
- MAX_INDY_CONCAT_ARG_SLOTS);
-
- }
-
- if (ptypes.isEmpty()) {
- return List.of(MethodHandles.constant(String.class, fragments.get(0)));
- }
-
- List mhs = new ArrayList<>();
- List fragmentsSection = new ArrayList<>();
- List> ptypeSection = new ArrayList<>();
- int slots = 0;
-
- int pos = 0;
- for (Class> ptype : ptypes) {
- boolean lastPType = pos == ptypes.size() - 1;
- fragmentsSection.add(fragments.get(pos));
- ptypeSection.add(ptype);
-
- slots += ptype == long.class || ptype == double.class ? 2 : 1;
-
- if (maxSlots <= slots || lastPType) {
- fragmentsSection.add(lastPType ? fragments.get(pos + 1) : "");
- MethodHandle mh = makeConcatWithTemplate(fragmentsSection,
- ptypeSection);
- mhs.add(mh);
- fragmentsSection.clear();
- fragmentsSection.add("");
- ptypeSection.clear();
- ptypeSection.add(String.class);
- slots = 1;
- }
-
- pos++;
- }
-
- return mhs;
- }
-
- /**
- * This method creates a {@link MethodHandle} expecting one input, the
- * receiver of the supplied getters. This method uses
- * {@link #makeConcatWithTemplateCluster}
- * to create the intermediate {@link MethodHandle MethodHandles}.
- *
- * @param fragments list of string fragments
- * @param getters list of getter {@link MethodHandle MethodHandles}
- * @param maxSlots maximum number of slots per {@link MethodHandle} in
- * cluster.
- *
- * @return the {@link MethodHandle} for concatenation
- *
- * @throws IllegalArgumentException If maxSlots is not between 1 and
- * MAX_INDY_CONCAT_ARG_SLOTS or if the
- * getters don't use the same argument type
- * @throws StringConcatException If any of the linkage invariants are violated
- * @throws NullPointerException If any of the incoming arguments is null
- * @throws IllegalArgumentException If the number of value slots exceed {@link #MAX_INDY_CONCAT_ARG_SLOTS}.
- *
- * @since 21
- */
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
- public static MethodHandle makeConcatWithTemplateGetters(
- List fragments,
- List getters,
- int maxSlots)
- throws StringConcatException
- {
- Objects.requireNonNull(fragments, "fragments is null");
- Objects.requireNonNull(getters, "getters is null");
-
- if (fragments.size() != getters.size() + 1) {
- throw new StringConcatException("fragments size not equal getters size plus one");
- }
-
- if (maxSlots < 1 || MAX_INDY_CONCAT_ARG_SLOTS < maxSlots) {
- throw new IllegalArgumentException("maxSlots must be between 1 and " +
- MAX_INDY_CONCAT_ARG_SLOTS);
-
- }
-
- if (getters.size() == 0) {
- throw new StringConcatException("no getters supplied");
- }
-
- Class> receiverType = null;
- List> ptypes = new ArrayList<>();
-
- for (MethodHandle getter : getters) {
- MethodType mt = getter.type();
- Class> returnType = mt.returnType();
-
- if (returnType == void.class || mt.parameterCount() != 1) {
- throw new StringConcatException("not a getter " + mt);
- }
-
- if (receiverType == null) {
- receiverType = mt.parameterType(0);
- } else if (receiverType != mt.parameterType(0)) {
- throw new StringConcatException("not the same receiever type " +
- mt + " needs " + receiverType);
- }
-
- ptypes.add(returnType);
- }
-
- MethodType resultType = MethodType.methodType(String.class, receiverType);
- List clusters = makeConcatWithTemplateCluster(fragments, ptypes,
- maxSlots);
-
- MethodHandle mh = null;
- Iterator getterIterator = getters.iterator();
-
- for (MethodHandle cluster : clusters) {
- MethodType mt = cluster.type();
- MethodHandle[] filters = new MethodHandle[mt.parameterCount()];
- int pos = 0;
-
- if (mh != null) {
- filters[pos++] = mh;
- }
-
- while (pos < filters.length) {
- filters[pos++] = getterIterator.next();
- }
-
- cluster = MethodHandles.filterArguments(cluster, 0, filters);
- mh = MethodHandles.permuteArguments(cluster, resultType,
- new int[filters.length]);
- }
-
- return mh;
- }
}
diff --git a/src/java.base/share/classes/java/lang/runtime/StringTemplateImpl.java b/src/java.base/share/classes/java/lang/runtime/StringTemplateImpl.java
deleted file mode 100644
index be510fe62b0..00000000000
--- a/src/java.base/share/classes/java/lang/runtime/StringTemplateImpl.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package java.lang.runtime;
-
-import java.lang.invoke.MethodHandle;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * This class implements specialized {@link StringTemplate StringTemplates} produced by
- * string template bootstrap method callsites generated by the compiler. Instances of this
- * class are produced by {@link StringTemplateImplFactory}.
- *
- * Values are stored by subclassing {@link Carriers.CarrierObject}. This allows specializations
- * and sharing of value shapes without creating a new class for each shape.
- *
- * {@link StringTemplate} fragments are shared via binding to the
- * {@link java.lang.invoke.CallSite CallSite's} {@link MethodHandle}.
- *
- * The {@link StringTemplateImpl} instance also carries
- * specialized {@link MethodHandle MethodHandles} for producing the values list and interpolation.
- * These {@link MethodHandle MethodHandles} are also shared by binding to the
- * {@link java.lang.invoke.CallSite CallSite}.
- *
- * @since 21
- *
- * Warning: This class is part of PreviewFeature.Feature.STRING_TEMPLATES.
- * Do not rely on its availability.
- */
-final class StringTemplateImpl extends Carriers.CarrierObject implements StringTemplate {
- /**
- * List of string fragments for the string template. This value of this list is shared by
- * all instances created at the {@link java.lang.invoke.CallSite CallSite}.
- */
- private final List fragments;
-
- /**
- * Specialized {@link MethodHandle} used to implement the {@link StringTemplate StringTemplate's}
- * {@code values} method. This {@link MethodHandle} is shared by all instances created at the
- * {@link java.lang.invoke.CallSite CallSite}.
- */
- private final MethodHandle valuesMH;
-
- /**
- * Specialized {@link MethodHandle} used to implement the {@link StringTemplate StringTemplate's}
- * {@code interpolate} method. This {@link MethodHandle} is shared by all instances created at the
- * {@link java.lang.invoke.CallSite CallSite}.
- */
- private final MethodHandle interpolateMH;
-
- /**
- * Constructor.
- *
- * @param primitiveCount number of primitive slots required (bound at callsite)
- * @param objectCount number of object slots required (bound at callsite)
- * @param fragments list of string fragments (bound in (bound at callsite)
- * @param valuesMH {@link MethodHandle} to produce list of values (bound at callsite)
- * @param interpolateMH {@link MethodHandle} to produce interpolation (bound at callsite)
- */
- StringTemplateImpl(int primitiveCount, int objectCount,
- List fragments, MethodHandle valuesMH, MethodHandle interpolateMH) {
- super(primitiveCount, objectCount);
- this.fragments = fragments;
- this.valuesMH = valuesMH;
- this.interpolateMH = interpolateMH;
- }
-
- @Override
- public List fragments() {
- return fragments;
- }
-
- @Override
- public List values() {
- try {
- return (List)valuesMH.invokeExact(this);
- } catch (RuntimeException | Error ex) {
- throw ex;
- } catch (Throwable ex) {
- throw new RuntimeException("string template values failure", ex);
- }
- }
-
- @Override
- public String interpolate() {
- try {
- return (String)interpolateMH.invokeExact(this);
- } catch (RuntimeException | Error ex) {
- throw ex;
- } catch (Throwable ex) {
- throw new RuntimeException("string template interpolate failure", ex);
- }
- }
-
- @Override
- public boolean equals(Object other) {
- return other instanceof StringTemplate st &&
- Objects.equals(fragments(), st.fragments()) &&
- Objects.equals(values(), st.values());
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(fragments(), values());
- }
-
- @Override
- public String toString() {
- return StringTemplate.toString(this);
- }
-}
diff --git a/src/java.base/share/classes/java/lang/runtime/StringTemplateImplFactory.java b/src/java.base/share/classes/java/lang/runtime/StringTemplateImplFactory.java
deleted file mode 100644
index a8e1f1f347b..00000000000
--- a/src/java.base/share/classes/java/lang/runtime/StringTemplateImplFactory.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package java.lang.runtime;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.StringConcatException;
-import java.lang.invoke.StringConcatFactory;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * This class synthesizes {@link StringTemplate StringTemplates} based on
- * fragments and bootstrap method type. Usage is primarily from
- * {@link java.lang.runtime.TemplateRuntime}.
- *
- * @since 21
- *
- * Warning: This class is part of PreviewFeature.Feature.STRING_TEMPLATES.
- * Do not rely on its availability.
- */
-final class StringTemplateImplFactory {
-
- /**
- * Private constructor.
- */
- StringTemplateImplFactory() {
- throw new AssertionError("private constructor");
- }
-
- /*
- * {@link StringTemplateImpl} constructor MethodHandle.
- */
- private static final MethodHandle CONSTRUCTOR;
-
-
- /*
- * Frequently used method types.
- */
- private static final MethodType MT_STRING_STIMPL =
- MethodType.methodType(String.class, StringTemplateImpl.class);
- private static final MethodType MT_LIST_STIMPL =
- MethodType.methodType(List.class, StringTemplateImpl.class);
-
- /**
- * List (for nullable) of MethodHandle;
- */
- private static final MethodHandle TO_LIST;
-
- static {
- try {
- MethodHandles.Lookup lookup = MethodHandles.lookup();
-
- MethodType mt = MethodType.methodType(void.class, int.class, int.class, List.class,
- MethodHandle.class, MethodHandle.class);
- CONSTRUCTOR = lookup.findConstructor(StringTemplateImpl.class, mt)
- .asType(mt.changeReturnType(Carriers.CarrierObject.class));
-
- mt = MethodType.methodType(List.class, Object[].class);
- TO_LIST = lookup.findStatic(StringTemplateImplFactory.class, "toList", mt);
- } catch(ReflectiveOperationException ex) {
- throw new AssertionError("carrier static init fail", ex);
- }
- }
-
- /**
- * Create a new {@link StringTemplateImpl} constructor.
- *
- * @param fragments string template fragments
- * @param type values types with StringTemplate return
- *
- * @return {@link MethodHandle} that can construct a {@link StringTemplateImpl} with arguments
- * used as values.
- */
- static MethodHandle createStringTemplateImplMH(List fragments, MethodType type) {
- Carriers.CarrierElements elements = Carriers.CarrierFactory.of(type);
- MethodHandle[] components = elements
- .components()
- .stream()
- .map(c -> c.asType(c.type().changeParameterType(0, StringTemplateImpl.class)))
- .toArray(MethodHandle[]::new);
- Class>[] ptypes = elements
- .components()
- .stream()
- .map(c -> c.type().returnType())
- .toArray(Class>[]::new);
- int[] permute = new int[ptypes.length];
-
- MethodHandle interpolateMH;
- MethodType mt;
- try {
- interpolateMH = StringConcatFactory.makeConcatWithTemplate(fragments, List.of(ptypes));
- } catch (StringConcatException ex) {
- throw new RuntimeException("constructing internal string template", ex);
- }
- interpolateMH = MethodHandles.filterArguments(interpolateMH, 0, components);
- interpolateMH = MethodHandles.permuteArguments(interpolateMH, MT_STRING_STIMPL, permute);
-
- mt = MethodType.methodType(List.class, ptypes);
- MethodHandle valuesMH = TO_LIST.asCollector(Object[].class, components.length).asType(mt);
- valuesMH = MethodHandles.filterArguments(valuesMH, 0, components);
- valuesMH = MethodHandles.permuteArguments(valuesMH, MT_LIST_STIMPL, permute);
-
- MethodHandle constructor = MethodHandles.insertArguments(CONSTRUCTOR, 0,
- elements.primitiveCount(), elements.objectCount(),
- fragments, valuesMH, interpolateMH);
- constructor = MethodHandles.foldArguments(elements.initializer(), 0, constructor);
-
- mt = MethodType.methodType(StringTemplate.class, ptypes);
- constructor = constructor.asType(mt);
-
- return constructor;
- }
-
- /**
- * Generic {@link StringTemplate}.
- *
- * @param fragments immutable list of string fragments from string template
- * @param values immutable list of expression values
- */
- private record SimpleStringTemplate(List fragments, List values)
- implements StringTemplate {
- @Override
- public String toString() {
- return StringTemplate.toString(this);
- }
- }
-
- /**
- * Returns a new StringTemplate composed from fragments and values.
- *
- * @param fragments array of string fragments
- * @param values array of expression values
- *
- * @return StringTemplate composed from fragments and values
- */
- static StringTemplate newTrustedStringTemplate(String[] fragments, Object[] values) {
- return new SimpleStringTemplate(List.of(fragments), toList(values));
- }
-
- /**
- * Returns a new StringTemplate composed from fragments and values.
- *
- * @param fragments list of string fragments
- * @param values array of expression values
- *
- * @return StringTemplate composed from fragments and values
- */
- static StringTemplate newTrustedStringTemplate(List fragments, Object[] values) {
- return new SimpleStringTemplate(List.copyOf(fragments), toList(values));
- }
-
- /**
- * Returns a new StringTemplate composed from fragments and values.
- *
- * @param fragments list of string fragments
- * @param values list of expression values
- *
- * @return StringTemplate composed from fragments and values
- */
-
- static StringTemplate newStringTemplate(List fragments, List> values) {
- @SuppressWarnings("unchecked")
- List copy = (List)values.stream().toList();
- return new SimpleStringTemplate(List.copyOf(fragments), copy);
- }
-
- /**
- * Collect nullable elements from an array into a unmodifiable list.
- * Elements are guaranteed to be safe.
- *
- * @param elements elements to place in list
- *
- * @return unmodifiable list.
- */
- private static List toList(Object[] elements) {
- return Arrays.stream(elements).toList();
- }
-
-}
diff --git a/src/java.base/share/classes/java/lang/runtime/TemplateRuntime.java b/src/java.base/share/classes/java/lang/runtime/TemplateRuntime.java
deleted file mode 100644
index 5b41fdb506f..00000000000
--- a/src/java.base/share/classes/java/lang/runtime/TemplateRuntime.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package java.lang.runtime;
-
-import java.lang.invoke.CallSite;
-import java.lang.invoke.ConstantCallSite;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.StringTemplate.Processor;
-import java.lang.StringTemplate.Processor.Linkage;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-import jdk.internal.access.JavaTemplateAccess;
-import jdk.internal.access.SharedSecrets;
-import jdk.internal.javac.PreviewFeature;
-
-/**
- * Manages string template bootstrap methods. These methods may be used, for example,
- * by Java compiler implementations to create {@link StringTemplate} instances. For example,
- * the java compiler will translate the following code;
- * {@snippet :
- * int x = 10;
- * int y = 20;
- * StringTemplate st = RAW."\{x} + \{y} = \{x + y}";
- * }
- * to byte code that invokes the {@link java.lang.runtime.TemplateRuntime#newStringTemplate}
- * bootstrap method to construct a {@link CallSite} that accepts two integers and produces a new
- * {@link StringTemplate} instance.
- * {@snippet :
- * MethodHandles.Lookup lookup = MethodHandles.lookup();
- * MethodType mt = MethodType.methodType(StringTemplate.class, int.class, int.class);
- * CallSite cs = TemplateRuntime.newStringTemplate(lookup, "", mt, "", " + ", " = ", "");
- * ...
- * int x = 10;
- * int y = 20;
- * StringTemplate st = (StringTemplate)cs.getTarget().invokeExact(x, y);
- * }
- * If the string template requires more than
- * {@link java.lang.invoke.StringConcatFactory#MAX_INDY_CONCAT_ARG_SLOTS} value slots,
- * then the java compiler will use the
- * {@link java.lang.runtime.TemplateRuntime#newLargeStringTemplate} bootstrap method
- * instead. For example, the java compiler will translate the following code;
- * {@snippet :
- * int[] a = new int[1000], b = new int[1000];
- * ...
- * StringTemplate st = """
- * \{a[0]} - \{b[0]}
- * \{a[1]} - \{b[1]}
- * ...
- * \{a[999]} - \{b[999]}
- * """;
- * }
- * to byte code that invokes the {@link java.lang.runtime.TemplateRuntime#newLargeStringTemplate}
- * bootstrap method to construct a {@link CallSite} that accepts an array of integers and produces a new
- * {@link StringTemplate} instance.
- * {@snippet :
- * MethodType mt = MethodType.methodType(StringTemplate.class, String[].class, Object[].class);
- * CallSite cs = TemplateRuntime.newStringTemplate(lookup, "", mt);
- * ...
- * int[] a = new int[1000], b = new int[1000];
- * ...
- * StringTemplate st = (StringTemplate)cs.getTarget().invokeExact(
- * new String[] { "", " - ", "\n", " - ", "\n", ... " - ", "\n" },
- * new Object[] { a[0], b[0], a[1], b[1], ..., a[999], b[999]}
- * );
- * }
- *
- * @since 21
- */
-@PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
-public final class TemplateRuntime {
- private static final JavaTemplateAccess JTA = SharedSecrets.getJavaTemplateAccess();
-
- /**
- * {@link MethodHandle} to {@link TemplateRuntime#defaultProcess}.
- */
- private static final MethodHandle DEFAULT_PROCESS_MH;
-
- /**
- * {@link MethodHandle} to {@link TemplateRuntime#newTrustedStringTemplate}.
- */
- private static final MethodHandle NEW_TRUSTED_STRING_TEMPLATE;
-
- /**
- * Initialize {@link MethodHandle MethodHandles}.
- */
- static {
- try {
- MethodHandles.Lookup lookup = MethodHandles.lookup();
-
- MethodType mt = MethodType.methodType(Object.class,
- List.class, Processor.class, Object[].class);
- DEFAULT_PROCESS_MH =
- lookup.findStatic(TemplateRuntime.class, "defaultProcess", mt);
-
- mt = MethodType.methodType(StringTemplate.class, String[].class, Object[].class);
- NEW_TRUSTED_STRING_TEMPLATE =
- lookup.findStatic(StringTemplateImplFactory.class, "newTrustedStringTemplate", mt);
- } catch (ReflectiveOperationException ex) {
- throw new AssertionError("string bootstrap fail", ex);
- }
- }
-
- /**
- * Private constructor.
- */
- private TemplateRuntime() {
- throw new AssertionError("private constructor");
- }
-
- /**
- * String template bootstrap method for creating string templates.
- * The static arguments include the fragments list.
- * The non-static arguments are the values.
- *
- * @param lookup method lookup from call site
- * @param name method name - not used
- * @param type method type
- * (ptypes...) -> StringTemplate
- * @param fragments fragment array for string template
- *
- * @return {@link CallSite} to handle create string template
- *
- * @throws NullPointerException if any of the arguments is null
- * @throws Throwable if linkage fails
- */
- public static CallSite newStringTemplate(MethodHandles.Lookup lookup,
- String name,
- MethodType type,
- String... fragments) throws Throwable {
- Objects.requireNonNull(lookup, "lookup is null");
- Objects.requireNonNull(name, "name is null");
- Objects.requireNonNull(type, "type is null");
- Objects.requireNonNull(fragments, "fragments is null");
-
- MethodHandle mh = StringTemplateImplFactory
- .createStringTemplateImplMH(List.of(fragments), type).asType(type);
-
- return new ConstantCallSite(mh);
- }
-
- /**
- * String template bootstrap method for creating large string templates,
- * i.e., when the number of value slots exceeds
- * {@link java.lang.invoke.StringConcatFactory#MAX_INDY_CONCAT_ARG_SLOTS}.
- * The non-static arguments are the fragments array and values array.
- *
- * @param lookup method lookup from call site
- * @param name method name - not used
- * @param type method type
- * (String[], Object[]) -> StringTemplate
- *
- * @return {@link CallSite} to handle create large string template
- *
- * @throws NullPointerException if any of the arguments is null
- * @throws Throwable if linkage fails
- */
- public static CallSite newLargeStringTemplate(MethodHandles.Lookup lookup,
- String name,
- MethodType type) throws Throwable {
- Objects.requireNonNull(lookup, "lookup is null");
- Objects.requireNonNull(name, "name is null");
- Objects.requireNonNull(type, "type is null");
-
- return new ConstantCallSite(NEW_TRUSTED_STRING_TEMPLATE.asType(type));
- }
-
- /**
- * String template bootstrap method for static final processors.
- * The static arguments include the fragments array and a {@link MethodHandle}
- * to retrieve the value of the static final processor.
- * The non-static arguments are the values.
- *
- * @param lookup method lookup from call site
- * @param name method name - not used
- * @param type method type
- * (ptypes...) -> Object
- * @param processorGetter {@link MethodHandle} to get static final processor
- * @param fragments fragments from string template
- *
- * @return {@link CallSite} to handle string template processing
- *
- * @throws NullPointerException if any of the arguments is null
- * @throws Throwable if linkage fails
- *
- * @implNote this method is likely to be revamped before exiting preview.
- */
- public static CallSite processStringTemplate(MethodHandles.Lookup lookup,
- String name,
- MethodType type,
- MethodHandle processorGetter,
- String... fragments) throws Throwable {
- Objects.requireNonNull(lookup, "lookup is null");
- Objects.requireNonNull(name, "name is null");
- Objects.requireNonNull(type, "type is null");
- Objects.requireNonNull(processorGetter, "processorGetter is null");
- Objects.requireNonNull(fragments, "fragments is null");
-
- Processor, ?> processor = (Processor, ?>)processorGetter.invoke();
- MethodHandle mh = processor instanceof Linkage linkage
- ? linkage.linkage(List.of(fragments), type)
- : defaultProcessMethodHandle(type, processor, List.of(fragments));
-
- return new ConstantCallSite(mh);
- }
-
- /**
- * Creates a simple {@link StringTemplate} and then invokes the processor's process method.
- *
- * @param fragments fragments from string template
- * @param processor {@link Processor} to process
- * @param values array of expression values
- *
- * @return result of processing the string template
- *
- * @throws Throwable when {@link Processor#process(StringTemplate)} throws
- */
- private static Object defaultProcess(
- List fragments,
- Processor, ?> processor,
- Object[] values
- ) throws Throwable {
- return processor.process(StringTemplate.of(fragments, Arrays.stream(values).toList()));
- }
-
- /**
- * Generate a {@link MethodHandle} which is effectively invokes
- * {@code processor.process(new StringTemplate(fragments, values...)}.
- *
- * @return default process {@link MethodHandle}
- */
- private static MethodHandle defaultProcessMethodHandle(
- MethodType type,
- Processor, ?> processor,
- List fragments
- ) {
- MethodHandle mh = MethodHandles.insertArguments(DEFAULT_PROCESS_MH, 0, fragments, processor);
- return mh.asCollector(Object[].class, type.parameterCount()).asType(type);
- }
-}
-
diff --git a/src/java.base/share/classes/java/lang/runtime/TemplateSupport.java b/src/java.base/share/classes/java/lang/runtime/TemplateSupport.java
deleted file mode 100644
index a754e69d794..00000000000
--- a/src/java.base/share/classes/java/lang/runtime/TemplateSupport.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package java.lang.runtime;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-
-import jdk.internal.access.JavaLangAccess;
-import jdk.internal.access.JavaTemplateAccess;
-import jdk.internal.access.SharedSecrets;
-
-/**
- * This class provides runtime support for string templates. The methods within
- * are intended for internal use only.
- *
- * @since 21
- *
- * Warning: This class is part of PreviewFeature.Feature.STRING_TEMPLATES.
- * Do not rely on its availability.
- */
-final class TemplateSupport implements JavaTemplateAccess {
-
- /**
- * Private constructor.
- */
- private TemplateSupport() {
- }
-
- static {
- SharedSecrets.setJavaTemplateAccess(new TemplateSupport());
- }
-
- private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
-
- /**
- * Returns a StringTemplate composed from fragments and values.
- *
- * @implSpec The {@code fragments} list size must be one more that the
- * {@code values} list size.
- *
- * @param fragments list of string fragments
- * @param values list of expression values
- *
- * @return StringTemplate composed from fragments and values
- *
- * @throws IllegalArgumentException if fragments list size is not one more
- * than values list size
- * @throws NullPointerException if fragments is null or values is null or if any fragment is null.
- *
- * @implNote Contents of both lists are copied to construct immutable lists.
- */
- @Override
- public StringTemplate of(List fragments, List> values) {
- return StringTemplateImplFactory.newStringTemplate(fragments, values);
- }
-
- /**
- * Creates a string that interleaves the elements of values between the
- * elements of fragments.
- *
- * @param fragments list of String fragments
- * @param values list of expression values
- *
- * @return String interpolation of fragments and values
- */
- @Override
- public String interpolate(List fragments, List> values) {
- int fragmentsSize = fragments.size();
- int valuesSize = values.size();
- if (fragmentsSize == 1) {
- return fragments.get(0);
- }
- int size = fragmentsSize + valuesSize;
- String[] strings = new String[size];
- int i = 0, j = 0;
- for (; j < valuesSize; j++) {
- strings[i++] = fragments.get(j);
- strings[i++] = String.valueOf(values.get(j));
- }
- strings[i] = fragments.get(j);
- return JLA.join("", "", "", strings, size);
- }
-
- /**
- * Combine one or more {@link StringTemplate StringTemplates} to produce a combined {@link StringTemplate}.
- * {@snippet :
- * StringTemplate st = StringTemplate.combine("\{a}", "\{b}", "\{c}");
- * assert st.interpolate().equals("\{a}\{b}\{c}");
- * }
- *
- * @param sts zero or more {@link StringTemplate}
- *
- * @return combined {@link StringTemplate}
- *
- * @throws NullPointerException if sts is null or if any element of sts is null
- */
- @Override
- public StringTemplate combine(StringTemplate... sts) {
- Objects.requireNonNull(sts, "sts must not be null");
- if (sts.length == 0) {
- return StringTemplate.of("");
- } else if (sts.length == 1) {
- return Objects.requireNonNull(sts[0], "string templates should not be null");
- }
- int size = 0;
- for (StringTemplate st : sts) {
- Objects.requireNonNull(st, "string templates should not be null");
- size += st.values().size();
- }
- String[] combinedFragments = new String[size + 1];
- Object[] combinedValues = new Object[size];
- combinedFragments[0] = "";
- int fragmentIndex = 1;
- int valueIndex = 0;
- for (StringTemplate st : sts) {
- Iterator iterator = st.fragments().iterator();
- combinedFragments[fragmentIndex - 1] += iterator.next();
- while (iterator.hasNext()) {
- combinedFragments[fragmentIndex++] = iterator.next();
- }
- for (Object value : st.values()) {
- combinedValues[valueIndex++] = value;
- }
- }
- return StringTemplateImplFactory.newTrustedStringTemplate(combinedFragments, combinedValues);
- }
-
-}
diff --git a/src/java.base/share/classes/java/util/FormatItem.java b/src/java.base/share/classes/java/util/FormatItem.java
deleted file mode 100644
index adf8ef9ddd3..00000000000
--- a/src/java.base/share/classes/java/util/FormatItem.java
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package java.util;
-
-import java.io.IOException;
-import java.lang.invoke.*;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.nio.ByteOrder;
-import java.nio.charset.StandardCharsets;
-import java.text.DecimalFormatSymbols;
-import java.util.Formatter.FormatSpecifier;
-
-import jdk.internal.access.JavaLangAccess;
-import jdk.internal.access.SharedSecrets;
-import jdk.internal.util.FormatConcatItem;
-import jdk.internal.util.DecimalDigits;
-import jdk.internal.util.HexDigits;
-import jdk.internal.util.OctalDigits;
-
-import static java.lang.invoke.MethodType.methodType;
-
-/**
- * A specialized objects used by FormatterBuilder that knows how to insert
- * themselves into a concatenation performed by StringConcatFactory.
- *
- * @since 21
- *
- * Warning: This class is part of PreviewFeature.Feature.STRING_TEMPLATES.
- * Do not rely on its availability.
- */
-class FormatItem {
- private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
-
- private static final MethodHandle CHAR_MIX =
- JLA.stringConcatHelper("mix",
- MethodType.methodType(long.class, long.class,char.class));
-
- private static final MethodHandle STRING_PREPEND =
- JLA.stringConcatHelper("prepend",
- MethodType.methodType(long.class, long.class, byte[].class,
- String.class));
-
- private static final MethodHandle SELECT_GETCHAR_MH =
- JLA.stringConcatHelper("selectGetChar",
- MethodType.methodType(MethodHandle.class, long.class));
-
- private static final MethodHandle SELECT_PUTCHAR_MH =
- JLA.stringConcatHelper("selectPutChar",
- MethodType.methodType(MethodHandle.class, long.class));
-
- private static long charMix(long lengthCoder, char value) {
- try {
- return (long)CHAR_MIX.invokeExact(lengthCoder, value);
- } catch (Error | RuntimeException ex) {
- throw ex;
- } catch (Throwable ex) {
- throw new RuntimeException(ex);
- }
- }
-
- private static long stringMix(long lengthCoder, String value) {
- return JLA.stringConcatMix(lengthCoder, value);
- }
-
- private static long stringPrepend(long lengthCoder, byte[] buffer,
- String value) throws Throwable {
- return (long)STRING_PREPEND.invokeExact(lengthCoder, buffer, value);
- }
-
- private static MethodHandle selectGetChar(long indexCoder) throws Throwable {
- return (MethodHandle)SELECT_GETCHAR_MH.invokeExact(indexCoder);
- }
-
- private static MethodHandle selectPutChar(long indexCoder) throws Throwable {
- return (MethodHandle)SELECT_PUTCHAR_MH.invokeExact(indexCoder);
- }
-
- private static final MethodHandle PUT_CHAR_DIGIT;
-
- static {
- try {
- Lookup lookup = MethodHandles.lookup();
- PUT_CHAR_DIGIT = lookup.findStatic(FormatItem.class, "putByte",
- MethodType.methodType(void.class,
- byte[].class, int.class, int.class));
- } catch (ReflectiveOperationException ex) {
- throw new AssertionError("putByte lookup failed", ex);
- }
- }
-
- private static void putByte(byte[] buffer, int index, int ch) {
- buffer[index] = (byte)ch;
- }
-
- private FormatItem() {
- throw new AssertionError("private constructor");
- }
-
- /**
- * Decimal value format item.
- */
- static final class FormatItemDecimal implements FormatConcatItem {
- private final char groupingSeparator;
- private final char zeroDigit;
- private final char minusSign;
- private final int digitOffset;
- private final byte[] digits;
- private final int length;
- private final boolean isNegative;
- private final int width;
- private final byte prefixSign;
- private final int groupSize;
- private final long value;
- private final boolean parentheses;
-
- FormatItemDecimal(DecimalFormatSymbols dfs, int width, char sign,
- boolean parentheses, int groupSize, long value) throws Throwable {
- this.groupingSeparator = dfs.getGroupingSeparator();
- this.zeroDigit = dfs.getZeroDigit();
- this.minusSign = dfs.getMinusSign();
- this.digitOffset = this.zeroDigit - '0';
- int length = DecimalDigits.INSTANCE.size(value);
- this.digits = new byte[length];
- DecimalDigits.INSTANCE.digits(value, this.digits, length, PUT_CHAR_DIGIT);
- this.isNegative = value < 0L;
- this.length = this.isNegative ? length - 1 : length;
- this.width = width;
- this.groupSize = groupSize;
- this.value = value;
- this.parentheses = parentheses && isNegative;
- this.prefixSign = (byte)(isNegative ? (parentheses ? '\0' : minusSign) : sign);
- }
-
- private int signLength() {
- return (prefixSign != '\0' ? 1 : 0) + (parentheses ? 2 : 0);
- }
-
- private int groupLength() {
- return 0 < groupSize ? (length - 1) / groupSize : 0;
- }
-
- @Override
- public long mix(long lengthCoder) {
- return JLA.stringConcatCoder(zeroDigit) |
- (lengthCoder +
- Integer.max(length + signLength() + groupLength(), width));
- }
-
- @Override
- public long prepend(long lengthCoder, byte[] buffer) throws Throwable {
- MethodHandle putCharMH = selectPutChar(lengthCoder);
-
- if (parentheses) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)')');
- }
-
- if (0 < groupSize) {
- int groupIndex = groupSize;
-
- for (int i = 1; i <= length; i++) {
- if (groupIndex-- == 0) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder,
- (int)groupingSeparator);
- groupIndex = groupSize - 1;
- }
-
- putCharMH.invokeExact(buffer, (int)--lengthCoder,
- digits[digits.length - i] + digitOffset);
- }
- } else {
- for (int i = 1; i <= length; i++) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder,
- digits[digits.length - i] + digitOffset);
- }
- }
-
- for (int i = length + signLength() + groupLength(); i < width; i++) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'0');
- }
-
- if (parentheses) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'(');
- }
- if (prefixSign != '\0') {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)prefixSign);
- }
-
- return lengthCoder;
- }
- }
-
- /**
- * Hexadecimal format item.
- */
- static final class FormatItemHexadecimal implements FormatConcatItem {
- private final int width;
- private final boolean hasPrefix;
- private final long value;
- private final int length;
-
- FormatItemHexadecimal(int width, boolean hasPrefix, long value) {
- this.width = width;
- this.hasPrefix = hasPrefix;
- this.value = value;
- this.length = HexDigits.INSTANCE.size(value);
- }
-
- private int prefixLength() {
- return hasPrefix ? 2 : 0;
- }
-
- private int zeroesLength() {
- return Integer.max(0, width - length - prefixLength());
- }
-
- @Override
- public long mix(long lengthCoder) {
- return lengthCoder + length + prefixLength() + zeroesLength();
- }
-
- @Override
- public long prepend(long lengthCoder, byte[] buffer) throws Throwable {
- MethodHandle putCharMH = selectPutChar(lengthCoder);
- HexDigits.INSTANCE.digits(value, buffer, (int)lengthCoder, putCharMH);
- lengthCoder -= length;
-
- for (int i = 0; i < zeroesLength(); i++) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'0');
- }
-
- if (hasPrefix) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'x');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'0');
- }
-
- return lengthCoder;
- }
- }
-
- /**
- * Hexadecimal format item.
- */
- static final class FormatItemOctal implements FormatConcatItem {
- private final int width;
- private final boolean hasPrefix;
- private final long value;
- private final int length;
-
- FormatItemOctal(int width, boolean hasPrefix, long value) {
- this.width = width;
- this.hasPrefix = hasPrefix;
- this.value = value;
- this.length = OctalDigits.INSTANCE.size(value);
- }
-
- private int prefixLength() {
- return hasPrefix && value != 0 ? 1 : 0;
- }
-
- private int zeroesLength() {
- return Integer.max(0, width - length - prefixLength());
- }
-
- @Override
- public long mix(long lengthCoder) {
- return lengthCoder + length + prefixLength() + zeroesLength();
- }
-
- @Override
- public long prepend(long lengthCoder, byte[] buffer) throws Throwable {
- MethodHandle putCharMH = selectPutChar(lengthCoder);
- OctalDigits.INSTANCE.digits(value, buffer, (int)lengthCoder, putCharMH);
- lengthCoder -= length;
-
- for (int i = 0; i < zeroesLength(); i++) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'0');
- }
-
- if (hasPrefix && value != 0) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'0');
- }
-
- return lengthCoder;
- }
- }
-
- /**
- * Boolean format item.
- */
- static final class FormatItemBoolean implements FormatConcatItem {
- private final boolean value;
-
- FormatItemBoolean(boolean value) {
- this.value = value;
- }
-
- @Override
- public long mix(long lengthCoder) {
- return lengthCoder + (value ? "true".length() : "false".length());
- }
-
- @Override
- public long prepend(long lengthCoder, byte[] buffer) throws Throwable {
- MethodHandle putCharMH = selectPutChar(lengthCoder);
-
- if (value) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'e');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'u');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'r');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'t');
- } else {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'e');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'s');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'l');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'a');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'f');
- }
-
- return lengthCoder;
- }
- }
-
- /**
- * Character format item.
- */
- static final class FormatItemCharacter implements FormatConcatItem {
- private final char value;
-
- FormatItemCharacter(char value) {
- this.value = value;
- }
-
- @Override
- public long mix(long lengthCoder) {
- return charMix(lengthCoder, value);
- }
-
- @Override
- public long prepend(long lengthCoder, byte[] buffer) throws Throwable {
- MethodHandle putCharMH = selectPutChar(lengthCoder);
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)value);
-
- return lengthCoder;
- }
- }
-
- /**
- * String format item.
- */
- static final class FormatItemString implements FormatConcatItem {
- private String value;
-
- FormatItemString(String value) {
- this.value = value;
- }
-
- @Override
- public long mix(long lengthCoder) {
- return stringMix(lengthCoder, value);
- }
-
- @Override
- public long prepend(long lengthCoder, byte[] buffer) throws Throwable {
- return stringPrepend(lengthCoder, buffer, value);
- }
- }
-
- /**
- * FormatSpecifier format item.
- */
- static final class FormatItemFormatSpecifier implements FormatConcatItem {
- private StringBuilder sb;
-
- FormatItemFormatSpecifier(FormatSpecifier fs, Locale locale, Object value) {
- this.sb = new StringBuilder(64);
- Formatter formatter = new Formatter(this.sb, locale);
-
- try {
- fs.print(formatter, value, locale);
- } catch (IOException ex) {
- throw new AssertionError("FormatItemFormatSpecifier IOException", ex);
- }
- }
-
- FormatItemFormatSpecifier(Locale locale,
- int flags, int width, int precision,
- Formattable formattable) {
- this.sb = new StringBuilder(64);
- Formatter formatter = new Formatter(this.sb, locale);
- formattable.formatTo(formatter, flags, width, precision);
- }
-
- @Override
- public long mix(long lengthCoder) {
- return JLA.stringBuilderConcatMix(lengthCoder, sb);
- }
-
- @Override
- public long prepend(long lengthCoder, byte[] buffer) throws Throwable {
- return JLA.stringBuilderConcatPrepend(lengthCoder, buffer, sb);
- }
- }
-
- abstract static sealed class FormatItemModifier implements FormatConcatItem
- permits FormatItemFillLeft,
- FormatItemFillRight
- {
- private final long itemLengthCoder;
- protected final FormatConcatItem item;
-
- FormatItemModifier(FormatConcatItem item) {
- this.itemLengthCoder = item.mix(0L);
- this.item = item;
- }
-
- int length() {
- return (int)itemLengthCoder;
- }
-
- long coder() {
- return itemLengthCoder & ~Integer.MAX_VALUE;
- }
-
- @Override
- public abstract long mix(long lengthCoder);
-
- @Override
- public abstract long prepend(long lengthCoder, byte[] buffer) throws Throwable;
- }
-
- /**
- * Fill left format item.
- */
- static final class FormatItemFillLeft extends FormatItemModifier
- implements FormatConcatItem {
- private final int width;
-
- FormatItemFillLeft(int width, FormatConcatItem item) {
- super(item);
- this.width = Integer.max(length(), width);
- }
-
- @Override
- public long mix(long lengthCoder) {
- return (lengthCoder | coder()) + width;
- }
-
- @Override
- public long prepend(long lengthCoder, byte[] buffer) throws Throwable {
- MethodHandle putCharMH = selectPutChar(lengthCoder);
- lengthCoder = item.prepend(lengthCoder, buffer);
-
- for (int i = length(); i < width; i++) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)' ');
- }
-
- return lengthCoder;
- }
- }
-
- /**
- * Fill right format item.
- */
- static final class FormatItemFillRight extends FormatItemModifier
- implements FormatConcatItem {
- private final int width;
-
- FormatItemFillRight(int width, FormatConcatItem item) {
- super(item);
- this.width = Integer.max(length(), width);
- }
-
- @Override
- public long mix(long lengthCoder) {
- return (lengthCoder | coder()) + width;
- }
-
- @Override
- public long prepend(long lengthCoder, byte[] buffer) throws Throwable {
- MethodHandle putCharMH = selectPutChar(lengthCoder);
-
- for (int i = length(); i < width; i++) {
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)' ');
- }
-
- lengthCoder = item.prepend(lengthCoder, buffer);
-
- return lengthCoder;
- }
- }
-
-
- /**
- * Null format item.
- */
- static final class FormatItemNull implements FormatConcatItem {
- FormatItemNull() {
- }
-
- @Override
- public long mix(long lengthCoder) {
- return lengthCoder + "null".length();
- }
-
- @Override
- public long prepend(long lengthCoder, byte[] buffer) throws Throwable {
- MethodHandle putCharMH = selectPutChar(lengthCoder);
-
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'l');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'l');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'u');
- putCharMH.invokeExact(buffer, (int)--lengthCoder, (int)'n');
-
- return lengthCoder;
- }
- }
-}
diff --git a/src/java.base/share/classes/java/util/FormatProcessor.java b/src/java.base/share/classes/java/util/FormatProcessor.java
deleted file mode 100644
index 20fbc1cedcf..00000000000
--- a/src/java.base/share/classes/java/util/FormatProcessor.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2023, Alibaba Group Holding Limited. 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package java.util;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.StringTemplate.Processor;
-import java.lang.StringTemplate.Processor.Linkage;
-
-import jdk.internal.javac.PreviewFeature;
-
-/**
- * This {@link Processor} constructs a {@link String} result using
- * {@link Formatter} specifications and values found in the {@link StringTemplate}.
- * Unlike {@link Formatter}, {@link FormatProcessor} uses the value from the
- * embedded expression that immediately follows, without whitespace, the
- * format specifier .
- * For example:
- * {@snippet :
- * FormatProcessor fmt = FormatProcessor.create(Locale.ROOT);
- * int x = 10;
- * int y = 20;
- * String result = fmt."%05d\{x} + %05d\{y} = %05d\{x + y}";
- * }
- * In the above example, the value of {@code result} will be {@code "00010 + 00020 = 00030"}.
- *
- * Embedded expressions without a preceeding format specifier, use {@code %s}
- * by default.
- * {@snippet :
- * FormatProcessor fmt = FormatProcessor.create(Locale.ROOT);
- * int x = 10;
- * int y = 20;
- * String result1 = fmt."\{x} + \{y} = \{x + y}";
- * String result2 = fmt."%s\{x} + %s\{y} = %s\{x + y}";
- * }
- * In the above example, the value of {@code result1} and {@code result2} will
- * both be {@code "10 + 20 = 30"}.
- *
- * The {@link FormatProcessor} format specification used and exceptions thrown are the
- * same as those of {@link Formatter}.
- *
- * However, there are two significant differences related to the position of arguments.
- * An explict {@code n$} and relative {@code <} index will cause an exception due to
- * a missing argument list.
- * Whitespace appearing between the specification and the embedded expression will
- * also cause an exception.
- *
- * {@link FormatProcessor} allows the use of different locales. For example:
- * {@snippet :
- * Locale locale = Locale.forLanguageTag("th-TH-u-nu-thai");
- * FormatProcessor thaiFMT = FormatProcessor.create(locale);
- * int x = 10;
- * int y = 20;
- * String result = thaiFMT."%4d\{x} + %4d\{y} = %5d\{x + y}";
- * }
- * In the above example, the value of {@code result} will be
- * {@code " \u0E51\u0E50 + \u0E52\u0E50 = \u0E53\u0E50"}.
- *
- * For day to day use, the predefined {@link FormatProcessor#FMT} {@link FormatProcessor}
- * is available. {@link FormatProcessor#FMT} is defined using the {@link Locale#ROOT}.
- * Example: {@snippet :
- * int x = 10;
- * int y = 20;
- * String result = FMT."0x%04x\{x} + 0x%04x\{y} = 0x%04x\{x + y}"; // @highlight substring="FMT"
- * }
- * In the above example, the value of {@code result} will be {@code "0x000a + 0x0014 = 0x001E"}.
- *
- * @since 21
- *
- * @see Processor
- */
-@PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
-public final class FormatProcessor implements Processor, Linkage {
- /**
- * {@link Locale} used to format
- */
- private final Locale locale;
-
- /**
- * Constructor.
- *
- * @param locale {@link Locale} used to format
- */
- private FormatProcessor(Locale locale) {
- this.locale = locale;
- }
-
- /**
- * Create a new {@link FormatProcessor} using the specified locale.
- *
- * @param locale {@link Locale} used to format
- *
- * @return a new instance of {@link FormatProcessor}
- *
- * @throws java.lang.NullPointerException if locale is null
- */
- public static FormatProcessor create(Locale locale) {
- Objects.requireNonNull(locale);
- return new FormatProcessor(locale);
- }
-
- /**
- * Constructs a {@link String} based on the fragments, format
- * specifications found in the fragments and values in the
- * supplied {@link StringTemplate} object. This method constructs a
- * format string from the fragments, gathers up the values and
- * evaluates the expression asif evaulating
- * {@code new Formatter(locale).format(format, values).toString()}.
- *
- * If an embedded expression is not immediately preceded by a
- * specifier then a {@code %s} is inserted in the format.
- *
- * @param stringTemplate a {@link StringTemplate} instance
- *
- * @return constructed {@link String}
-
- * @throws IllegalFormatException
- * If a format specifier contains an illegal syntax, a format
- * specifier that is incompatible with the given arguments,
- * a specifier not followed immediately by an embedded expression or
- * other illegal conditions. For specification of all possible
- * formatting errors, see the
- * details
- * section of the formatter class specification.
- * @throws NullPointerException if stringTemplate is null
- *
- * @see java.util.Formatter
- */
- @Override
- public final String process(StringTemplate stringTemplate) {
- Objects.requireNonNull(stringTemplate);
- String format = stringTemplateFormat(stringTemplate.fragments());
- Object[] values = stringTemplate.values().toArray();
-
- return new Formatter(locale).format(format, values).toString();
- }
-
- /**
- * Constructs a {@link MethodHandle} that when supplied with the values from
- * a {@link StringTemplate} will produce a result equivalent to that provided by
- * {@link FormatProcessor#process(StringTemplate)}. This {@link MethodHandle}
- * is used by {@link FormatProcessor#FMT} and the ilk to perform a more
- * specialized composition of a result. This specialization is done by
- * prescanning the fragments and value types of a {@link StringTemplate}.
- *
- * Process template expressions can be specialized when the processor is
- * of type {@link Linkage} and fetched from a static constant as is
- * {@link FormatProcessor#FMT} ({@code static final FormatProcessor}).
- *
- * Other {@link FormatProcessor FormatProcessors} can be specialized when stored in a static
- * final.
- * For example:
- * {@snippet :
- * FormatProcessor THAI_FMT = FormatProcessor.create(Locale.forLanguageTag("th-TH-u-nu-thai"));
- * }
- * {@code THAI_FMT} will now produce specialized {@link MethodHandle MethodHandles} by way
- * of {@link FormatProcessor#linkage(List, MethodType)}.
- *
- * See {@link FormatProcessor#process(StringTemplate)} for more information.
- *
- * @throws IllegalFormatException
- * If a format specifier contains an illegal syntax, a format
- * specifier that is incompatible with the given arguments,
- * a specifier not followed immediately by an embedded expression or
- * other illegal conditions. For specification of all possible
- * formatting errors, see the
- * details
- * section of the formatter class specification.
- * @throws NullPointerException if fragments or type is null
- *
- * @see java.util.Formatter
- */
- @Override
- public MethodHandle linkage(List fragments, MethodType type) {
- Objects.requireNonNull(fragments);
- Objects.requireNonNull(type);
- String format = stringTemplateFormat(fragments);
- Class>[] ptypes = type.dropParameterTypes(0, 1).parameterArray();
- MethodHandle mh = new FormatterBuilder(format, locale, ptypes).build();
- mh = MethodHandles.dropArguments(mh, 0, type.parameterType(0));
-
- return mh;
- }
-
- /**
- * Find a format specification at the end of a fragment.
- *
- * @param fragment fragment to check
- * @param needed if the specification is needed
- *
- * @return true if the specification is found and needed
- *
- * @throws MissingFormatArgumentException if not at end or found and not needed
- */
- private static boolean findFormat(String fragment, boolean needed) {
- int max = fragment.length();
- for (int i = 0; i < max;) {
- int n = fragment.indexOf('%', i);
- if (n < 0) {
- return false;
- }
-
- i = n + 1;
- if (i >= max) {
- return false;
- }
-
- char c = fragment.charAt(i);
- if (c == '%' || c == 'n') {
- i++;
- continue;
- }
- int off = new Formatter.FormatSpecifierParser(null, c, i, fragment, max)
- .parse();
- if (off == 0) {
- return false;
- }
- if (i + off == max && needed) {
- return true;
- }
- throw new MissingFormatArgumentException(
- fragment.substring(i - 1, i + off)
- + " is not immediately followed by an embedded expression");
- }
- return false;
- }
-
- /**
- * Convert {@link StringTemplate} fragments, containing format specifications,
- * to a form that can be passed on to {@link Formatter}. The method scans each fragment,
- * matching up formatter specifications with the following expression. If no
- * specification is found, the method inserts "%s".
- *
- * @param fragments string template fragments
- *
- * @return format string
- */
- private static String stringTemplateFormat(List fragments) {
- StringBuilder sb = new StringBuilder();
- int lastIndex = fragments.size() - 1;
- List formats = fragments.subList(0, lastIndex);
- String last = fragments.get(lastIndex);
-
- for (String format : formats) {
- if (findFormat(format, true)) {
- sb.append(format);
- } else {
- sb.append(format);
- sb.append("%s");
- }
- }
-
- if (!findFormat(last, false)) {
- sb.append(last);
- }
-
- return sb.toString();
- }
-
- /**
- * This predefined {@link FormatProcessor} instance constructs a {@link String} result using
- * the Locale.ROOT {@link Locale}. See {@link FormatProcessor} for more details.
- * Example: {@snippet :
- * int x = 10;
- * int y = 20;
- * String result = FMT."0x%04x\{x} + 0x%04x\{y} = 0x%04x\{x + y}"; // @highlight substring="FMT"
- * }
- * In the above example, the value of {@code result} will be {@code "0x000a + 0x0014 = 0x001E"}.
- *
- * @see java.util.FormatProcessor
- */
- public static final FormatProcessor FMT = FormatProcessor.create(Locale.ROOT);
-
-}
diff --git a/src/java.base/share/classes/java/util/Formatter.java b/src/java.base/share/classes/java/util/Formatter.java
index 3f37774469d..a7d95ee5780 100644
--- a/src/java.base/share/classes/java/util/Formatter.java
+++ b/src/java.base/share/classes/java/util/Formatter.java
@@ -61,7 +61,6 @@ import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQueries;
import java.time.temporal.UnsupportedTemporalTypeException;
-import jdk.internal.javac.PreviewFeature;
import jdk.internal.math.DoubleConsts;
import jdk.internal.math.FormattedFPDecimal;
import sun.util.locale.provider.LocaleProviderAdapter;
diff --git a/src/java.base/share/classes/java/util/FormatterBuilder.java b/src/java.base/share/classes/java/util/FormatterBuilder.java
deleted file mode 100644
index 854fdfef68d..00000000000
--- a/src/java.base/share/classes/java/util/FormatterBuilder.java
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package java.util;
-
-import java.io.IOException;
-import java.lang.invoke.*;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.NumberFormat;
-import java.text.spi.NumberFormatProvider;
-import java.util.FormatItem.*;
-import java.util.Formatter.*;
-
-import jdk.internal.util.FormatConcatItem;
-
-import sun.invoke.util.Wrapper;
-import sun.util.locale.provider.LocaleProviderAdapter;
-import sun.util.locale.provider.ResourceBundleBasedAdapter;
-
-import static java.util.Formatter.Conversion.*;
-import static java.util.Formatter.Flags.*;
-import static java.lang.invoke.MethodHandles.*;
-import static java.lang.invoke.MethodType.*;
-
-/**
- * This package private class supports the construction of the {@link MethodHandle}
- * used by {@link FormatProcessor}.
- *
- * @since 21
- *
- * Warning: This class is part of PreviewFeature.Feature.STRING_TEMPLATES.
- * Do not rely on its availability.
- */
-final class FormatterBuilder {
- private static final Lookup LOOKUP = lookup();
-
- private final String format;
- private final Locale locale;
- private final Class>[] ptypes;
- private final DecimalFormatSymbols dfs;
- private final boolean isGenericDFS;
-
- FormatterBuilder(String format, Locale locale, Class>[] ptypes) {
- this.format = format;
- this.locale = locale;
- this.ptypes = ptypes;
- this.dfs = DecimalFormatSymbols.getInstance(locale);
- this.isGenericDFS = isGenericDFS(this.dfs);
- }
-
- private static boolean isGenericDFS(DecimalFormatSymbols dfs) {
- return dfs.getZeroDigit() == '0' &&
- dfs.getDecimalSeparator() == '.' &&
- dfs.getGroupingSeparator() == ',' &&
- dfs.getMinusSign() == '-';
- }
-
- private static Class> mapType(Class> type) {
- return type.isPrimitive() || type == String.class ? type : Object.class;
- }
-
- private static MethodHandle findStringConcatItemConstructor(Class> cls,
- Class>... ptypes) {
- MethodType methodType = methodType(void.class, ptypes);
-
- try {
- MethodHandle mh = LOOKUP.findConstructor(cls, methodType);
-
- return mh.asType(mh.type().changeReturnType(FormatConcatItem.class));
- } catch (ReflectiveOperationException e) {
- throw new AssertionError("Missing constructor in " +
- cls + ": " + methodType);
- }
- }
-
- private static MethodHandle findMethod(Class> cls, String name,
- Class> rType, Class>... ptypes) {
- MethodType methodType = methodType(rType, ptypes);
-
- try {
- return LOOKUP.findVirtual(cls, name, methodType);
- } catch (ReflectiveOperationException e) {
- throw new AssertionError("Missing method in " +
- cls + ": " + name + " " + methodType);
- }
- }
-
- private static MethodHandle findStaticMethod(Class> cls, String name,
- Class> rType, Class>... ptypes) {
- MethodType methodType = methodType(rType, ptypes);
-
- try {
- return LOOKUP.findStatic(cls, name, methodType);
- } catch (ReflectiveOperationException e) {
- throw new AssertionError("Missing static method in " +
- cls + ": " + name + " " + methodType);
- }
- }
-
- private static final MethodHandle FIDecimal_MH =
- findStringConcatItemConstructor(FormatItemDecimal.class,
- DecimalFormatSymbols.class, int.class, char.class, boolean.class,
- int.class, long.class);
-
- private static final MethodHandle FIHexadecimal_MH =
- findStringConcatItemConstructor(FormatItemHexadecimal.class,
- int.class, boolean.class, long.class);
-
- private static final MethodHandle FIOctal_MH =
- findStringConcatItemConstructor(FormatItemOctal.class,
- int.class, boolean.class, long.class);
-
- private static final MethodHandle FIBoolean_MH =
- findStringConcatItemConstructor(FormatItemBoolean.class,
- boolean.class);
-
- private static final MethodHandle FICharacter_MH =
- findStringConcatItemConstructor(FormatItemCharacter.class,
- char.class);
-
- private static final MethodHandle FIString_MH =
- findStringConcatItemConstructor(FormatItemString.class,
- String.class);
-
- private static final MethodHandle FIFormatSpecifier_MH =
- findStringConcatItemConstructor(FormatItemFormatSpecifier.class,
- FormatSpecifier.class, Locale.class, Object.class);
-
- private static final MethodHandle FIFormattable_MH =
- findStringConcatItemConstructor(FormatItemFormatSpecifier.class,
- Locale.class, int.class, int.class, int.class,
- Formattable.class);
-
- private static final MethodHandle FIFillLeft_MH =
- findStringConcatItemConstructor(FormatItemFillLeft.class,
- int.class, FormatConcatItem.class);
-
- private static final MethodHandle FIFillRight_MH =
- findStringConcatItemConstructor(FormatItemFillRight.class,
- int.class, FormatConcatItem.class);
-
- private static final MethodHandle FINull_MH =
- findStringConcatItemConstructor(FormatItemNull.class);
-
- private static final MethodHandle NullCheck_MH =
- findStaticMethod(FormatterBuilder.class, "nullCheck", boolean.class,
- Object.class);
-
- private static final MethodHandle FormattableCheck_MH =
- findStaticMethod(FormatterBuilder.class, "formattableCheck", boolean.class,
- Object.class);
-
- private static final MethodHandle ToLong_MH =
- findStaticMethod(java.util.FormatterBuilder.class, "toLong", long.class,
- int.class);
-
- private static final MethodHandle ToString_MH =
- findStaticMethod(String.class, "valueOf", String.class,
- Object.class);
-
- private static final MethodHandle HashCode_MH =
- findStaticMethod(Objects.class, "hashCode", int.class,
- Object.class);
-
- private static boolean nullCheck(Object object) {
- return object == null;
- }
-
- private static boolean formattableCheck(Object object) {
- return Formattable.class.isAssignableFrom(object.getClass());
- }
-
- private static long toLong(int value) {
- return (long)value & 0xFFFFFFFFL;
- }
-
- private static boolean isFlag(int value, int flags) {
- return (value & flags) != 0;
- }
-
- private static boolean validFlags(int value, int flags) {
- return (value & ~flags) == 0;
- }
-
- private static int groupSize(Locale locale, DecimalFormatSymbols dfs) {
- if (isGenericDFS(dfs)) {
- return 3;
- }
-
- DecimalFormat df;
- NumberFormat nf = NumberFormat.getNumberInstance(locale);
-
- if (nf instanceof DecimalFormat) {
- df = (DecimalFormat)nf;
- } else {
- LocaleProviderAdapter adapter = LocaleProviderAdapter
- .getAdapter(NumberFormatProvider.class, locale);
-
- if (!(adapter instanceof ResourceBundleBasedAdapter)) {
- adapter = LocaleProviderAdapter.getResourceBundleBased();
- }
-
- String[] all = adapter.getLocaleResources(locale)
- .getNumberPatterns();
-
- df = new DecimalFormat(all[0], dfs);
- }
-
- return df.isGroupingUsed() ? df.getGroupingSize() : 0;
- }
-
- private MethodHandle formatSpecifier(FormatSpecifier fs, Class> ptype) {
- boolean isPrimitive = ptype.isPrimitive();
- MethodHandle mh = identity(ptype);
- MethodType mt = mh.type();
-
-//cannot cast to primitive types as it breaks null values formatting
-// if (ptype == byte.class || ptype == short.class ||
-// ptype == Byte.class || ptype == Short.class ||
-// ptype == Integer.class) {
-// mt = mt.changeReturnType(int.class);
-// } else if (ptype == Long.class) {
-// mt = mt.changeReturnType(long.class);
-// } else if (ptype == float.class || ptype == Float.class ||
-// ptype == Double.class) {
-// mt = mt.changeReturnType(double.class);
-// } else if (ptype == Boolean.class) {
-// mt = mt.changeReturnType(boolean.class);
-// } else if (ptype == Character.class) {
-// mt = mt.changeReturnType(char.class);
-// }
-
- Class> itype = mt.returnType();
-
- if (itype != ptype) {
- mh = explicitCastArguments(mh, mt);
- }
-
- boolean handled = false;
- int flags = fs.flags;
- int width = fs.width;
- int precision = fs.precision;
- Character conv = fs.dt ? 't' : fs.c;
-
- switch (Character.toLowerCase(conv)) {
- case BOOLEAN -> {
- if (itype == boolean.class && precision == -1) {
- if (flags == 0 && width == -1 && isPrimitive) {
- return null;
- }
-
- if (validFlags(flags, LEFT_JUSTIFY)) {
- handled = true;
- mh = filterReturnValue(mh, FIBoolean_MH);
- }
- }
- }
- case STRING -> {
- if (flags == 0 && width == -1 && precision == -1) {
- if (isPrimitive || ptype == String.class) {
- return null;
- } else if (itype.isPrimitive()) {
- return mh;
- }
- }
-
- if (validFlags(flags, LEFT_JUSTIFY) && precision == -1) {
- if (itype == String.class) {
- handled = true;
- mh = filterReturnValue(mh, FIString_MH);
- } else if (!itype.isPrimitive()) {
- handled = true;
- MethodHandle test = FormattableCheck_MH;
- test = test.asType(test.type().changeParameterType(0, ptype));
- MethodHandle pass = insertArguments(FIFormattable_MH,
- 0, locale, flags, width, precision);
- pass = pass.asType(pass.type().changeParameterType(0, ptype));
- MethodHandle fail = ToString_MH;
- fail = filterReturnValue(fail, FIString_MH);
- fail = fail.asType(fail.type().changeParameterType(0, ptype));
- mh = guardWithTest(test, pass, fail);
- }
- }
- }
- case CHARACTER -> {
- if (itype == char.class && precision == -1) {
- if (flags == 0 && width == -1) {
- return isPrimitive ? null : mh;
- }
-
- if (validFlags(flags, LEFT_JUSTIFY)) {
- handled = true;
- mh = filterReturnValue(mh, FICharacter_MH);
- }
- }
- }
- case DECIMAL_INTEGER -> {
- if ((itype == int.class || itype == long.class) && precision == -1) {
- if (itype == int.class) {
- mh = explicitCastArguments(mh,
- mh.type().changeReturnType(long.class));
- }
-
- if (flags == 0 && isGenericDFS && width == -1) {
- return mh;
- } else if (validFlags(flags, PLUS | LEADING_SPACE |
- ZERO_PAD | GROUP |
- PARENTHESES)) {
- handled = true;
- int zeroPad = isFlag(flags, ZERO_PAD) ? width : -1;
- char sign = isFlag(flags, PLUS) ? '+' :
- isFlag(flags, LEADING_SPACE) ? ' ' : '\0';
- boolean parentheses = isFlag(flags, PARENTHESES);
- int groupSize = isFlag(flags, GROUP) ?
- groupSize(locale, dfs) : 0;
- mh = filterReturnValue(mh,
- insertArguments(FIDecimal_MH, 0, dfs, zeroPad,
- sign, parentheses, groupSize));
- }
- }
- }
- case OCTAL_INTEGER -> {
- if ((itype == int.class || itype == long.class) &&
- precision == -1 &&
- validFlags(flags, ZERO_PAD | ALTERNATE)) {
- handled = true;
-
- if (itype == int.class) {
- mh = filterReturnValue(mh, ToLong_MH);
- }
-
- int zeroPad = isFlag(flags, ZERO_PAD) ? width : -1;
- boolean hasPrefix = isFlag(flags, ALTERNATE);
- mh = filterReturnValue(mh,
- insertArguments(FIOctal_MH, 0, zeroPad, hasPrefix));
- }
- }
- case HEXADECIMAL_INTEGER -> {
- if ((itype == int.class || itype == long.class) &&
- precision == -1 &&
- validFlags(flags, ZERO_PAD | ALTERNATE)) {
- handled = true;
-
- if (itype == int.class) {
- mh = filterReturnValue(mh, ToLong_MH);
- }
-
- int zeroPad = isFlag(flags, ZERO_PAD) ? width : -1;
- boolean hasPrefix = isFlag(flags, ALTERNATE);
- mh = filterReturnValue(mh,
- insertArguments(FIHexadecimal_MH, 0, zeroPad, hasPrefix));
- }
- }
- default -> {
- // pass thru
- }
- }
-
- if (handled) {
- if (!isPrimitive) {
- MethodHandle test = NullCheck_MH.asType(
- NullCheck_MH.type().changeParameterType(0, ptype));
- MethodHandle pass = dropArguments(FINull_MH, 0, ptype);
- mh = guardWithTest(test, pass, mh);
- }
-
- if (0 < width) {
- if (isFlag(flags, LEFT_JUSTIFY)) {
- mh = filterReturnValue(mh,
- insertArguments(FIFillRight_MH, 0, width));
- } else {
- mh = filterReturnValue(mh,
- insertArguments(FIFillLeft_MH, 0, width));
- }
- }
-
- if (!isFlag(flags, UPPERCASE)) {
- return mh;
- }
- }
-
- mh = insertArguments(FIFormatSpecifier_MH, 0, fs, locale);
- mh = mh.asType(mh.type().changeParameterType(0, ptype));
-
- return mh;
- }
-
- /**
- * Construct concat {@link MethodHandle} for based on format.
- *
- * @param fsa list of specifiers
- *
- * @return concat {@link MethodHandle} for based on format
- */
- private MethodHandle buildFilters(List fsa,
- List segments,
- MethodHandle[] filters) {
- MethodHandle mh = null;
- int iParam = 0;
- StringBuilder segment = new StringBuilder();
-
- for (FormatString fs : fsa) {
- int index = fs.index();
-
- switch (index) {
- case -2: // fixed string, "%n", or "%%"
- String string = fs.toString();
-
- if ("%%".equals(string)) {
- segment.append('%');
- } else if ("%n".equals(string)) {
- segment.append(System.lineSeparator());
- } else {
- segment.append(string);
- }
- break;
- case 0: // ordinary index
- segments.add(segment.toString());
- segment.setLength(0);
-
- if (iParam < ptypes.length) {
- Class> ptype = ptypes[iParam];
- filters[iParam++] = formatSpecifier((FormatSpecifier)fs, ptype);
- } else {
- throw new MissingFormatArgumentException(fs.toString());
- }
- break;
- case -1: // relative index
- default: // explicit index
- throw new IllegalFormatFlagsException("Indexing not allowed: " + fs.toString());
- }
- }
-
- segments.add(segment.toString());
-
- return mh;
- }
-
- /**
- * Build a {@link MethodHandle} to format arguments.
- *
- * @return new {@link MethodHandle} to format arguments
- */
- MethodHandle build() {
- List segments = new ArrayList<>();
- MethodHandle[] filters = new MethodHandle[ptypes.length];
- buildFilters(Formatter.parse(format), segments, filters);
- Class>[] ftypes = new Class>[filters.length];
-
- for (int i = 0; i < filters.length; i++) {
- MethodHandle filter = filters[i];
- ftypes[i] = filter == null ? ptypes[i] : filter.type().returnType();
- }
-
- try {
- MethodHandle mh = StringConcatFactory.makeConcatWithTemplate(segments,
- List.of(ftypes));
- mh = filterArguments(mh, 0, filters);
-
- return mh;
- } catch (StringConcatException ex) {
- throw new AssertionError("concat fail", ex);
- }
- }
-}
diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java
index c6200520fdd..af7ff2e4aa2 100644
--- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java
+++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java
@@ -364,6 +364,15 @@ public interface JavaLangAccess {
*/
char getUTF16Char(byte[] bytes, int index);
+ /**
+ * Put the char at index in a byte[] in internal UTF-16 representation,
+ * with no bounds checks.
+ *
+ * @param bytes the UTF-16 encoded bytes
+ * @param index of the char to retrieve, 0 <= index < (bytes.length >> 1)
+ */
+ void putCharUTF16(byte[] bytes, int index, int ch);
+
/**
* Encode the given string into a sequence of bytes using utf8.
*
@@ -417,6 +426,12 @@ public interface JavaLangAccess {
*/
MethodHandle stringConcatHelper(String name, MethodType methodType);
+ /**
+ * Prepends constant and the stringly representation of value into buffer,
+ * given the coder and final index. Index is measured in chars, not in bytes!
+ */
+ long stringConcatHelperPrepend(long indexCoder, byte[] buf, String value);
+
/**
* Get the string concat initial coder
*/
@@ -427,20 +442,10 @@ public interface JavaLangAccess {
*/
long stringConcatMix(long lengthCoder, String constant);
- /**
- * Get the coder for the supplied character.
- */
- long stringConcatCoder(char value);
-
- /**
- * Update lengthCoder for StringBuilder.
- */
- long stringBuilderConcatMix(long lengthCoder, StringBuilder sb);
-
/**
- * Prepend StringBuilder content.
- */
- long stringBuilderConcatPrepend(long lengthCoder, byte[] buf, StringBuilder sb);
+ * Mix value length and coder into current length and coder.
+ */
+ long stringConcatMix(long lengthCoder, char value);
/**
* Join strings
@@ -454,6 +459,12 @@ public interface JavaLangAccess {
*/
Object classData(Class> c);
+ int stringSize(long i);
+
+ int getCharsLatin1(long i, int index, byte[] buf);
+
+ int getCharsUTF16(long i, int index, byte[] buf);
+
long findNative(ClassLoader loader, String entry);
/**
diff --git a/src/java.base/share/classes/jdk/internal/access/JavaTemplateAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaTemplateAccess.java
deleted file mode 100644
index da99f7806d1..00000000000
--- a/src/java.base/share/classes/jdk/internal/access/JavaTemplateAccess.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.access;
-
-import java.util.List;
-
-public interface JavaTemplateAccess {
-
- /**
- * Returns a StringTemplate composed from fragments and values.
- *
- * @implSpec The {@code fragments} list size must be one more that the
- * {@code values} list size.
- *
- * @param fragments list of string fragments
- * @param values list of expression values
- *
- * @return StringTemplate composed from fragments and values
- *
- * @throws IllegalArgumentException if fragments list size is not one more
- * than values list size
- * @throws NullPointerException if fragments is null or values is null or if any fragment is null.
- *
- * @implNote Contents of both lists are copied to construct immutable lists.
- */
- StringTemplate of(List fragments, List> values);
-
- /**
- * Creates a string that interleaves the elements of values between the
- * elements of fragments.
- *
- * @param fragments list of String fragments
- * @param values list of expression values
- *
- * @return String interpolation of fragments and values
- */
- String interpolate(List fragments, List> values);
-
- /**
- * Combine one or more {@link StringTemplate StringTemplates} to produce a combined {@link StringTemplate}.
- * {@snippet :
- * StringTemplate st = StringTemplate.combine("\{a}", "\{b}", "\{c}");
- * assert st.interpolate().equals("\{a}\{b}\{c}");
- * }
- *
- * @param sts zero or more {@link StringTemplate}
- *
- * @return combined {@link StringTemplate}
- *
- * @throws NullPointerException if sts is null or if any element of sts is null
- */
- StringTemplate combine(StringTemplate... sts);
-
-}
-
diff --git a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java
index eb0a7821d0d..0dacbef993a 100644
--- a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java
+++ b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java
@@ -91,7 +91,6 @@ public class SharedSecrets {
private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
private static JavaxCryptoSpecAccess javaxCryptoSpecAccess;
private static JavaxSecurityAccess javaxSecurityAccess;
- private static JavaTemplateAccess javaTemplateAccess;
public static void setJavaUtilCollectionAccess(JavaUtilCollectionAccess juca) {
javaUtilCollectionAccess = juca;
@@ -532,21 +531,6 @@ public class SharedSecrets {
return access;
}
- public static void setJavaTemplateAccess(JavaTemplateAccess jta) {
- javaTemplateAccess = jta;
- }
-
- public static JavaTemplateAccess getJavaTemplateAccess() {
- var access = javaTemplateAccess;
- if (access == null) {
- try {
- Class.forName("java.lang.runtime.TemplateSupport", true, null);
- access = javaTemplateAccess;
- } catch (ClassNotFoundException e) {}
- }
- return access;
- }
-
private static void ensureClassInitialized(Class> c) {
try {
MethodHandles.lookup().ensureInitialized(c);
diff --git a/src/java.base/share/classes/jdk/internal/util/DecimalDigits.java b/src/java.base/share/classes/jdk/internal/util/DecimalDigits.java
index f078c7d5726..bdcbe15ea84 100644
--- a/src/java.base/share/classes/jdk/internal/util/DecimalDigits.java
+++ b/src/java.base/share/classes/jdk/internal/util/DecimalDigits.java
@@ -25,8 +25,6 @@
package jdk.internal.util;
-import java.lang.invoke.MethodHandle;
-
import jdk.internal.vm.annotation.Stable;
/**
@@ -34,7 +32,7 @@ import jdk.internal.vm.annotation.Stable;
*
* @since 21
*/
-public final class DecimalDigits implements Digits {
+public final class DecimalDigits {
/**
* Each element of the array represents the packaging of two ascii characters based on little endian:
@@ -72,85 +70,12 @@ public final class DecimalDigits implements Digits {
DIGITS = digits;
}
- /**
- * Singleton instance of DecimalDigits.
- */
- public static final Digits INSTANCE = new DecimalDigits();
-
/**
* Constructor.
*/
private DecimalDigits() {
}
- @Override
- public int digits(long value, byte[] buffer, int index,
- MethodHandle putCharMH) throws Throwable {
- boolean negative = value < 0;
- if (!negative) {
- value = -value;
- }
-
- long q;
- int r;
- while (value <= Integer.MIN_VALUE) {
- q = value / 100;
- r = (int)((q * 100) - value);
- value = q;
- int digits = DIGITS[r];
-
- putCharMH.invokeExact(buffer, --index, digits >> 8);
- putCharMH.invokeExact(buffer, --index, digits & 0xFF);
- }
-
- int iq, ivalue = (int)value;
- while (ivalue <= -100) {
- iq = ivalue / 100;
- r = (iq * 100) - ivalue;
- ivalue = iq;
- int digits = DIGITS[r];
- putCharMH.invokeExact(buffer, --index, digits >> 8);
- putCharMH.invokeExact(buffer, --index, digits & 0xFF);
- }
-
- if (ivalue < 0) {
- ivalue = -ivalue;
- }
-
- int digits = DIGITS[ivalue];
- putCharMH.invokeExact(buffer, --index, digits >> 8);
-
- if (9 < ivalue) {
- putCharMH.invokeExact(buffer, --index, digits & 0xFF);
- }
-
- if (negative) {
- putCharMH.invokeExact(buffer, --index, (int)'-');
- }
-
- return index;
- }
-
- @Override
- public int size(long value) {
- boolean negative = value < 0;
- int sign = negative ? 1 : 0;
-
- if (!negative) {
- value = -value;
- }
-
- long precision = -10;
- for (int i = 1; i < 19; i++) {
- if (value > precision)
- return i + sign;
-
- precision = 10 * precision;
- }
-
- return 19 + sign;
- }
-
/**
* For values from 0 to 99 return a short encoding a pair of ASCII-encoded digit characters in little-endian
* @param i value to convert
diff --git a/src/java.base/share/classes/jdk/internal/util/Digits.java b/src/java.base/share/classes/jdk/internal/util/Digits.java
deleted file mode 100644
index e301688ff4e..00000000000
--- a/src/java.base/share/classes/jdk/internal/util/Digits.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.util;
-
-import java.lang.invoke.MethodHandle;
-
-/**
- * Digits provides a fast methodology for converting integers and longs to
- * ASCII strings.
- *
- * @since 21
- */
-public sealed interface Digits permits DecimalDigits, HexDigits, OctalDigits {
- /**
- * Insert digits for long value in buffer from high index to low index.
- *
- * @param value value to convert
- * @param buffer byte buffer to copy into
- * @param index insert point + 1
- * @param putCharMH method to put character
- *
- * @return the last index used
- *
- * @throws Throwable if putCharMH fails (unusual).
- */
- int digits(long value, byte[] buffer, int index,
- MethodHandle putCharMH) throws Throwable;
-
- /**
- * Calculate the number of digits required to represent the long.
- *
- * @param value value to convert
- *
- * @return number of digits
- */
- int size(long value);
-
-}
diff --git a/src/java.base/share/classes/jdk/internal/util/FormatConcatItem.java b/src/java.base/share/classes/jdk/internal/util/FormatConcatItem.java
deleted file mode 100644
index b4588968a3e..00000000000
--- a/src/java.base/share/classes/jdk/internal/util/FormatConcatItem.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.internal.util;
-
-/**
- * Implementations of this class provide information necessary to
- * assist {@link java.lang.invoke.StringConcatFactory} perform optimal
- * insertion.
- *
- * @since 21
- *
- * Warning: This class is part of PreviewFeature.Feature.STRING_TEMPLATES.
- * Do not rely on its availability.
- */
-public interface FormatConcatItem {
- /**
- * Calculate the length of the insertion.
- *
- * @param lengthCoder current value of the length + coder
- * @return adjusted value of the length + coder
- */
- long mix(long lengthCoder);
-
- /**
- * Insert content into buffer prior to the current length.
- *
- * @param lengthCoder current value of the length + coder
- * @param buffer buffer to append to
- *
- * @return adjusted value of the length + coder
- *
- * @throws Throwable if fails to prepend value (unusual).
- */
- long prepend(long lengthCoder, byte[] buffer) throws Throwable;
-}
diff --git a/src/java.base/share/classes/jdk/internal/util/HexDigits.java b/src/java.base/share/classes/jdk/internal/util/HexDigits.java
index 1adda90a65a..075443571e1 100644
--- a/src/java.base/share/classes/jdk/internal/util/HexDigits.java
+++ b/src/java.base/share/classes/jdk/internal/util/HexDigits.java
@@ -25,16 +25,19 @@
package jdk.internal.util;
-import java.lang.invoke.MethodHandle;
-
+import jdk.internal.access.JavaLangAccess;
+import jdk.internal.access.SharedSecrets;
import jdk.internal.vm.annotation.Stable;
/**
- * Digits class for hexadecimal digits.
+ * Digits provides a fast methodology for converting integers and longs to
+ * hexadecimal digits ASCII strings.
*
* @since 21
*/
-public final class HexDigits implements Digits {
+public final class HexDigits {
+ private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
+
/**
* Each element of the array represents the ascii encoded
* hex relative to its index, for example:
@@ -65,11 +68,6 @@ public final class HexDigits implements Digits {
@Stable
private static final short[] DIGITS;
- /**
- * Singleton instance of HexDigits.
- */
- public static final Digits INSTANCE = new HexDigits();
-
static {
short[] digits = new short[16 * 16];
@@ -136,28 +134,68 @@ public final class HexDigits implements Digits {
| (((long) DIGITS[b3 & 0xff]) << 48);
}
- @Override
- public int digits(long value, byte[] buffer, int index,
- MethodHandle putCharMH) throws Throwable {
+ /**
+ * Insert digits for long value in buffer from high index to low index.
+ *
+ * @param value value to convert
+ * @param index insert point + 1
+ * @param buffer byte buffer to copy into
+ *
+ * @return the last index used
+ */
+ public static int getCharsLatin1(long value, int index, byte[] buffer) {
while ((value & ~0xFF) != 0) {
- int digits = DIGITS[(int) (value & 0xFF)];
+ short pair = DIGITS[((int) value) & 0xFF];
+ buffer[--index] = (byte)(pair >> 8);
+ buffer[--index] = (byte)(pair);
value >>>= 8;
- putCharMH.invokeExact(buffer, --index, digits >> 8);
- putCharMH.invokeExact(buffer, --index, digits & 0xFF);
}
int digits = DIGITS[(int) (value & 0xFF)];
- putCharMH.invokeExact(buffer, --index, digits >> 8);
+ buffer[--index] = (byte) (digits >> 8);
if (0xF < value) {
- putCharMH.invokeExact(buffer, --index, digits & 0xFF);
+ buffer[--index] = (byte) (digits & 0xFF);
}
return index;
}
- @Override
- public int size(long value) {
+ /**
+ * Insert digits for long value in buffer from high index to low index.
+ *
+ * @param value value to convert
+ * @param index insert point + 1
+ * @param buffer byte buffer to copy into
+ *
+ * @return the last index used
+ */
+ public static int getCharsUTF16(long value, int index, byte[] buffer) {
+ while ((value & ~0xFF) != 0) {
+ int pair = (int) DIGITS[((int) value) & 0xFF];
+ JLA.putCharUTF16(buffer, --index, pair >> 8);
+ JLA.putCharUTF16(buffer, --index, pair & 0xFF);
+ value >>>= 8;
+ }
+
+ int digits = DIGITS[(int) (value & 0xFF)];
+ JLA.putCharUTF16(buffer, --index, (byte) (digits >> 8));
+
+ if (0xF < value) {
+ JLA.putCharUTF16(buffer, --index, (byte) (digits & 0xFF));
+ }
+
+ return index;
+ }
+
+ /**
+ * Calculate the number of digits required to represent the long.
+ *
+ * @param value value to convert
+ *
+ * @return number of digits
+ */
+ public static int stringSize(long value) {
return value == 0 ? 1 :
67 - Long.numberOfLeadingZeros(value) >> 2;
}
diff --git a/src/java.base/share/classes/jdk/internal/util/OctalDigits.java b/src/java.base/share/classes/jdk/internal/util/OctalDigits.java
index 785947442e8..97b1f882f59 100644
--- a/src/java.base/share/classes/jdk/internal/util/OctalDigits.java
+++ b/src/java.base/share/classes/jdk/internal/util/OctalDigits.java
@@ -25,8 +25,8 @@
package jdk.internal.util;
-import java.lang.invoke.MethodHandle;
-
+import jdk.internal.access.JavaLangAccess;
+import jdk.internal.access.SharedSecrets;
import jdk.internal.vm.annotation.Stable;
/**
@@ -34,15 +34,12 @@ import jdk.internal.vm.annotation.Stable;
*
* @since 21
*/
-public final class OctalDigits implements Digits {
+public final class OctalDigits {
+ private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
+
@Stable
private static final short[] DIGITS;
- /**
- * Singleton instance of OctalDigits.
- */
- public static final Digits INSTANCE = new OctalDigits();
-
static {
short[] digits = new short[8 * 8];
@@ -64,28 +61,70 @@ public final class OctalDigits implements Digits {
private OctalDigits() {
}
- @Override
- public int digits(long value, byte[] buffer, int index,
- MethodHandle putCharMH) throws Throwable {
+ /**
+ * Insert digits for long value in buffer from high index to low index.
+ *
+ * @param value value to convert
+ * @param index insert point + 1
+ * @param buffer byte buffer to copy into
+ *
+ * @return the last index used
+ */
+ public static int getCharsLatin1(long value, int index, byte[] buffer){
while ((value & ~0x3F) != 0) {
- int digits = DIGITS[(int) (value & 0x3F)];
+ int digits = DIGITS[((int) value) & 0x3F];
value >>>= 6;
- putCharMH.invokeExact(buffer, --index, digits >> 8);
- putCharMH.invokeExact(buffer, --index, digits & 0xFF);
+ buffer[--index] = (byte) (digits >> 8);
+ buffer[--index] = (byte) (digits & 0xFF);
}
int digits = DIGITS[(int) (value & 0x3F)];
- putCharMH.invokeExact(buffer, --index, digits >> 8);
+ buffer[--index] = (byte) (digits >> 8);
if (7 < value) {
- putCharMH.invokeExact(buffer, --index, digits & 0xFF);
+ buffer[--index] = (byte) (digits & 0xFF);
}
return index;
}
- @Override
- public int size(long value) {
- return (66 - Long.numberOfLeadingZeros(value)) / 3;
+
+ /**
+ * This is a variant of {@link OctalDigits#getCharsLatin1(long, int, byte[])}, but for
+ * UTF-16 coder.
+ *
+ * @param value value to convert
+ * @param index insert point + 1
+ * @param buffer byte buffer to copy into
+ *
+ * @return the last index used
+ */
+ public static int getCharsUTF16(long value, int index, byte[] buffer){
+ while ((value & ~0x3F) != 0) {
+ int pair = (int) DIGITS[((int) value) & 0x3F];
+ JLA.putCharUTF16(buffer, --index, pair >> 8);
+ JLA.putCharUTF16(buffer, --index, pair & 0xFF);
+ value >>>= 6;
+ }
+
+ int digits = DIGITS[(int) (value & 0x3F)];
+ JLA.putCharUTF16(buffer, --index, digits >> 8);
+
+ if (7 < value) {
+ JLA.putCharUTF16(buffer, --index, digits & 0xFF);
+ }
+
+ return index;
+ }
+
+ /**
+ * Calculate the number of digits required to represent the long.
+ *
+ * @param value value to convert
+ *
+ * @return number of digits
+ */
+ public static int stringSize(long value) {
+ return value == 0 ? 1 : ((66 - Long.numberOfLeadingZeros(value)) / 3);
}
}
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/StringTemplateTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/StringTemplateTree.java
deleted file mode 100644
index 9cf94d1cbd3..00000000000
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/StringTemplateTree.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package com.sun.source.tree;
-
-import java.util.List;
-
-import jdk.internal.javac.PreviewFeature;
-
-/**
- * A tree node for a string template expression.
- *
- * @since 21
- */
-@PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES, reflective=true)
-public interface StringTemplateTree extends ExpressionTree {
- /**
- * Returns templated string processor (may be qualified) or null.
- *
- * @return templated string processor
- */
- ExpressionTree getProcessor();
-
- /**
- * Returns string fragments.
- *
- * @return string fragments
- */
- List getFragments();
-
- /**
- * Returns list of expressions.
- *
- * @return list of expressions
- */
- List extends ExpressionTree> getExpressions();
-}
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
index 9150c4cf4b0..0bd3823307b 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
@@ -25,8 +25,6 @@
package com.sun.source.tree;
-import jdk.internal.javac.PreviewFeature;
-
/**
* Common interface for all nodes in an abstract syntax tree.
*
@@ -175,13 +173,6 @@ public interface Tree {
*/
INSTANCE_OF(InstanceOfTree.class),
- /**
- * Used for instances of {@link StringTemplateTree}.
- * @since 21
- */
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES, reflective=true)
- TEMPLATE(StringTemplateTree.class),
-
/**
* Used for instances of {@link LabeledStatementTree}.
*/
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
index d01625ff4b0..3f7a683350c 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
@@ -25,8 +25,6 @@
package com.sun.source.tree;
-import jdk.internal.javac.PreviewFeature;
-
/**
* A visitor of trees, in the style of the visitor design pattern.
* Classes implementing this interface are used to operate
@@ -259,16 +257,6 @@ public interface TreeVisitor {
*/
R visitLiteral(LiteralTree node, P p);
- /**
- * Visits a StringTemplateTree node.
- * @param node the node being visited
- * @param p a parameter value
- * @return a result value
- * @since 21
- */
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES, reflective=true)
- R visitStringTemplate(StringTemplateTree node, P p);
-
/**
* Visits a {@code AnyPatternTree} node.
* @param node the node being visited
diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
index 22a2e479a80..5179061b4bb 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
@@ -26,7 +26,6 @@
package com.sun.source.util;
import com.sun.source.tree.*;
-import jdk.internal.javac.PreviewFeature;
/**
* A simple visitor for tree nodes.
@@ -628,20 +627,6 @@ public class SimpleTreeVisitor implements TreeVisitor {
return defaultAction(node, p);
}
- /**
- * {@inheritDoc} This implementation calls {@code defaultAction}.
- *
- * @param node {@inheritDoc}
- * @param p {@inheritDoc}
- * @return the result of {@code defaultAction}
- * @since 21
- */
- @Override
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES, reflective=true)
- public R visitStringTemplate(StringTemplateTree node, P p) {
- return defaultAction(node, p);
- }
-
/**
* {@inheritDoc}
*
diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
index fc3a7823914..49bec302100 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
@@ -26,7 +26,6 @@
package com.sun.source.util;
import com.sun.source.tree.*;
-import jdk.internal.javac.PreviewFeature;
/**
* A TreeVisitor that visits all the child tree nodes.
@@ -775,24 +774,6 @@ public class TreeScanner implements TreeVisitor {
return null;
}
- /**
- * {@inheritDoc}
- *
- * @implSpec This implementation scans the children in left to right order.
- *
- * @param node {@inheritDoc}
- * @param p {@inheritDoc}
- * @return the result of scanning
- * @since 21
- */
- @Override
- @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES, reflective=true)
- public R visitStringTemplate(StringTemplateTree node, P p) {
- R r = scan(node.getProcessor(), p);
- r = scanAndReduce(node.getExpressions(), p, r);
- return r;
- }
-
/**
* {@inheritDoc}
*
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java
index 32a7d068715..1572973179b 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java
@@ -207,7 +207,6 @@ public class Preview {
*/
public boolean isPreview(Feature feature) {
return switch (feature) {
- case STRING_TEMPLATES -> true;
case IMPLICIT_CLASSES -> true;
case SUPER_INIT -> true;
case PRIMITIVE_PATTERNS -> true;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
index 54e5cfec32a..80f60aa7209 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
@@ -250,7 +250,6 @@ public enum Source {
REDUNDANT_STRICTFP(JDK17),
UNCONDITIONAL_PATTERN_IN_INSTANCEOF(JDK21, Fragments.FeatureUnconditionalPatternsInInstanceof, DiagKind.PLURAL),
RECORD_PATTERNS(JDK21, Fragments.FeatureDeconstructionPatterns, DiagKind.PLURAL),
- STRING_TEMPLATES(JDK21, Fragments.FeatureStringTemplates, DiagKind.PLURAL),
IMPLICIT_CLASSES(JDK21, Fragments.FeatureImplicitClasses, DiagKind.PLURAL),
WARN_ON_ILLEGAL_UTF8(MIN, JDK21),
UNNAMED_VARIABLES(JDK22, Fragments.FeatureUnnamedVariables, DiagKind.PLURAL),
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
index b1dd2186d7e..89de932ab72 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -242,12 +242,6 @@ public class Symtab {
public final Type objectInputType;
public final Type objectOutputType;
- // For string templates
- public final Type stringTemplateType;
- public final Type templateRuntimeType;
- public final Type processorType;
- public final Type linkageType;
-
/** The symbol representing the length field of an array.
*/
public final VarSymbol lengthVar;
@@ -641,12 +635,6 @@ public class Symtab {
synthesizeBoxTypeIfMissing(floatType);
synthesizeBoxTypeIfMissing(voidType);
- // For string templates
- stringTemplateType = enterClass("java.lang.StringTemplate");
- templateRuntimeType = enterClass("java.lang.runtime.TemplateRuntime");
- processorType = enterClass("java.lang.StringTemplate$Processor");
- linkageType = enterClass("java.lang.StringTemplate$Processor$Linkage");
-
// Enter a synthetic class that is used to mark internal
// proprietary classes in ct.sym. This class does not have a
// class file.
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
index 65da42f3fbc..0d6e39c8b06 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -4992,32 +4992,6 @@ public class Attr extends JCTree.Visitor {
return (tag == CLASS) ? syms.stringType : syms.typeOfTag[tag.ordinal()];
}
- public void visitStringTemplate(JCStringTemplate tree) {
- JCExpression processor = tree.processor;
- Type processorType = attribTree(processor, env, new ResultInfo(KindSelector.VAL, Type.noType));
- chk.checkProcessorType(processor, processorType, env);
- Type processMethodType = getProcessMethodType(tree, processorType);
- tree.processMethodType = processMethodType;
- Type resultType = processMethodType.getReturnType();
-
- Env localEnv = env.dup(tree, env.info.dup());
-
- for (JCExpression arg : tree.expressions) {
- chk.checkNonVoid(arg.pos(), attribExpr(arg, localEnv));
- }
-
- tree.type = resultType;
- result = resultType;
- check(tree, resultType, KindSelector.VAL, resultInfo);
- }
-
- private Type getProcessMethodType(JCStringTemplate tree, Type processorType) {
- MethodSymbol processSymbol = rs.resolveInternalMethod(tree.pos(),
- env, types.skipTypeVars(processorType, false),
- names.process, List.of(syms.stringTemplateType), List.nil());
- return types.memberType(processorType, processSymbol);
- }
-
public void visitTypeIdent(JCPrimitiveTypeTree tree) {
result = check(tree, syms.typeOfTag[tree.typetag.ordinal()], KindSelector.TYP, resultInfo);
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
index 834d976a7c8..1e717b2b034 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -4475,26 +4475,6 @@ public class Check {
}
}
- public Type checkProcessorType(JCExpression processor, Type resultType, Env env) {
- Type processorType = processor.type;
- Type interfaceType = types.asSuper(processorType, syms.processorType.tsym);
-
- if (interfaceType != null) {
- List typeArguments = interfaceType.getTypeArguments();
-
- if (typeArguments.size() == 2) {
- resultType = typeArguments.head;
- } else {
- resultType = syms.objectType;
- }
- } else {
- log.error(DiagnosticFlag.RESOLVE_ERROR, processor.pos,
- Errors.NotAProcessorType(processorType.tsym));
- }
-
- return resultType;
- }
-
public void checkLeaksNotAccessible(Env env, JCClassDecl check) {
JCCompilationUnit toplevel = env.toplevel;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/CompileStates.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/CompileStates.java
index 0f808af0308..b044f956fdf 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/CompileStates.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/CompileStates.java
@@ -59,11 +59,10 @@ public class CompileStates extends HashMap, CompileStates.Compi
ATTR(4),
FLOW(5),
TRANSTYPES(6),
- TRANSLITERALS(7),
- TRANSPATTERNS(8),
- UNLAMBDA(9),
- LOWER(10),
- GENERATE(11);
+ TRANSPATTERNS(7),
+ UNLAMBDA(8),
+ LOWER(9),
+ GENERATE(10);
CompileState(int value) {
this.value = value;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
index 98a060d6bf8..4c9a28102e0 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
@@ -1744,15 +1744,6 @@ public class Flow {
}
}
- @Override
- public void visitStringTemplate(JCStringTemplate tree) {
- for (Type thrown : tree.processMethodType.getThrownTypes()) {
- markThrown(tree, thrown);
- }
-
- scan(tree.expressions);
- }
-
void checkCaughtType(DiagnosticPosition pos, Type exc, List thrownInTry, List caughtInTry) {
if (chk.subset(exc, caughtInTry)) {
log.error(pos, Errors.ExceptAlreadyCaught(exc));
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransLiterals.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransLiterals.java
deleted file mode 100644
index fef3a6c0526..00000000000
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransLiterals.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (c) 2023, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package com.sun.tools.javac.comp;
-
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
-import com.sun.tools.javac.code.Symbol.MethodSymbol;
-import com.sun.tools.javac.code.Symbol.VarSymbol;
-import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.*;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.*;
-import com.sun.tools.javac.tree.TreeInfo;
-import com.sun.tools.javac.tree.TreeMaker;
-import com.sun.tools.javac.tree.TreeTranslator;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Names;
-
-import java.util.Iterator;
-
-/** This pass translates constructed literals (string templates, ...) to conventional Java.
- *
- * This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.
- */
-public final class TransLiterals extends TreeTranslator {
- /**
- * The context key for the TransTypes phase.
- */
- protected static final Context.Key transLiteralsKey = new Context.Key<>();
-
- /**
- * Get the instance for this context.
- */
- public static TransLiterals instance(Context context) {
- TransLiterals instance = context.get(transLiteralsKey);
- if (instance == null)
- instance = new TransLiterals(context);
- return instance;
- }
-
- private final Symtab syms;
- private final Resolve rs;
- private final Types types;
- private final Operators operators;
- private final Names names;
- private TreeMaker make = null;
- private Env env = null;
- private ClassSymbol currentClass = null;
- private MethodSymbol currentMethodSym = null;
-
- protected TransLiterals(Context context) {
- context.put(transLiteralsKey, this);
- syms = Symtab.instance(context);
- rs = Resolve.instance(context);
- make = TreeMaker.instance(context);
- types = Types.instance(context);
- operators = Operators.instance(context);
- names = Names.instance(context);
- }
-
- JCExpression makeLit(Type type, Object value) {
- return make.Literal(type.getTag(), value).setType(type.constType(value));
- }
-
- JCExpression makeString(String string) {
- return makeLit(syms.stringType, string);
- }
-
- List makeStringList(List strings) {
- List exprs = List.nil();
- for (String string : strings) {
- exprs = exprs.append(makeString(string));
- }
- return exprs;
- }
-
- JCBinary makeBinary(JCTree.Tag optag, JCExpression lhs, JCExpression rhs) {
- JCBinary tree = make.Binary(optag, lhs, rhs);
- tree.operator = operators.resolveBinary(tree, optag, lhs.type, rhs.type);
- tree.type = tree.operator.type.getReturnType();
- return tree;
- }
-
- MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List args) {
- return rs.resolveInternalMethod(pos, env, qual, name, args, List.nil());
- }
-
- @Override
- public void visitClassDef(JCClassDecl tree) {
- ClassSymbol prevCurrentClass = currentClass;
- try {
- currentClass = tree.sym;
- super.visitClassDef(tree);
- } finally {
- currentClass = prevCurrentClass;
- }
- }
-
- @Override
- public void visitMethodDef(JCMethodDecl tree) {
- MethodSymbol prevMethodSym = currentMethodSym;
- try {
- currentMethodSym = tree.sym;
- super.visitMethodDef(tree);
- } finally {
- currentMethodSym = prevMethodSym;
- }
- }
-
- final class TransStringTemplate {
- final JCStringTemplate tree;
- final JCExpression processor;
- final List fragments;
- final List expressions;
- final List expressionTypes;
- final boolean useValuesList;
-
- TransStringTemplate(JCStringTemplate tree) {
- this.tree = tree;
- this.processor = tree.processor;
- this.fragments = tree.fragments;
- this.expressions = translate(tree.expressions);
- this.expressionTypes = expressions.stream()
- .map(arg -> arg.type == syms.botType ? syms.objectType : arg.type)
- .collect(List.collector());
- int slots = expressionTypes.stream()
- .mapToInt(t -> types.isSameType(t, syms.longType) ||
- types.isSameType(t, syms.doubleType) ? 2 : 1).sum();
- this.useValuesList = 200 < slots; // StringConcatFactory.MAX_INDY_CONCAT_ARG_SLOTS
- }
-
- JCExpression concatExpression(List fragments, List expressions) {
- JCExpression expr = null;
- Iterator iterator = expressions.iterator();
- for (String fragment : fragments) {
- expr = expr == null ? makeString(fragment)
- : makeBinary(Tag.PLUS, expr, makeString(fragment));
- if (iterator.hasNext()) {
- JCExpression expression = iterator.next();
- Type expressionType = expression.type;
- expr = makeBinary(Tag.PLUS, expr, expression.setType(expressionType));
- }
- }
- return expr;
- }
-
- JCExpression bsmCall(Name name, Name bootstrapName, Type type,
- List args,
- List argTypes,
- List staticArgValues,
- List staticArgsTypes) {
- Symbol bsm = rs.resolveQualifiedMethod(tree.pos(), env,
- syms.templateRuntimeType, bootstrapName, staticArgsTypes, List.nil());
- MethodType indyType = new MethodType(argTypes, type, List.nil(), syms.methodClass);
- DynamicMethodSymbol dynSym = new DynamicMethodSymbol(
- name,
- syms.noSymbol,
- ((MethodSymbol)bsm).asHandle(),
- indyType,
- staticArgValues.toArray(new LoadableConstant[0])
- );
- JCFieldAccess qualifier = make.Select(make.Type(syms.processorType), dynSym.name);
- qualifier.sym = dynSym;
- qualifier.type = type;
- JCMethodInvocation apply = make.Apply(List.nil(), qualifier, args);
- apply.type = type;
- return apply;
- }
-
- JCExpression processCall(JCExpression stringTemplate) {
- MethodSymbol appyMeth = lookupMethod(tree.pos(), names.process,
- syms.processorType, List.of(syms.stringTemplateType));
- JCExpression applySelect = make.Select(processor, appyMeth);
- JCExpression process = make.Apply(null, applySelect, List.of(stringTemplate))
- .setType(syms.objectType);
- JCTypeCast cast = make.TypeCast(tree.type, process);
- return cast;
- }
-
- JCExpression newStringTemplate() {
- List staticArgValues = List.nil();
- List staticArgsTypes =
- List.of(syms.methodHandleLookupType, syms.stringType,
- syms.methodTypeType);
- if (useValuesList) {
- JCNewArray fragmentArray = make.NewArray(make.Type(syms.stringType),
- List.nil(), makeStringList(fragments));
- fragmentArray.type = new ArrayType(syms.stringType, syms.arrayClass);
- JCNewArray valuesArray = make.NewArray(make.Type(syms.objectType),
- List.nil(), expressions);
- valuesArray.type = new ArrayType(syms.objectType, syms.arrayClass);
- return bsmCall(names.process, names.newLargeStringTemplate, syms.stringTemplateType,
- List.of(fragmentArray, valuesArray),
- List.of(fragmentArray.type, valuesArray.type),
- staticArgValues, staticArgsTypes);
- } else {
- for (String fragment : fragments) {
- staticArgValues = staticArgValues.append(LoadableConstant.String(fragment));
- staticArgsTypes = staticArgsTypes.append(syms.stringType);
- }
- return bsmCall(names.process, names.newStringTemplate, syms.stringTemplateType,
- expressions, expressionTypes, staticArgValues, staticArgsTypes);
- }
- }
-
- JCExpression bsmProcessCall() {
- List args = expressions.prepend(processor);
- List argTypes = expressionTypes.prepend(processor.type);
- VarSymbol processorSym = (VarSymbol)TreeInfo.symbol(processor);
- List staticArgValues = List.of(processorSym.asMethodHandle(true));
- List staticArgsTypes =
- List.of(syms.methodHandleLookupType, syms.stringType,
- syms.methodTypeType, syms.methodHandleType);
- for (String fragment : fragments) {
- staticArgValues = staticArgValues.append(LoadableConstant.String(fragment));
- staticArgsTypes = staticArgsTypes.append(syms.stringType);
- }
- return bsmCall(names.process, names.processStringTemplate, tree.type,
- args, argTypes, staticArgValues, staticArgsTypes);
- }
-
- boolean isNamedProcessor(Name name) {
- Symbol sym = switch (processor) {
- case JCIdent ident -> ident.sym;
- case JCFieldAccess access -> access.sym;
- default -> null;
- };
- if (sym instanceof VarSymbol varSym) {
- if (varSym.flags() == (Flags.PUBLIC | Flags.FINAL | Flags.STATIC) &&
- varSym.name == name &&
- types.isSameType(varSym.owner.type, syms.stringTemplateType)) {
- return true;
- }
- }
- return false;
- }
-
- boolean isLinkageProcessor() {
- return !useValuesList &&
- types.isSubtype(processor.type, syms.linkageType) &&
- processor.type.isFinal() &&
- TreeInfo.symbol(processor) instanceof VarSymbol varSymbol &&
- varSymbol.isStatic() &&
- varSymbol.isFinal();
- }
-
- JCExpression visit() {
- JCExpression result;
- make.at(tree.pos);
-
- if (isNamedProcessor(names.RAW)) {
- result = newStringTemplate();
- } else if (isNamedProcessor(names.STR)) {
- result = concatExpression(fragments, expressions);
- } else if (isLinkageProcessor()) {
- result = bsmProcessCall();
- } else {
- result = processCall(newStringTemplate());
- }
-
- return result;
- }
- }
-
- public void visitStringTemplate(JCStringTemplate tree) {
- int prevPos = make.pos;
- try {
- tree.processor = translate(tree.processor);
- tree.expressions = translate(tree.expressions);
-
- TransStringTemplate transStringTemplate = new TransStringTemplate(tree);
-
- result = transStringTemplate.visit();
- } catch (Throwable ex) {
- ex.printStackTrace();
- throw ex;
- } finally {
- make.at(prevPos);
- }
- }
-
- public void visitVarDef(JCVariableDecl tree) {
- MethodSymbol prevMethodSym = currentMethodSym;
- try {
- tree.mods = translate(tree.mods);
- tree.vartype = translate(tree.vartype);
- if (currentMethodSym == null) {
- // A class or instance field initializer.
- currentMethodSym =
- new MethodSymbol((tree.mods.flags& Flags.STATIC) | Flags.BLOCK,
- names.empty, null,
- currentClass);
- }
- if (tree.init != null) tree.init = translate(tree.init);
- result = tree;
- } finally {
- currentMethodSym = prevMethodSym;
- }
- }
-
- public JCTree translateTopLevelClass(Env env, JCTree cdef, TreeMaker make) {
- try {
- this.make = make;
- this.env = env;
- translate(cdef);
- } finally {
- this.make = null;
- this.env = null;
- }
-
- return cdef;
- }
-
-}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
index 36d3a2b24bd..fd3b507b038 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -837,14 +837,6 @@ public class TransTypes extends TreeTranslator {
}
}
- public void visitStringTemplate(JCStringTemplate tree) {
- tree.processor = translate(tree.processor, erasure(tree.processor.type));
- tree.expressions = tree.expressions.stream()
- .map(e -> translate(e, erasure(e.type))).collect(List.collector());
- tree.type = erasure(tree.type);
- result = tree;
- }
-
public void visitSelect(JCFieldAccess tree) {
Type t = types.skipTypeVars(tree.selected.type, false);
if (t.isCompound()) {
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
index a421bd6bca4..af5f3dccdd6 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
@@ -340,29 +340,6 @@ public class TypeEnter implements Completer {
javaLang, env);
}
- private void staticImports(JCCompilationUnit tree, Env env, ImportFilter staticImportFilter) {
- if (preview.isEnabled() && preview.isPreview(Feature.STRING_TEMPLATES)) {
- Lint prevLint = chk.setLint(lint.suppress(LintCategory.DEPRECATION, LintCategory.REMOVAL, LintCategory.PREVIEW));
- boolean prevPreviewCheck = chk.disablePreviewCheck;
-
- try {
- chk.disablePreviewCheck = true;
- String autoImports = """
- import static java.lang.StringTemplate.STR;
- """;
- Parser parser = parserFactory.newParser(autoImports, false, false, false, false);
- JCCompilationUnit importTree = parser.parseCompilationUnit();
-
- for (JCImport imp : importTree.getImports()) {
- doImport(imp);
- }
- } finally {
- chk.setLint(prevLint);
- chk.disablePreviewCheck = prevPreviewCheck;
- }
- }
- }
-
private void resolveImports(JCCompilationUnit tree, Env env) {
if (tree.starImportScope.isFilled()) {
// we must have already processed this toplevel
@@ -386,7 +363,6 @@ public class TypeEnter implements Completer {
chk.importAccessible(sym, packge);
importJavaLang(tree, env, typeImportFilter);
- staticImports(tree, env, staticImportFilter);
JCModuleDecl decl = tree.getModuleDecl();
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
index 63950ed2f68..9d5def3f781 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
@@ -1612,12 +1612,6 @@ public class JavaCompiler {
env.tree = transTypes.translateTopLevelClass(env.tree, localMake);
compileStates.put(env, CompileState.TRANSTYPES);
- if (shouldStop(CompileState.TRANSLITERALS))
- return;
-
- env.tree = TransLiterals.instance(context).translateTopLevelClass(env, env.tree, localMake);
- compileStates.put(env, CompileState.TRANSLITERALS);
-
if (shouldStop(CompileState.TRANSPATTERNS))
return;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java
index 406ed328769..88de2333069 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java
@@ -99,16 +99,6 @@ public class JavaTokenizer extends UnicodeReader {
*/
protected final StringBuilder sb;
- /**
- * Tokens pending to be read from string template embedded expressions.
- */
- protected List pendingTokens;
-
- /**
- * String template fragment ranges; end-endPos pairs.
- */
- protected List fragmentRanges;
-
/**
* The token kind, set by nextToken().
*/
@@ -139,16 +129,6 @@ public class JavaTokenizer extends UnicodeReader {
*/
protected boolean hasEscapeSequences;
- /**
- * true if contains templated string escape sequences, set by nextToken().
- */
- protected boolean isStringTemplate;
-
- /**
- * true if errors are pending from embedded expressions.
- */
- protected boolean hasStringTemplateErrors;
-
/**
* The set of lint options currently in effect. It is initialized
* from the context, and then is set/reset as needed by Attr as it
@@ -183,8 +163,6 @@ public class JavaTokenizer extends UnicodeReader {
this.preview = fac.preview;
this.lint = fac.lint;
this.sb = new StringBuilder(256);
- this.pendingTokens = List.nil();
- this.fragmentRanges = List.nil();
}
/**
@@ -339,86 +317,6 @@ public class JavaTokenizer extends UnicodeReader {
processLineTerminator(start, position());
}
- /**
- * Scan the content of a string template expression.
- *
- * @param pos start of literal
- * @param endPos start of embedded expression
- */
- private void scanEmbeddedExpression(int pos, int endPos) {
- // If first embedded expression.
- if (!isStringTemplate) {
- checkSourceLevel(pos, Feature.STRING_TEMPLATES);
- fragmentRanges = fragmentRanges.append(pos);
- isStringTemplate = true;
- }
- // Track end of previous fragment.
- fragmentRanges = fragmentRanges.append(endPos);
- // Keep backslash and add rest of placeholder.
- sb.append("{}");
-
- // Separate tokenizer for the embedded expression.
- JavaTokenizer tokenizer = new JavaTokenizer(fac, buffer(), length());
- tokenizer.reset(position());
-
- // Track brace depth.
- int braceCount = 0;
-
- // Accumulate tokens.
- List tokens = List.nil();
-
- // Stash first left brace.
- Token token = tokenizer.readToken();
- tokens = tokens.append(token);
-
- while (isAvailable()) {
- // Read and stash next token.
- token = tokenizer.readToken();
- tokens = tokens.append(token);
-
- // Intercept errors
- if (token.kind == TokenKind.ERROR) {
- // Track start of next fragment.
- if (isTextBlock) {
- reset(length());
- } else {
- skipToEOLN();
- }
- hasStringTemplateErrors = true;
- return;
- }
-
- if (token.kind == TokenKind.RBRACE) {
- // Potential closing brace.
- if (braceCount == 0) {
- break;
- }
-
- braceCount--;
- } else if (token.kind == TokenKind.LBRACE) {
- // Nesting deeper.
- braceCount++;
- } else if (token.kind == TokenKind.STRINGFRAGMENT) {
- tokens = tokens.appendList(tokenizer.pendingTokens);
- tokenizer.pendingTokens = List.nil();
- } else if (token.kind == TokenKind.EOF) {
- break;
- }
- }
-
- // If no closing brace will be picked up as an unterminated string.
-
- // Set main tokenizer to continue at next position.
- int position = tokenizer.position();
- reset(position);
-
- // Track start of next fragment.
- fragmentRanges = fragmentRanges.append(position);
-
- // Pend the expression tokens after the STRINGFRAGMENT.
- pendingTokens = pendingTokens.appendList(tokens);
- }
-
/**
* Processes the current character and places in the literal buffer. If the current
* character is a backslash then the next character is assumed to be a proper
@@ -480,17 +378,6 @@ public class JavaTokenizer extends UnicodeReader {
}
break;
- case '{':
- if (isString) {
- scanEmbeddedExpression(pos, backslash);
- if (hasStringTemplateErrors) {
- return;
- }
- } else {
- lexError(position(), Errors.IllegalEscChar);
- }
- break;
-
default:
lexError(position(), Errors.IllegalEscChar);
break;
@@ -530,13 +417,7 @@ public class JavaTokenizer extends UnicodeReader {
// While characters are available.
while (isAvailable()) {
- if (hasStringTemplateErrors) {
- break;
- } else if (accept("\"\"\"")) {
- if (isStringTemplate && tk == TokenKind.STRINGLITERAL) {
- tk = TokenKind.STRINGFRAGMENT;
- }
-
+ if (accept("\"\"\"")) {
return;
}
@@ -560,12 +441,7 @@ public class JavaTokenizer extends UnicodeReader {
// While characters are available.
while (isAvailable()) {
- if (hasStringTemplateErrors) {
- break;
- } else if (accept('\"')) {
- if (isStringTemplate && tk == TokenKind.STRINGLITERAL) {
- tk = TokenKind.STRINGFRAGMENT;
- }
+ if (accept('\"')) {
return;
}
@@ -580,18 +456,11 @@ public class JavaTokenizer extends UnicodeReader {
}
}
- // String ended without close delimiter sequence or has embedded expression errors.
- if (isStringTemplate) {
- lexError(pos, isTextBlock ? Errors.TextBlockTemplateIsNotWellFormed
- : Errors.StringTemplateIsNotWellFormed);
- fragmentRanges = List.nil();
- pendingTokens = List.nil();
- } else {
- lexError(pos, isTextBlock ? Errors.UnclosedTextBlock
- : Errors.UnclosedStrLit);
- }
+ // String ended without close delimiter sequence.
+ lexError(pos, isTextBlock ? Errors.UnclosedTextBlock
+ : Errors.UnclosedStrLit);
- if (!hasStringTemplateErrors && firstEOLN != NOT_FOUND) {
+ if (firstEOLN != NOT_FOUND) {
// Reset recovery position to point after text block open delimiter sequence.
reset(firstEOLN);
}
@@ -906,20 +775,11 @@ public class JavaTokenizer extends UnicodeReader {
* Read token (main entrypoint.)
*/
public Token readToken() {
- if (pendingTokens.nonEmpty()) {
- Token token = pendingTokens.head;
- pendingTokens = pendingTokens.tail;
- return token;
- }
-
sb.setLength(0);
name = null;
radix = 0;
isTextBlock = false;
hasEscapeSequences = false;
- isStringTemplate = false;
- hasStringTemplateErrors = false;
- fragmentRanges = List.nil();
int pos;
List comments = null;
@@ -1134,7 +994,6 @@ public class JavaTokenizer extends UnicodeReader {
case '\"': // (Spec. 3.10)
scanString(pos);
break loop;
-
default:
if (isSpecial(get())) {
scanOperator();
@@ -1181,11 +1040,6 @@ public class JavaTokenizer extends UnicodeReader {
int endPos = position();
- // Track end of final fragment.
- if (isStringTemplate) {
- fragmentRanges = fragmentRanges.append(endPos);
- }
-
if (tk.tag == Token.Tag.DEFAULT) {
return new Token(tk, pos, endPos, comments);
} else if (tk.tag == Token.Tag.NAMED) {
@@ -1217,11 +1071,6 @@ public class JavaTokenizer extends UnicodeReader {
}
}
- if (isStringTemplate) {
- // Break string into fragments and then return the first of the framents.
- return getFragments(string, comments);
- }
-
// Translate escape sequences if present.
if (hasEscapeSequences) {
try {
@@ -1251,66 +1100,6 @@ public class JavaTokenizer extends UnicodeReader {
}
}
- /**
- * Convert the string into a list of pending tokens to precede embedded
- * expressions.
- *
- * @param string string to fragment
- * @param comments comments for first token
- *
- * @return first pending token.
- */
- private Token getFragments(String string, List comments) {
- List tokens = List.nil();
- Iterator rangeIter = fragmentRanges.iterator();
- for (String fragment : fragment(string)) {
- fragment = fragment.translateEscapes();
- int fragmentPos = rangeIter.next();
- int fragmentEndPos = rangeIter.next();
- Token token = new StringToken(TokenKind.STRINGFRAGMENT,
- fragmentPos, fragmentEndPos, fragment, comments);
- comments = null;
- tokens = tokens.append(token);
- }
- pendingTokens = tokens.appendList(pendingTokens);
- Token first = pendingTokens.head;
- pendingTokens = pendingTokens.tail;
- return first;
- }
-
- /**
- * Break string template up into fragments. "\{}" indicates where
- * embedded expressions occur.
- *
- * @param string string template
- *
- * @return list of fragment strings
- */
- List fragment(String string) {
- List fragments = List.nil();
- StringBuilder sb = new StringBuilder();
- int length = string.length();
- for (int i = 0; i < length; i++) {
- char ch = string.charAt(i);
- if (ch != '\\') {
- sb.append(ch);
- } else if (i + 2 < length && string.charAt(i + 1) == '{'
- && string.charAt(i + 2) == '}') {
- fragments = fragments.append(sb.toString());
- sb.setLength(0);
- i += 2;
- } else if (i + 1 < length){
- sb.append('\\');
- sb.append(string.charAt(i + 1));
- i++;
- } else {
- // Error already reported.
- }
- }
- fragments = fragments.append(sb.toString());
- return fragments;
- }
-
/**
* Appends a comment to the list of comments preceding the current token.
*
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
index 4df24ef8c9d..bc53b18b3a5 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -692,59 +692,6 @@ public class JavacParser implements Parser {
return t;
}
- /**
- * StringTemplate =
- * [STRINGFRAGMENT] [EmbeddedExpression]
- * | STRINGLITERAL
- *
- * EmbeddedExpression =
- * LBRACE term RBRACE
- */
- JCExpression stringTemplate(JCExpression processor) {
- checkSourceLevel(Feature.STRING_TEMPLATES);
- // Disable standalone string templates
- if (processor == null) {
- log.error(DiagnosticFlag.SYNTAX, token.pos,
- Errors.ProcessorMissingFromStringTemplateExpression);
- }
- int oldmode = mode;
- selectExprMode();
- Token stringToken = token;
- int pos = stringToken.pos;
- int endPos = stringToken.endPos;
- TokenKind kind = stringToken.kind;
- String string = token.stringVal();
- List fragments = List.of(string);
- List expressions = List.nil();
- nextToken();
- if (kind != STRINGLITERAL) {
- while (token.kind == STRINGFRAGMENT) {
- stringToken = token;
- endPos = stringToken.endPos;
- string = stringToken.stringVal();
- fragments = fragments.append(string);
- nextToken();
- }
- while (token.pos < endPos && token.kind != DEFAULT && token.kind != ERROR) {
- accept(LBRACE);
- JCExpression expression = token.kind == RBRACE ? F.at(pos).Literal(TypeTag.BOT, null)
- : term(EXPR);
- expressions = expressions.append(expression);
- if (token.kind != ERROR) {
- accept(RBRACE);
- }
- }
- // clean up remaining expression tokens if error
- while (token.pos < endPos && token.kind != DEFAULT) {
- nextToken();
- }
- S.setPrevToken(stringToken);
- }
- JCExpression t = toP(F.at(pos).StringTemplate(processor, fragments, expressions));
- setMode(oldmode);
- return t;
- }
-
JCExpression literal(Name prefix) {
return literal(prefix, token.pos);
}
@@ -1422,14 +1369,6 @@ public class JavacParser implements Parser {
t = literal(names.empty);
} else return illegal();
break;
- case STRINGFRAGMENT:
- if (typeArgs == null && isMode(EXPR)) {
- selectExprMode();
- t = stringTemplate(null);
- } else {
- return illegal();
- }
- break;
case NEW:
if (typeArgs != null) return illegal();
if (isMode(EXPR)) {
@@ -1560,12 +1499,6 @@ public class JavacParser implements Parser {
t = innerCreator(pos1, typeArgs, t);
typeArgs = null;
break loop;
- case STRINGFRAGMENT:
- case STRINGLITERAL:
- if (typeArgs != null) return illegal();
- t = stringTemplate(t);
- typeArgs = null;
- break loop;
}
}
@@ -1789,12 +1722,6 @@ public class JavacParser implements Parser {
if (token.kind == LT) typeArgs = typeArguments(false);
t = innerCreator(pos2, typeArgs, t);
typeArgs = null;
- } else if (token.kind == TokenKind.STRINGFRAGMENT ||
- token.kind == TokenKind.STRINGLITERAL) {
- if (typeArgs != null) {
- return illegal();
- }
- t = stringTemplate(t);
} else {
List tyannos = null;
if (isMode(TYPE) && token.kind == MONKEYS_AT) {
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
index b672c1546fc..273c5bef7b4 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -1361,19 +1361,6 @@ compiler.err.unclosed.str.lit=\
compiler.err.unclosed.text.block=\
unclosed text block
-compiler.err.string.template.is.not.well.formed=\
- string template is not well formed
-
-compiler.err.text.block.template.is.not.well.formed=\
- text block template is not well formed
-
-compiler.err.processor.missing.from.string.template.expression=\
- processor missing from string template expression
-
-# 0: symbol
-compiler.err.not.a.processor.type=\
- not a processor type: {0}
-
# 0: string
compiler.err.unsupported.encoding=\
unsupported encoding: {0}
@@ -3219,9 +3206,6 @@ compiler.misc.feature.case.null=\
compiler.misc.feature.pattern.switch=\
patterns in switch statements
-compiler.misc.feature.string.templates=\
- string templates
-
compiler.misc.feature.unconditional.patterns.in.instanceof=\
unconditional patterns in instanceof
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
index fcb73c59686..56daece2b2f 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -269,10 +269,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
*/
LITERAL,
- /** String template expression.
- */
- STRING_TEMPLATE,
-
/** Basic type identifiers, of type TypeIdent.
*/
TYPEIDENT,
@@ -2481,59 +2477,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
- /**
- * String template expression.
- */
- public static class JCStringTemplate extends JCExpression implements StringTemplateTree {
- public JCExpression processor;
- public List fragments;
- public List expressions;
- public Type processMethodType;
-
- protected JCStringTemplate(JCExpression processor,
- List fragments,
- List expressions) {
- this.processor = processor;
- this.fragments = fragments;
- this.expressions = expressions;
- }
-
- @Override
- public ExpressionTree getProcessor() {
- return processor;
- }
-
- @Override
- public List getFragments() {
- return fragments;
- }
-
- @Override
- public List extends ExpressionTree> getExpressions() {
- return expressions;
- }
-
- @Override @DefinedBy(Api.COMPILER_TREE)
- public Kind getKind() {
- return Kind.TEMPLATE;
- }
-
- @Override @DefinedBy(Api.COMPILER_TREE)
- public Tag getTag() {
- return STRING_TEMPLATE;
- }
-
- @Override @DefinedBy(Api.COMPILER_TREE)
- public void accept(Visitor v) {
- v.visitStringTemplate(this);
- }
-
- @Override @DefinedBy(Api.COMPILER_TREE)
- public R accept(TreeVisitor v, D d) {
- return v.visitStringTemplate(this, d);
- }
- }
-
/**
* An array selection
*/
@@ -3513,9 +3456,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
JCFieldAccess Select(JCExpression selected, Name selector);
JCIdent Ident(Name idname);
JCLiteral Literal(TypeTag tag, Object value);
- JCStringTemplate StringTemplate(JCExpression processor,
- List fragments,
- List expressions);
JCPrimitiveTypeTree TypeIdent(TypeTag typetag);
JCArrayTypeTree TypeArray(JCExpression elemtype);
JCTypeApply TypeApply(JCExpression clazz, List arguments);
@@ -3587,7 +3527,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public void visitReference(JCMemberReference that) { visitTree(that); }
public void visitIdent(JCIdent that) { visitTree(that); }
public void visitLiteral(JCLiteral that) { visitTree(that); }
- public void visitStringTemplate(JCStringTemplate that) { visitTree(that); }
public void visitTypeIdent(JCPrimitiveTypeTree that) { visitTree(that); }
public void visitTypeArray(JCArrayTypeTree that) { visitTree(that); }
public void visitTypeApply(JCTypeApply that) { visitTree(that); }
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java
index 06a8f6f143f..c63706639b3 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -1476,21 +1476,6 @@ public class Pretty extends JCTree.Visitor {
}
}
- public void visitStringTemplate(JCStringTemplate tree) {
- try {
- JCExpression processor = tree.processor;
- print("[");
- printExpr(processor);
- print("]");
- print("\"" + tree.fragments.stream().collect(Collectors.joining("\\{}")) + "\"");
- print("(");
- printExprs(tree.expressions);
- print(")");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
public void visitTypeIdent(JCPrimitiveTypeTree tree) {
try {
switch(tree.typetag) {
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java
index 4d15bb8f9ae..7c2ef075ccb 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2024, 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
@@ -283,14 +283,6 @@ public class TreeCopier implements TreeVisitor {
return M.at(t.pos).Literal(t.typetag, t.value);
}
- @DefinedBy(Api.COMPILER_TREE)
- public JCTree visitStringTemplate(StringTemplateTree node, P p) {
- JCStringTemplate t = (JCStringTemplate) node;
- JCExpression processor = copy(t.processor, p);
- List expressions = copy(t.expressions, p);
- return M.at(t.pos).StringTemplate(processor, t.fragments, expressions);
- }
-
@DefinedBy(Api.COMPILER_TREE)
public JCTree visitMethod(MethodTree node, P p) {
JCMethodDecl t = (JCMethodDecl) node;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java
index ee4477135c6..0a2fe85d1c3 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -371,7 +371,6 @@ public class TreeInfo {
case PLUS_ASG: case MINUS_ASG:
case MUL_ASG: case DIV_ASG: case MOD_ASG:
case APPLY: case NEWCLASS:
- case STRING_TEMPLATE:
case ERRONEOUS:
return true;
default:
@@ -587,10 +586,6 @@ public class TreeInfo {
JCBindingPattern node = (JCBindingPattern)tree;
return getStartPos(node.var);
}
- case STRING_TEMPLATE: {
- JCStringTemplate node = (JCStringTemplate) tree;
- return node.processor == null ? node.pos : getStartPos(node.processor);
- }
case ERRONEOUS: {
JCErroneous node = (JCErroneous)tree;
if (node.errs != null && node.errs.nonEmpty()) {
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
index 21ced44c80e..fe6ca849f31 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -552,14 +552,6 @@ public class TreeMaker implements JCTree.Factory {
return tree;
}
- public JCStringTemplate StringTemplate(JCExpression processor,
- List fragments,
- List expressions) {
- JCStringTemplate tree = new JCStringTemplate(processor, fragments, expressions);
- tree.pos = pos;
- return tree;
- }
-
public JCPrimitiveTypeTree TypeIdent(TypeTag typetag) {
JCPrimitiveTypeTree tree = new JCPrimitiveTypeTree(typetag);
tree.pos = pos;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java
index f07871eff24..fc356047542 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2024, 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
@@ -353,11 +353,6 @@ public class TreeScanner extends Visitor {
public void visitLiteral(JCLiteral tree) {
}
- public void visitStringTemplate(JCStringTemplate tree) {
- scan(tree.processor);
- scan(tree.expressions);
- }
-
public void visitTypeIdent(JCPrimitiveTypeTree tree) {
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java
index a3b7e4fc5d6..59a7457e6d0 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -409,13 +409,6 @@ public class TreeTranslator extends JCTree.Visitor {
result = tree;
}
- public void visitStringTemplate(JCStringTemplate tree) {
- tree.processor = translate(tree.processor);
- tree.expressions = translate(tree.expressions);
-
- result = tree;
- }
-
public void visitTypeIdent(JCPrimitiveTypeTree tree) {
result = tree;
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
index 229c710f7df..6c48490cf16 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2024, 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
@@ -227,14 +227,6 @@ public class Names {
public final Name enumSwitch;
public final Name enumConstant;
- // templated string
- public final Name process;
- public final Name STR;
- public final Name RAW;
- public final Name newStringTemplate;
- public final Name newLargeStringTemplate;
- public final Name processStringTemplate;
-
public final Name.Table table;
@SuppressWarnings("this-escape")
@@ -413,13 +405,6 @@ public class Names {
permits = fromString("permits");
sealed = fromString("sealed");
- // templated string
- process = fromString("process");
- STR = fromString("STR");
- RAW = fromString("RAW");
- newStringTemplate = fromString("newStringTemplate");
- newLargeStringTemplate = fromString("newLargeStringTemplate");
- processStringTemplate = fromString("processStringTemplate");
// pattern switches
typeSwitch = fromString("typeSwitch");
diff --git a/test/jdk/java/lang/String/concat/MakeConcatWithTemplate.java b/test/jdk/java/lang/String/concat/MakeConcatWithTemplate.java
deleted file mode 100644
index 2927afe4f9d..00000000000
--- a/test/jdk/java/lang/String/concat/MakeConcatWithTemplate.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2023, 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.
- */
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.StringConcatFactory;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @test
- * @summary Test StringConcatFactory.makeConcatWithTemplate... methods.
- * @enablePreview true
- */
-
-public class MakeConcatWithTemplate {
- public static void main(String... args) {
- makeConcatWithTemplate();
- makeConcatWithTemplateCluster();
- makeConcatWithTemplateGetters();
- }
-
- static List fragments(int n) {
- String[] array = new String[n];
- Arrays.fill(array, "abc");
- return Arrays.asList(array);
- }
-
- static List> types(int n) {
- Class>[] array = new Class>[n];
- Arrays.fill(array, int.class);
- return Arrays.asList(array);
- }
-
- static List values(int n) {
- Integer[] array = new Integer[n];
- Arrays.fill(array, 123);
- return Arrays.asList(array);
- }
-
- static List getters(int n) {
- MethodHandle[] array = new MethodHandle[n];
- MethodHandle m = MethodHandles.dropArguments(MethodHandles.constant(int.class, 123), 0, Object.class);
- Arrays.fill(array, m);
- return Arrays.asList(array);
- }
-
- static void makeConcatWithTemplate() {
- try {
- int n = StringConcatFactory.MAX_INDY_CONCAT_ARG_SLOTS - 1;
- MethodHandle m = StringConcatFactory.makeConcatWithTemplate(fragments(n + 1), types(n));
- m.invokeWithArguments(values(n));
- } catch (Throwable e) {
- throw new RuntimeException(e);
- }
-
- try {
- int n = StringConcatFactory.MAX_INDY_CONCAT_ARG_SLOTS;
- MethodHandle m = StringConcatFactory.makeConcatWithTemplate(fragments(n + 1), types(n));
- m.invokeWithArguments(values(n));
- } catch (Throwable e) {
- throw new RuntimeException(e);
- }
-
- boolean threw = false;
- try {
- int n = StringConcatFactory.MAX_INDY_CONCAT_ARG_SLOTS + 1;
- MethodHandle m = StringConcatFactory.makeConcatWithTemplate(fragments(n + 1), types(n));
- m.invokeWithArguments(values(n));
- } catch (Throwable e) {
- threw = true;
- }
-
- if (!threw) {
- throw new RuntimeException("Exception expected - makeConcatWithTemplate");
- }
- }
-
- static void makeConcatWithTemplateCluster() {
- int n = StringConcatFactory.MAX_INDY_CONCAT_ARG_SLOTS;
- int c = 3;
- try {
- List ms = StringConcatFactory.makeConcatWithTemplateCluster(fragments(c * n + 1), types(c * n), n);
- MethodHandle m0 = ms.get(0);
- MethodHandle m1 = ms.get(1);
- MethodHandle m2 = ms.get(2);
- MethodHandle m3 = ms.get(3);
-
- String s = (String)m0.invokeWithArguments(values(n));
- List args = new ArrayList<>();
- args.add(s);
- args.addAll(values(n - 1)); // one less for carry over string
- s = (String)m1.invokeWithArguments(args);
- args.clear();
- args.add(s);
- args.addAll(values(n - 1)); // one less for carry over string
- s = (String)m2.invokeWithArguments(args);
- args.clear();
- args.add(s);
- args.addAll(values(2)); // two remaining carry overs
- s = (String)m3.invokeWithArguments(args);
- } catch (Throwable e) {
- throw new RuntimeException(e);
- }
- }
-
- static void makeConcatWithTemplateGetters() {
- int n = StringConcatFactory.MAX_INDY_CONCAT_ARG_SLOTS;
- int c = 3;
- try {
- MethodHandle m = StringConcatFactory.makeConcatWithTemplateGetters(fragments(c * n + 1), getters(c * n), n);
- String s = (String)m.invoke(null);
- } catch (Throwable e) {
- throw new RuntimeException(e);
- }
- }
-
-}
diff --git a/test/jdk/java/lang/template/Basic.java b/test/jdk/java/lang/template/Basic.java
deleted file mode 100644
index e0096ce0b57..00000000000
--- a/test/jdk/java/lang/template/Basic.java
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * Copyright (c) 2023, 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
- * @bug 0000000
- * @summary Exercise runtime handing of templated strings.
- * @enablePreview true
- */
-
-import java.lang.StringTemplate.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.function.*;
-
-import static java.lang.StringTemplate.RAW;
-
-public class Basic {
- public static void main(String... arg) {
- equalsHashCode();
- concatenationTests();
- componentTests();
- limitsTests();
- processorTests();
- stringTemplateCoverage();
- simpleProcessorCoverage();
- }
-
- static void ASSERT(String a, String b) {
- if (!Objects.equals(a, b)) {
- System.out.println(a);
- System.out.println(b);
- throw new RuntimeException("Test failed");
- }
- }
-
- static void ASSERT(Object a, Object b) {
- if (!Objects.deepEquals(a, b)) {
- System.out.println(a);
- System.out.println(b);
- throw new RuntimeException("Test failed");
- }
- }
-
- /*
- * equals and hashCode tests.
- */
- static void equalsHashCode() {
- int x = 10;
- int y = 20;
- int a = 10;
- int b = 20;
-
- StringTemplate st0 = RAW."\{x} + \{y} = \{x + y}";
- StringTemplate st1 = RAW."\{a} + \{b} = \{a + b}";
- StringTemplate st2 = RAW."\{x} + \{y} = \{x + y}!";
- x++;
- StringTemplate st3 = RAW."\{x} + \{y} = \{x + y}";
-
- if (!st0.equals(st1)) throw new RuntimeException("st0 != st1");
- if (st0.equals(st2)) throw new RuntimeException("st0 == st2");
- if (st0.equals(st3)) throw new RuntimeException("st0 == st3");
-
- if (st0.hashCode() != st1.hashCode()) throw new RuntimeException("st0.hashCode() != st1.hashCode()");
- }
-
- /*
- * Concatenation tests.
- */
- static void concatenationTests() {
- int x = 10;
- int y = 20;
-
- ASSERT(STR."\{x} \{y}", x + " " + y);
- ASSERT(STR."\{x + y}", "" + (x + y));
- ASSERT(STR.process(RAW."\{x} \{y}"), x + " " + y);
- ASSERT(STR.process(RAW."\{x + y}"), "" + (x + y));
- ASSERT((RAW."\{x} \{y}").process(STR), x + " " + y);
- ASSERT((RAW."\{x + y}").process(STR), "" + (x + y));
- }
-
- /*
- * Component tests.
- */
- static void componentTests() {
- int x = 10;
- int y = 20;
-
- StringTemplate st = RAW."\{x} + \{y} = \{x + y}";
- ASSERT(st.values(), List.of(x, y, x + y));
- ASSERT(st.fragments(), List.of("", " + ", " = ", ""));
- ASSERT(st.interpolate(), x + " + " + y + " = " + (x + y));
- }
-
- /*
- * Limits tests.
- */
- static void limitsTests() {
- int x = 9;
-
- StringTemplate ts250 = RAW."""
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- """;
- ASSERT(ts250.values().size(), 250);
- ASSERT(ts250.interpolate(), """
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999
- """);
-
- StringTemplate ts251 = RAW."""
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}
- """;
- ASSERT(ts251.values().size(), 251);
- ASSERT(ts251.interpolate(), """
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9
- """);
-
- StringTemplate ts252 = RAW."""
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}
- """;
- ASSERT(ts252.values().size(), 252);
- ASSERT(ts252.interpolate(), """
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 99
- """);
-
- StringTemplate ts253 = RAW."""
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}
- """;
- ASSERT(ts253.values().size(), 253);
- ASSERT(ts253.interpolate(), """
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 999
- """);
-
- StringTemplate ts254 = RAW."""
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}
- """;
- ASSERT(ts254.values().size(), 254);
- ASSERT(ts254.interpolate(), """
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999
- """);
-
- StringTemplate ts255 = RAW."""
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}
- """;
- ASSERT(ts255.values().size(), 255);
- ASSERT(ts255.interpolate(), """
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 99999
- """);
-
- StringTemplate ts256 = RAW."""
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
-
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}
- \{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x}\{x} \{x}\{x}\{x}\{x}\{x}\{x}
- """;
- ASSERT(ts256.values().size(), 256);
- ASSERT(ts256.interpolate(), """
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 9999999999
-
- 9999999999 9999999999
- 9999999999 9999999999
- 9999999999 999999
- """);
-
- }
-
- /*
- * Processor tests.
- */
- public static final Processor STRINGIFY = st -> {
- List values = st.values()
- .stream()
- .map(v -> (Object)String.valueOf(v))
- .toList();
-
- return StringTemplate.of(st.fragments(), values);
- };
-
- public static final Processor UPPER = st -> {
- List fragments = st.fragments()
- .stream()
- .map(String::toUpperCase)
- .toList();
-
- return StringTemplate.of(fragments, st.values());
- };
-
- public static final Processor CHAIN = st -> {
- st = STRINGIFY.process(st);
- st = UPPER.process(st);
- return STR.process(st);
- };
-
- static void processorTests() {
- String name = "Joan";
- int age = 25;
- ASSERT(CHAIN."\{name} is \{age} years old", "Joan IS 25 YEARS OLD");
- }
-
- /*
- * StringTemplate coverage
- */
- static void stringTemplateCoverage() {
- StringTemplate tsNoValues = StringTemplate.of("No Values");
-
- ASSERT(tsNoValues.values(), List.of());
- ASSERT(tsNoValues.fragments(), List.of("No Values"));
- ASSERT(tsNoValues.interpolate(), STR."No Values");
-
- int x = 10, y = 20;
- StringTemplate src = RAW."\{x} + \{y} = \{x + y}";
- StringTemplate tsValues = StringTemplate.of(src.fragments(), src.values());
- ASSERT(tsValues.fragments(), List.of("", " + ", " = ", ""));
- ASSERT(tsValues.values(), List.of(x, y, x + y));
- ASSERT(tsValues.interpolate(), x + " + " + y + " = " + (x + y));
- ASSERT(StringTemplate.combine(src, src).interpolate(),
- RAW."\{x} + \{y} = \{x + y}\{x} + \{y} = \{x + y}".interpolate());
- ASSERT(StringTemplate.combine(src), src);
- ASSERT(StringTemplate.combine().interpolate(), "");
- ASSERT(StringTemplate.combine(List.of(src, src)).interpolate(),
- RAW."\{x} + \{y} = \{x + y}\{x} + \{y} = \{x + y}".interpolate());
- }
-
- /*
- * SimpleProcessor coverage.
- */
-
- static class Processor0 implements Processor {
- @Override
- public String process(StringTemplate stringTemplate) throws IllegalArgumentException {
- StringBuilder sb = new StringBuilder();
- Iterator fragmentsIter = stringTemplate.fragments().iterator();
-
- for (Object value : stringTemplate.values()) {
- sb.append(fragmentsIter.next());
-
- if (value instanceof Boolean) {
- throw new IllegalArgumentException("I don't like Booleans");
- }
-
- sb.append(value);
- }
-
- sb.append(fragmentsIter.next());
-
- return sb.toString();
- }
- }
-
- static Processor0 processor0 = new Processor0();
-
- static Processor processor1 =
- st -> st.interpolate();
-
- static Processor processor2 = st -> st.interpolate();
-
- static Processor processor3 = st -> st.interpolate();
-
- static Processor processor4 = st ->
- StringTemplate.interpolate(st.fragments(), st.values());
-
-
- static void simpleProcessorCoverage() {
- try {
- int x = 10;
- int y = 20;
- ASSERT(processor0."\{x} + \{y} = \{x + y}", "10 + 20 = 30");
- ASSERT(processor1."\{x} + \{y} = \{x + y}", "10 + 20 = 30");
- ASSERT(processor2."\{x} + \{y} = \{x + y}", "10 + 20 = 30");
- ASSERT(processor3."\{x} + \{y} = \{x + y}", "10 + 20 = 30");
- ASSERT(processor4."\{x} + \{y} = \{x + y}", "10 + 20 = 30");
- } catch (IllegalArgumentException ex) {
- throw new RuntimeException("processor fail");
- }
- }
-
- static String justify(String string, int width) {
- boolean leftJustify = width < 0;
- int length = string.length();
- width = Math.abs(width);
- int diff = width - length;
-
- if (diff < 0) {
- string = "*".repeat(width);
- } else if (0 < diff) {
- if (leftJustify) {
- string += " ".repeat(diff);
- } else {
- string = " ".repeat(diff) + string;
- }
- }
-
- return string;
- }
-
-}
diff --git a/test/jdk/java/lang/template/FormatterBuilder.java b/test/jdk/java/lang/template/FormatterBuilder.java
deleted file mode 100644
index 1fc79e89846..00000000000
--- a/test/jdk/java/lang/template/FormatterBuilder.java
+++ /dev/null
@@ -1,961 +0,0 @@
-/*
- * Copyright (c) 2023, 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
- * @bug 0000000
- * @summary Exercise format builder.
- * @enablePreview true
- */
-
-import java.util.FormatProcessor;
-import java.util.Objects;
-import java.util.Locale;
-import java.util.MissingFormatArgumentException;
-import java.util.UnknownFormatConversionException;
-
-import static java.util.FormatProcessor.FMT;
-
-public class FormatterBuilder {
- public static void main(String... args) {
- Locale.setDefault(Locale.US);
- suite(FMT);
- Locale thai = Locale.forLanguageTag("th-TH-u-nu-thai");
- FormatProcessor thaiFormat = FormatProcessor.create(thai);
- Locale.setDefault(thai);
- suite(thaiFormat);
- }
-
- static void test(String a, String b) {
- if (!Objects.equals(a, b)) {
- throw new RuntimeException("format and FMT do not match: " + a + " : " + b);
- }
- }
-
- public interface Executable {
- void execute() throws Throwable;
- }
-
- static void assertThrows(Class expectedType, Executable executable, String message) {
- Throwable actualException = null;
- try {
- executable.execute();
- } catch (Throwable e) {
- actualException = e;
- }
- if (actualException == null) {
- throw new RuntimeException("Expected " + expectedType + " to be thrown, but nothing was thrown.");
- }
- if (!expectedType.isInstance(actualException)) {
- throw new RuntimeException("Expected " + expectedType + " to be thrown, but was thrown " + actualException.getClass());
- }
- if (message != null && !message.equals(actualException.getMessage())) {
- throw new RuntimeException("Expected " + message + " to be thrown, but was thrown " + actualException.getMessage());
- }
- }
-
- static void suite(FormatProcessor fmt) {
- Object nullObject = null;
- test(String.format("%b", false), fmt."%b\{false}");
- test(String.format("%b", true), fmt."%b\{true}");
- test(String.format("%10b", false), fmt."%10b\{false}");
- test(String.format("%10b", true), fmt."%10b\{true}");
- test(String.format("%-10b", false), fmt."%-10b\{false}");
- test(String.format("%-10b", true), fmt."%-10b\{true}");
- test(String.format("%B", false), fmt."%B\{false}");
- test(String.format("%B", true), fmt."%B\{true}");
- test(String.format("%10B", false), fmt."%10B\{false}");
- test(String.format("%10B", true), fmt."%10B\{true}");
- test(String.format("%-10B", false), fmt."%-10B\{false}");
- test(String.format("%-10B", true), fmt."%-10B\{true}");
-
- test(String.format("%h", 12345), fmt."%h\{12345}");
- test(String.format("%h", 0xABCDE), fmt."%h\{0xABCDE}");
- test(String.format("%10h", 12345), fmt."%10h\{12345}");
- test(String.format("%10h", 0xABCDE), fmt."%10h\{0xABCDE}");
- test(String.format("%-10h", 12345), fmt."%-10h\{12345}");
- test(String.format("%-10h", 0xABCDE), fmt."%-10h\{0xABCDE}");
- test(String.format("%H", 12345), fmt."%H\{12345}");
- test(String.format("%H", 0xABCDE), fmt."%H\{0xABCDE}");
- test(String.format("%10H", 12345), fmt."%10H\{12345}");
- test(String.format("%10H", 0xABCDE), fmt."%10H\{0xABCDE}");
- test(String.format("%-10H", 12345), fmt."%-10H\{12345}");
- test(String.format("%-10H", 0xABCDE), fmt."%-10H\{0xABCDE}");
-
- test(String.format("%s", (byte)0xFF), fmt."%s\{(byte)0xFF}");
- test(String.format("%s", (short)0xFFFF), fmt."%s\{(short)0xFFFF}");
- test(String.format("%s", 12345), fmt."%s\{12345}");
- test(String.format("%s", 12345L), fmt."%s\{12345L}");
- test(String.format("%s", 1.33f), fmt."%s\{1.33f}");
- test(String.format("%s", 1.33), fmt."%s\{1.33}");
- test(String.format("%s", "abcde"), fmt."%s\{"abcde"}");
- test(String.format("%s", nullObject), fmt."%s\{nullObject}");
- test(String.format("%10s", (byte)0xFF), fmt."%10s\{(byte)0xFF}");
- test(String.format("%10s", (short)0xFFFF), fmt."%10s\{(short)0xFFFF}");
- test(String.format("%10s", 12345), fmt."%10s\{12345}");
- test(String.format("%10s", 12345L), fmt."%10s\{12345L}");
- test(String.format("%10s", 1.33f), fmt."%10s\{1.33f}");
- test(String.format("%10s", 1.33), fmt."%10s\{1.33}");
- test(String.format("%10s", "abcde"), fmt."%10s\{"abcde"}");
- test(String.format("%10s", nullObject), fmt."%10s\{nullObject}");
- test(String.format("%-10s", (byte)0xFF), fmt."%-10s\{(byte)0xFF}");
- test(String.format("%-10s", (short)0xFFFF), fmt."%-10s\{(short)0xFFFF}");
- test(String.format("%-10s", 12345), fmt."%-10s\{12345}");
- test(String.format("%-10s", 12345L), fmt."%-10s\{12345L}");
- test(String.format("%-10s", 1.33f), fmt."%-10s\{1.33f}");
- test(String.format("%-10s", 1.33), fmt."%-10s\{1.33}");
- test(String.format("%-10s", "abcde"), fmt."%-10s\{"abcde"}");
- test(String.format("%-10s", nullObject), fmt."%-10s\{nullObject}");
- test(String.format("%S", (byte)0xFF), fmt."%S\{(byte)0xFF}");
- test(String.format("%S", (short)0xFFFF), fmt."%S\{(short)0xFFFF}");
- test(String.format("%S", 12345), fmt."%S\{12345}");
- test(String.format("%S", 12345L), fmt."%S\{12345L}");
- test(String.format("%S", 1.33f), fmt."%S\{1.33f}");
- test(String.format("%S", 1.33), fmt."%S\{1.33}");
- test(String.format("%S", "abcde"), fmt."%S\{"abcde"}");
- test(String.format("%S", nullObject), fmt."%S\{nullObject}");
- test(String.format("%10S", (byte)0xFF), fmt."%10S\{(byte)0xFF}");
- test(String.format("%10S", (short)0xFFFF), fmt."%10S\{(short)0xFFFF}");
- test(String.format("%10S", 12345), fmt."%10S\{12345}");
- test(String.format("%10S", 12345L), fmt."%10S\{12345L}");
- test(String.format("%10S", 1.33f), fmt."%10S\{1.33f}");
- test(String.format("%10S", 1.33), fmt."%10S\{1.33}");
- test(String.format("%10S", "abcde"), fmt."%10S\{"abcde"}");
- test(String.format("%10S", nullObject), fmt."%10S\{nullObject}");
- test(String.format("%-10S", (byte)0xFF), fmt."%-10S\{(byte)0xFF}");
- test(String.format("%-10S", (short)0xFFFF), fmt."%-10S\{(short)0xFFFF}");
- test(String.format("%-10S", 12345), fmt."%-10S\{12345}");
- test(String.format("%-10S", 12345L), fmt."%-10S\{12345L}");
- test(String.format("%-10S", 1.33f), fmt."%-10S\{1.33f}");
- test(String.format("%-10S", 1.33), fmt."%-10S\{1.33}");
- test(String.format("%-10S", "abcde"), fmt."%-10S\{"abcde"}");
- test(String.format("%-10S", nullObject), fmt."%-10S\{nullObject}");
-
- test(String.format("%c", 'a'), fmt."%c\{'a'}");
- test(String.format("%10c", 'a'), fmt."%10c\{'a'}");
- test(String.format("%-10c", 'a'), fmt."%-10c\{'a'}");
- test(String.format("%C", 'a'), fmt."%C\{'a'}");
- test(String.format("%10C", 'a'), fmt."%10C\{'a'}");
- test(String.format("%-10C", 'a'), fmt."%-10C\{'a'}");
-
- test(String.format("%d", -12345), fmt."%d\{-12345}");
- test(String.format("%d", 0), fmt."%d\{0}");
- test(String.format("%d", 12345), fmt."%d\{12345}");
- test(String.format("%10d", -12345), fmt."%10d\{-12345}");
- test(String.format("%10d", 0), fmt."%10d\{0}");
- test(String.format("%10d", 12345), fmt."%10d\{12345}");
- test(String.format("%-10d", -12345), fmt."%-10d\{-12345}");
- test(String.format("%-10d", 0), fmt."%-10d\{0}");
- test(String.format("%-10d", 12345), fmt."%-10d\{12345}");
- test(String.format("%,d", -12345), fmt."%,d\{-12345}");
- test(String.format("%,d", 0), fmt."%,d\{0}");
- test(String.format("%,d", 12345), fmt."%,d\{12345}");
- test(String.format("%,10d", -12345), fmt."%,10d\{-12345}");
- test(String.format("%,10d", 0), fmt."%,10d\{0}");
- test(String.format("%,10d", 12345), fmt."%,10d\{12345}");
- test(String.format("%,-10d", -12345), fmt."%,-10d\{-12345}");
- test(String.format("%,-10d", 0), fmt."%,-10d\{0}");
- test(String.format("%,-10d", 12345), fmt."%,-10d\{12345}");
- test(String.format("%010d", -12345), fmt."%010d\{-12345}");
- test(String.format("%010d", 0), fmt."%010d\{0}");
- test(String.format("%010d", 12345), fmt."%010d\{12345}");
- test(String.format("%,010d", -12345), fmt."%,010d\{-12345}");
- test(String.format("%,010d", 0), fmt."%,010d\{0}");
- test(String.format("%,010d", 12345), fmt."%,010d\{12345}");
-
- test(String.format("%d", -12345), fmt."%d\{-12345}");
- test(String.format("%d", 0), fmt."%d\{0}");
- test(String.format("%d", 12345), fmt."%d\{12345}");
- test(String.format("%10d", -12345), fmt."%10d\{-12345}");
- test(String.format("%10d", 0), fmt."%10d\{0}");
- test(String.format("%10d", 12345), fmt."%10d\{12345}");
- test(String.format("%-10d", -12345), fmt."%-10d\{-12345}");
- test(String.format("%-10d", 0), fmt."%-10d\{0}");
- test(String.format("%-10d", 12345), fmt."%-10d\{12345}");
- test(String.format("%,d", -12345), fmt."%,d\{-12345}");
- test(String.format("%,d", 0), fmt."%,d\{0}");
- test(String.format("%,d", 12345), fmt."%,d\{12345}");
- test(String.format("%,10d", -12345), fmt."%,10d\{-12345}");
- test(String.format("%,10d", 0), fmt."%,10d\{0}");
- test(String.format("%,10d", 12345), fmt."%,10d\{12345}");
- test(String.format("%,-10d", -12345), fmt."%,-10d\{-12345}");
- test(String.format("%,-10d", 0), fmt."%,-10d\{0}");
- test(String.format("%,-10d", 12345), fmt."%,-10d\{12345}");
- test(String.format("% d", -12345), fmt."% d\{-12345}");
- test(String.format("% d", 0), fmt."% d\{0}");
- test(String.format("% d", 12345), fmt."% d\{12345}");
- test(String.format("% 10d", -12345), fmt."% 10d\{-12345}");
- test(String.format("% 10d", 0), fmt."% 10d\{0}");
- test(String.format("% 10d", 12345), fmt."% 10d\{12345}");
- test(String.format("% -10d", -12345), fmt."% -10d\{-12345}");
- test(String.format("% -10d", 0), fmt."% -10d\{0}");
- test(String.format("% -10d", 12345), fmt."% -10d\{12345}");
- test(String.format("%, d", -12345), fmt."%, d\{-12345}");
- test(String.format("%, d", 0), fmt."%, d\{0}");
- test(String.format("%, d", 12345), fmt."%, d\{12345}");
- test(String.format("%, 10d", -12345), fmt."%, 10d\{-12345}");
- test(String.format("%, 10d", 0), fmt."%, 10d\{0}");
- test(String.format("%, 10d", 12345), fmt."%, 10d\{12345}");
- test(String.format("%, -10d", -12345), fmt."%, -10d\{-12345}");
- test(String.format("%, -10d", 0), fmt."%, -10d\{0}");
- test(String.format("%, -10d", 12345), fmt."%, -10d\{12345}");
- test(String.format("%010d", -12345), fmt."%010d\{-12345}");
- test(String.format("%010d", 0), fmt."%010d\{0}");
- test(String.format("%010d", 12345), fmt."%010d\{12345}");
- test(String.format("%,010d", -12345), fmt."%,010d\{-12345}");
- test(String.format("%,010d", 0), fmt."%,010d\{0}");
- test(String.format("%,010d", 12345), fmt."%,010d\{12345}");
- test(String.format("% 010d", -12345), fmt."% 010d\{-12345}");
- test(String.format("% 010d", 0), fmt."% 010d\{0}");
- test(String.format("% 010d", 12345), fmt."% 010d\{12345}");
- test(String.format("%, 010d", -12345), fmt."%, 010d\{-12345}");
- test(String.format("%, 010d", 0), fmt."%, 010d\{0}");
- test(String.format("%, 010d", 12345), fmt."%, 010d\{12345}");
-
- test(String.format("%d", -12345), fmt."%d\{-12345}");
- test(String.format("%d", 0), fmt."%d\{0}");
- test(String.format("%d", 12345), fmt."%d\{12345}");
- test(String.format("%10d", -12345), fmt."%10d\{-12345}");
- test(String.format("%10d", 0), fmt."%10d\{0}");
- test(String.format("%10d", 12345), fmt."%10d\{12345}");
- test(String.format("%-10d", -12345), fmt."%-10d\{-12345}");
- test(String.format("%-10d", 0), fmt."%-10d\{0}");
- test(String.format("%-10d", 12345), fmt."%-10d\{12345}");
- test(String.format("%,d", -12345), fmt."%,d\{-12345}");
- test(String.format("%,d", 0), fmt."%,d\{0}");
- test(String.format("%,d", 12345), fmt."%,d\{12345}");
- test(String.format("%,10d", -12345), fmt."%,10d\{-12345}");
- test(String.format("%,10d", 0), fmt."%,10d\{0}");
- test(String.format("%,10d", 12345), fmt."%,10d\{12345}");
- test(String.format("%,-10d", -12345), fmt."%,-10d\{-12345}");
- test(String.format("%,-10d", 0), fmt."%,-10d\{0}");
- test(String.format("%,-10d", 12345), fmt."%,-10d\{12345}");
- test(String.format("%+d", -12345), fmt."%+d\{-12345}");
- test(String.format("%+d", 0), fmt."%+d\{0}");
- test(String.format("%+d", 12345), fmt."%+d\{12345}");
- test(String.format("%+10d", -12345), fmt."%+10d\{-12345}");
- test(String.format("%+10d", 0), fmt."%+10d\{0}");
- test(String.format("%+10d", 12345), fmt."%+10d\{12345}");
- test(String.format("%+-10d", -12345), fmt."%+-10d\{-12345}");
- test(String.format("%+-10d", 0), fmt."%+-10d\{0}");
- test(String.format("%+-10d", 12345), fmt."%+-10d\{12345}");
- test(String.format("%,+d", -12345), fmt."%,+d\{-12345}");
- test(String.format("%,+d", 0), fmt."%,+d\{0}");
- test(String.format("%,+d", 12345), fmt."%,+d\{12345}");
- test(String.format("%,+10d", -12345), fmt."%,+10d\{-12345}");
- test(String.format("%,+10d", 0), fmt."%,+10d\{0}");
- test(String.format("%,+10d", 12345), fmt."%,+10d\{12345}");
- test(String.format("%,+-10d", -12345), fmt."%,+-10d\{-12345}");
- test(String.format("%,+-10d", 0), fmt."%,+-10d\{0}");
- test(String.format("%,+-10d", 12345), fmt."%,+-10d\{12345}");
- test(String.format("%010d", -12345), fmt."%010d\{-12345}");
- test(String.format("%010d", 0), fmt."%010d\{0}");
- test(String.format("%010d", 12345), fmt."%010d\{12345}");
- test(String.format("%,010d", -12345), fmt."%,010d\{-12345}");
- test(String.format("%,010d", 0), fmt."%,010d\{0}");
- test(String.format("%,010d", 12345), fmt."%,010d\{12345}");
- test(String.format("%+010d", -12345), fmt."%+010d\{-12345}");
- test(String.format("%+010d", 0), fmt."%+010d\{0}");
- test(String.format("%+010d", 12345), fmt."%+010d\{12345}");
- test(String.format("%,+010d", -12345), fmt."%,+010d\{-12345}");
- test(String.format("%,+010d", 0), fmt."%,+010d\{0}");
- test(String.format("%,+010d", 12345), fmt."%,+010d\{12345}");
-
- test(String.format("%d", -12345), fmt."%d\{-12345}");
- test(String.format("%d", 0), fmt."%d\{0}");
- test(String.format("%d", 12345), fmt."%d\{12345}");
- test(String.format("%10d", -12345), fmt."%10d\{-12345}");
- test(String.format("%10d", 0), fmt."%10d\{0}");
- test(String.format("%10d", 12345), fmt."%10d\{12345}");
- test(String.format("%-10d", -12345), fmt."%-10d\{-12345}");
- test(String.format("%-10d", 0), fmt."%-10d\{0}");
- test(String.format("%-10d", 12345), fmt."%-10d\{12345}");
- test(String.format("%,d", -12345), fmt."%,d\{-12345}");
- test(String.format("%,d", 0), fmt."%,d\{0}");
- test(String.format("%,d", 12345), fmt."%,d\{12345}");
- test(String.format("%,10d", -12345), fmt."%,10d\{-12345}");
- test(String.format("%,10d", 0), fmt."%,10d\{0}");
- test(String.format("%,10d", 12345), fmt."%,10d\{12345}");
- test(String.format("%,-10d", -12345), fmt."%,-10d\{-12345}");
- test(String.format("%,-10d", 0), fmt."%,-10d\{0}");
- test(String.format("%,-10d", 12345), fmt."%,-10d\{12345}");
- test(String.format("%(d", -12345), fmt."%(d\{-12345}");
- test(String.format("%(d", 0), fmt."%(d\{0}");
- test(String.format("%(d", 12345), fmt."%(d\{12345}");
- test(String.format("%(10d", -12345), fmt."%(10d\{-12345}");
- test(String.format("%(10d", 0), fmt."%(10d\{0}");
- test(String.format("%(10d", 12345), fmt."%(10d\{12345}");
- test(String.format("%(-10d", -12345), fmt."%(-10d\{-12345}");
- test(String.format("%(-10d", 0), fmt."%(-10d\{0}");
- test(String.format("%(-10d", 12345), fmt."%(-10d\{12345}");
- test(String.format("%,(d", -12345), fmt."%,(d\{-12345}");
- test(String.format("%,(d", 0), fmt."%,(d\{0}");
- test(String.format("%,(d", 12345), fmt."%,(d\{12345}");
- test(String.format("%,(10d", -12345), fmt."%,(10d\{-12345}");
- test(String.format("%,(10d", 0), fmt."%,(10d\{0}");
- test(String.format("%,(10d", 12345), fmt."%,(10d\{12345}");
- test(String.format("%,(-10d", -12345), fmt."%,(-10d\{-12345}");
- test(String.format("%,(-10d", 0), fmt."%,(-10d\{0}");
- test(String.format("%,(-10d", 12345), fmt."%,(-10d\{12345}");
- test(String.format("%010d", -12345), fmt."%010d\{-12345}");
- test(String.format("%010d", 0), fmt."%010d\{0}");
- test(String.format("%010d", 12345), fmt."%010d\{12345}");
- test(String.format("%,010d", -12345), fmt."%,010d\{-12345}");
- test(String.format("%,010d", 0), fmt."%,010d\{0}");
- test(String.format("%,010d", 12345), fmt."%,010d\{12345}");
- test(String.format("%(010d", -12345), fmt."%(010d\{-12345}");
- test(String.format("%(010d", 0), fmt."%(010d\{0}");
- test(String.format("%(010d", 12345), fmt."%(010d\{12345}");
- test(String.format("%,(010d", -12345), fmt."%,(010d\{-12345}");
- test(String.format("%,(010d", 0), fmt."%,(010d\{0}");
- test(String.format("%,(010d", 12345), fmt."%,(010d\{12345}");
-
- test(String.format("%o", -12345), fmt."%o\{-12345}");
- test(String.format("%o", 0), fmt."%o\{0}");
- test(String.format("%o", 12345), fmt."%o\{12345}");
- test(String.format("%10o", -12345), fmt."%10o\{-12345}");
- test(String.format("%10o", 0), fmt."%10o\{0}");
- test(String.format("%10o", 12345), fmt."%10o\{12345}");
- test(String.format("%-10o", -12345), fmt."%-10o\{-12345}");
- test(String.format("%-10o", 0), fmt."%-10o\{0}");
- test(String.format("%-10o", 12345), fmt."%-10o\{12345}");
- test(String.format("%#o", -12345), fmt."%#o\{-12345}");
- test(String.format("%#o", 0), fmt."%#o\{0}");
- test(String.format("%#o", 12345), fmt."%#o\{12345}");
- test(String.format("%#10o", -12345), fmt."%#10o\{-12345}");
- test(String.format("%#10o", 0), fmt."%#10o\{0}");
- test(String.format("%#10o", 12345), fmt."%#10o\{12345}");
- test(String.format("%#-10o", -12345), fmt."%#-10o\{-12345}");
- test(String.format("%#-10o", 0), fmt."%#-10o\{0}");
- test(String.format("%#-10o", 12345), fmt."%#-10o\{12345}");
- test(String.format("%010o", -12345), fmt."%010o\{-12345}");
- test(String.format("%010o", 0), fmt."%010o\{0}");
- test(String.format("%010o", 12345), fmt."%010o\{12345}");
- test(String.format("%#010o", -12345), fmt."%#010o\{-12345}");
- test(String.format("%#010o", 0), fmt."%#010o\{0}");
- test(String.format("%#010o", 12345), fmt."%#010o\{12345}");
-
- test(String.format("%x", -12345), fmt."%x\{-12345}");
- test(String.format("%x", 0), fmt."%x\{0}");
- test(String.format("%x", 12345), fmt."%x\{12345}");
- test(String.format("%10x", -12345), fmt."%10x\{-12345}");
- test(String.format("%10x", 0), fmt."%10x\{0}");
- test(String.format("%10x", 12345), fmt."%10x\{12345}");
- test(String.format("%-10x", -12345), fmt."%-10x\{-12345}");
- test(String.format("%-10x", 0), fmt."%-10x\{0}");
- test(String.format("%-10x", 12345), fmt."%-10x\{12345}");
- test(String.format("%X", -12345), fmt."%X\{-12345}");
- test(String.format("%X", 0), fmt."%X\{0}");
- test(String.format("%X", 12345), fmt."%X\{12345}");
- test(String.format("%10X", -12345), fmt."%10X\{-12345}");
- test(String.format("%10X", 0), fmt."%10X\{0}");
- test(String.format("%10X", 12345), fmt."%10X\{12345}");
- test(String.format("%-10X", -12345), fmt."%-10X\{-12345}");
- test(String.format("%-10X", 0), fmt."%-10X\{0}");
- test(String.format("%-10X", 12345), fmt."%-10X\{12345}");
- test(String.format("%#x", -12345), fmt."%#x\{-12345}");
- test(String.format("%#x", 0), fmt."%#x\{0}");
- test(String.format("%#x", 12345), fmt."%#x\{12345}");
- test(String.format("%#10x", -12345), fmt."%#10x\{-12345}");
- test(String.format("%#10x", 0), fmt."%#10x\{0}");
- test(String.format("%#10x", 12345), fmt."%#10x\{12345}");
- test(String.format("%#-10x", -12345), fmt."%#-10x\{-12345}");
- test(String.format("%#-10x", 0), fmt."%#-10x\{0}");
- test(String.format("%#-10x", 12345), fmt."%#-10x\{12345}");
- test(String.format("%#X", -12345), fmt."%#X\{-12345}");
- test(String.format("%#X", 0), fmt."%#X\{0}");
- test(String.format("%#X", 12345), fmt."%#X\{12345}");
- test(String.format("%#10X", -12345), fmt."%#10X\{-12345}");
- test(String.format("%#10X", 0), fmt."%#10X\{0}");
- test(String.format("%#10X", 12345), fmt."%#10X\{12345}");
- test(String.format("%#-10X", -12345), fmt."%#-10X\{-12345}");
- test(String.format("%#-10X", 0), fmt."%#-10X\{0}");
- test(String.format("%#-10X", 12345), fmt."%#-10X\{12345}");
- test(String.format("%010x", -12345), fmt."%010x\{-12345}");
- test(String.format("%010x", 0), fmt."%010x\{0}");
- test(String.format("%010x", 12345), fmt."%010x\{12345}");
- test(String.format("%010X", -12345), fmt."%010X\{-12345}");
- test(String.format("%010X", 0), fmt."%010X\{0}");
- test(String.format("%010X", 12345), fmt."%010X\{12345}");
- test(String.format("%#010x", -12345), fmt."%#010x\{-12345}");
- test(String.format("%#010x", 0), fmt."%#010x\{0}");
- test(String.format("%#010x", 12345), fmt."%#010x\{12345}");
- test(String.format("%#010X", -12345), fmt."%#010X\{-12345}");
- test(String.format("%#010X", 0), fmt."%#010X\{0}");
- test(String.format("%#010X", 12345), fmt."%#010X\{12345}");
-
- test(String.format("%f", -12345.6), fmt."%f\{-12345.6}");
- test(String.format("%f", 0.0), fmt."%f\{0.0}");
- test(String.format("%f", 12345.6), fmt."%f\{12345.6}");
- test(String.format("%10f", -12345.6), fmt."%10f\{-12345.6}");
- test(String.format("%10f", 0.0), fmt."%10f\{0.0}");
- test(String.format("%10f", 12345.6), fmt."%10f\{12345.6}");
- test(String.format("%-10f", -12345.6), fmt."%-10f\{-12345.6}");
- test(String.format("%-10f", 0.0), fmt."%-10f\{0.0}");
- test(String.format("%-10f", 12345.6), fmt."%-10f\{12345.6}");
- test(String.format("%,f", -12345.6), fmt."%,f\{-12345.6}");
- test(String.format("%,f", 0.0), fmt."%,f\{0.0}");
- test(String.format("%,f", 12345.6), fmt."%,f\{12345.6}");
- test(String.format("%,10f", -12345.6), fmt."%,10f\{-12345.6}");
- test(String.format("%,10f", 0.0), fmt."%,10f\{0.0}");
- test(String.format("%,10f", 12345.6), fmt."%,10f\{12345.6}");
- test(String.format("%,-10f", -12345.6), fmt."%,-10f\{-12345.6}");
- test(String.format("%,-10f", 0.0), fmt."%,-10f\{0.0}");
- test(String.format("%,-10f", 12345.6), fmt."%,-10f\{12345.6}");
-
- test(String.format("%f", -12345.6), fmt."%f\{-12345.6}");
- test(String.format("%f", 0.0), fmt."%f\{0.0}");
- test(String.format("%f", 12345.6), fmt."%f\{12345.6}");
- test(String.format("%10f", -12345.6), fmt."%10f\{-12345.6}");
- test(String.format("%10f", 0.0), fmt."%10f\{0.0}");
- test(String.format("%10f", 12345.6), fmt."%10f\{12345.6}");
- test(String.format("%-10f", -12345.6), fmt."%-10f\{-12345.6}");
- test(String.format("%-10f", 0.0), fmt."%-10f\{0.0}");
- test(String.format("%-10f", 12345.6), fmt."%-10f\{12345.6}");
- test(String.format("%,f", -12345.6), fmt."%,f\{-12345.6}");
- test(String.format("%,f", 0.0), fmt."%,f\{0.0}");
- test(String.format("%,f", 12345.6), fmt."%,f\{12345.6}");
- test(String.format("%,10f", -12345.6), fmt."%,10f\{-12345.6}");
- test(String.format("%,10f", 0.0), fmt."%,10f\{0.0}");
- test(String.format("%,10f", 12345.6), fmt."%,10f\{12345.6}");
- test(String.format("%,-10f", -12345.6), fmt."%,-10f\{-12345.6}");
- test(String.format("%,-10f", 0.0), fmt."%,-10f\{0.0}");
- test(String.format("%,-10f", 12345.6), fmt."%,-10f\{12345.6}");
- test(String.format("% f", -12345.6), fmt."% f\{-12345.6}");
- test(String.format("% f", 0.0), fmt."% f\{0.0}");
- test(String.format("% f", 12345.6), fmt."% f\{12345.6}");
- test(String.format("% 10f", -12345.6), fmt."% 10f\{-12345.6}");
- test(String.format("% 10f", 0.0), fmt."% 10f\{0.0}");
- test(String.format("% 10f", 12345.6), fmt."% 10f\{12345.6}");
- test(String.format("% -10f", -12345.6), fmt."% -10f\{-12345.6}");
- test(String.format("% -10f", 0.0), fmt."% -10f\{0.0}");
- test(String.format("% -10f", 12345.6), fmt."% -10f\{12345.6}");
- test(String.format("%, f", -12345.6), fmt."%, f\{-12345.6}");
- test(String.format("%, f", 0.0), fmt."%, f\{0.0}");
- test(String.format("%, f", 12345.6), fmt."%, f\{12345.6}");
- test(String.format("%, 10f", -12345.6), fmt."%, 10f\{-12345.6}");
- test(String.format("%, 10f", 0.0), fmt."%, 10f\{0.0}");
- test(String.format("%, 10f", 12345.6), fmt."%, 10f\{12345.6}");
- test(String.format("%, -10f", -12345.6), fmt."%, -10f\{-12345.6}");
- test(String.format("%, -10f", 0.0), fmt."%, -10f\{0.0}");
- test(String.format("%, -10f", 12345.6), fmt."%, -10f\{12345.6}");
-
- test(String.format("%f", -12345.6), fmt."%f\{-12345.6}");
- test(String.format("%f", 0.0), fmt."%f\{0.0}");
- test(String.format("%f", 12345.6), fmt."%f\{12345.6}");
- test(String.format("%10f", -12345.6), fmt."%10f\{-12345.6}");
- test(String.format("%10f", 0.0), fmt."%10f\{0.0}");
- test(String.format("%10f", 12345.6), fmt."%10f\{12345.6}");
- test(String.format("%-10f", -12345.6), fmt."%-10f\{-12345.6}");
- test(String.format("%-10f", 0.0), fmt."%-10f\{0.0}");
- test(String.format("%-10f", 12345.6), fmt."%-10f\{12345.6}");
- test(String.format("%,f", -12345.6), fmt."%,f\{-12345.6}");
- test(String.format("%,f", 0.0), fmt."%,f\{0.0}");
- test(String.format("%,f", 12345.6), fmt."%,f\{12345.6}");
- test(String.format("%,10f", -12345.6), fmt."%,10f\{-12345.6}");
- test(String.format("%,10f", 0.0), fmt."%,10f\{0.0}");
- test(String.format("%,10f", 12345.6), fmt."%,10f\{12345.6}");
- test(String.format("%,-10f", -12345.6), fmt."%,-10f\{-12345.6}");
- test(String.format("%,-10f", 0.0), fmt."%,-10f\{0.0}");
- test(String.format("%,-10f", 12345.6), fmt."%,-10f\{12345.6}");
- test(String.format("%+f", -12345.6), fmt."%+f\{-12345.6}");
- test(String.format("%+f", 0.0), fmt."%+f\{0.0}");
- test(String.format("%+f", 12345.6), fmt."%+f\{12345.6}");
- test(String.format("%+10f", -12345.6), fmt."%+10f\{-12345.6}");
- test(String.format("%+10f", 0.0), fmt."%+10f\{0.0}");
- test(String.format("%+10f", 12345.6), fmt."%+10f\{12345.6}");
- test(String.format("%+-10f", -12345.6), fmt."%+-10f\{-12345.6}");
- test(String.format("%+-10f", 0.0), fmt."%+-10f\{0.0}");
- test(String.format("%+-10f", 12345.6), fmt."%+-10f\{12345.6}");
- test(String.format("%,+f", -12345.6), fmt."%,+f\{-12345.6}");
- test(String.format("%,+f", 0.0), fmt."%,+f\{0.0}");
- test(String.format("%,+f", 12345.6), fmt."%,+f\{12345.6}");
- test(String.format("%,+10f", -12345.6), fmt."%,+10f\{-12345.6}");
- test(String.format("%,+10f", 0.0), fmt."%,+10f\{0.0}");
- test(String.format("%,+10f", 12345.6), fmt."%,+10f\{12345.6}");
- test(String.format("%,+-10f", -12345.6), fmt."%,+-10f\{-12345.6}");
- test(String.format("%,+-10f", 0.0), fmt."%,+-10f\{0.0}");
- test(String.format("%,+-10f", 12345.6), fmt."%,+-10f\{12345.6}");
-
- test(String.format("%f", -12345.6), fmt."%f\{-12345.6}");
- test(String.format("%f", 0.0), fmt."%f\{0.0}");
- test(String.format("%f", 12345.6), fmt."%f\{12345.6}");
- test(String.format("%10f", -12345.6), fmt."%10f\{-12345.6}");
- test(String.format("%10f", 0.0), fmt."%10f\{0.0}");
- test(String.format("%10f", 12345.6), fmt."%10f\{12345.6}");
- test(String.format("%-10f", -12345.6), fmt."%-10f\{-12345.6}");
- test(String.format("%-10f", 0.0), fmt."%-10f\{0.0}");
- test(String.format("%-10f", 12345.6), fmt."%-10f\{12345.6}");
- test(String.format("%,f", -12345.6), fmt."%,f\{-12345.6}");
- test(String.format("%,f", 0.0), fmt."%,f\{0.0}");
- test(String.format("%,f", 12345.6), fmt."%,f\{12345.6}");
- test(String.format("%,10f", -12345.6), fmt."%,10f\{-12345.6}");
- test(String.format("%,10f", 0.0), fmt."%,10f\{0.0}");
- test(String.format("%,10f", 12345.6), fmt."%,10f\{12345.6}");
- test(String.format("%,-10f", -12345.6), fmt."%,-10f\{-12345.6}");
- test(String.format("%,-10f", 0.0), fmt."%,-10f\{0.0}");
- test(String.format("%,-10f", 12345.6), fmt."%,-10f\{12345.6}");
- test(String.format("%(f", -12345.6), fmt."%(f\{-12345.6}");
- test(String.format("%(f", 0.0), fmt."%(f\{0.0}");
- test(String.format("%(f", 12345.6), fmt."%(f\{12345.6}");
- test(String.format("%(10f", -12345.6), fmt."%(10f\{-12345.6}");
- test(String.format("%(10f", 0.0), fmt."%(10f\{0.0}");
- test(String.format("%(10f", 12345.6), fmt."%(10f\{12345.6}");
- test(String.format("%(-10f", -12345.6), fmt."%(-10f\{-12345.6}");
- test(String.format("%(-10f", 0.0), fmt."%(-10f\{0.0}");
- test(String.format("%(-10f", 12345.6), fmt."%(-10f\{12345.6}");
- test(String.format("%,(f", -12345.6), fmt."%,(f\{-12345.6}");
- test(String.format("%,(f", 0.0), fmt."%,(f\{0.0}");
- test(String.format("%,(f", 12345.6), fmt."%,(f\{12345.6}");
- test(String.format("%,(10f", -12345.6), fmt."%,(10f\{-12345.6}");
- test(String.format("%,(10f", 0.0), fmt."%,(10f\{0.0}");
- test(String.format("%,(10f", 12345.6), fmt."%,(10f\{12345.6}");
- test(String.format("%,(-10f", -12345.6), fmt."%,(-10f\{-12345.6}");
- test(String.format("%,(-10f", 0.0), fmt."%,(-10f\{0.0}");
- test(String.format("%,(-10f", 12345.6), fmt."%,(-10f\{12345.6}");
- test(String.format("%+f", -12345.6), fmt."%+f\{-12345.6}");
- test(String.format("%+f", 0.0), fmt."%+f\{0.0}");
- test(String.format("%+f", 12345.6), fmt."%+f\{12345.6}");
- test(String.format("%+10f", -12345.6), fmt."%+10f\{-12345.6}");
- test(String.format("%+10f", 0.0), fmt."%+10f\{0.0}");
- test(String.format("%+10f", 12345.6), fmt."%+10f\{12345.6}");
- test(String.format("%+-10f", -12345.6), fmt."%+-10f\{-12345.6}");
- test(String.format("%+-10f", 0.0), fmt."%+-10f\{0.0}");
- test(String.format("%+-10f", 12345.6), fmt."%+-10f\{12345.6}");
- test(String.format("%,+f", -12345.6), fmt."%,+f\{-12345.6}");
- test(String.format("%,+f", 0.0), fmt."%,+f\{0.0}");
- test(String.format("%,+f", 12345.6), fmt."%,+f\{12345.6}");
- test(String.format("%,+10f", -12345.6), fmt."%,+10f\{-12345.6}");
- test(String.format("%,+10f", 0.0), fmt."%,+10f\{0.0}");
- test(String.format("%,+10f", 12345.6), fmt."%,+10f\{12345.6}");
- test(String.format("%,+-10f", -12345.6), fmt."%,+-10f\{-12345.6}");
- test(String.format("%,+-10f", 0.0), fmt."%,+-10f\{0.0}");
- test(String.format("%,+-10f", 12345.6), fmt."%,+-10f\{12345.6}");
- test(String.format("%(+f", -12345.6), fmt."%(+f\{-12345.6}");
- test(String.format("%(+f", 0.0), fmt."%(+f\{0.0}");
- test(String.format("%(+f", 12345.6), fmt."%(+f\{12345.6}");
- test(String.format("%(+10f", -12345.6), fmt."%(+10f\{-12345.6}");
- test(String.format("%(+10f", 0.0), fmt."%(+10f\{0.0}");
- test(String.format("%(+10f", 12345.6), fmt."%(+10f\{12345.6}");
- test(String.format("%(+-10f", -12345.6), fmt."%(+-10f\{-12345.6}");
- test(String.format("%(+-10f", 0.0), fmt."%(+-10f\{0.0}");
- test(String.format("%(+-10f", 12345.6), fmt."%(+-10f\{12345.6}");
- test(String.format("%,(+f", -12345.6), fmt."%,(+f\{-12345.6}");
- test(String.format("%,(+f", 0.0), fmt."%,(+f\{0.0}");
- test(String.format("%,(+f", 12345.6), fmt."%,(+f\{12345.6}");
- test(String.format("%,(+10f", -12345.6), fmt."%,(+10f\{-12345.6}");
- test(String.format("%,(+10f", 0.0), fmt."%,(+10f\{0.0}");
- test(String.format("%,(+10f", 12345.6), fmt."%,(+10f\{12345.6}");
- test(String.format("%,(+-10f", -12345.6), fmt."%,(+-10f\{-12345.6}");
- test(String.format("%,(+-10f", 0.0), fmt."%,(+-10f\{0.0}");
- test(String.format("%,(+-10f", 12345.6), fmt."%,(+-10f\{12345.6}");
-
- test(String.format("%e", -12345.6), fmt."%e\{-12345.6}");
- test(String.format("%e", 0.0), fmt."%e\{0.0}");
- test(String.format("%e", 12345.6), fmt."%e\{12345.6}");
- test(String.format("%10e", -12345.6), fmt."%10e\{-12345.6}");
- test(String.format("%10e", 0.0), fmt."%10e\{0.0}");
- test(String.format("%10e", 12345.6), fmt."%10e\{12345.6}");
- test(String.format("%-10e", -12345.6), fmt."%-10e\{-12345.6}");
- test(String.format("%-10e", 0.0), fmt."%-10e\{0.0}");
- test(String.format("%-10e", 12345.6), fmt."%-10e\{12345.6}");
- test(String.format("%E", -12345.6), fmt."%E\{-12345.6}");
- test(String.format("%E", 0.0), fmt."%E\{0.0}");
- test(String.format("%E", 12345.6), fmt."%E\{12345.6}");
- test(String.format("%10E", -12345.6), fmt."%10E\{-12345.6}");
- test(String.format("%10E", 0.0), fmt."%10E\{0.0}");
- test(String.format("%10E", 12345.6), fmt."%10E\{12345.6}");
- test(String.format("%-10E", -12345.6), fmt."%-10E\{-12345.6}");
- test(String.format("%-10E", 0.0), fmt."%-10E\{0.0}");
- test(String.format("%-10E", 12345.6), fmt."%-10E\{12345.6}");
-
- test(String.format("%g", -12345.6), fmt."%g\{-12345.6}");
- test(String.format("%g", 0.0), fmt."%g\{0.0}");
- test(String.format("%g", 12345.6), fmt."%g\{12345.6}");
- test(String.format("%10g", -12345.6), fmt."%10g\{-12345.6}");
- test(String.format("%10g", 0.0), fmt."%10g\{0.0}");
- test(String.format("%10g", 12345.6), fmt."%10g\{12345.6}");
- test(String.format("%-10g", -12345.6), fmt."%-10g\{-12345.6}");
- test(String.format("%-10g", 0.0), fmt."%-10g\{0.0}");
- test(String.format("%-10g", 12345.6), fmt."%-10g\{12345.6}");
- test(String.format("%G", -12345.6), fmt."%G\{-12345.6}");
- test(String.format("%G", 0.0), fmt."%G\{0.0}");
- test(String.format("%G", 12345.6), fmt."%G\{12345.6}");
- test(String.format("%10G", -12345.6), fmt."%10G\{-12345.6}");
- test(String.format("%10G", 0.0), fmt."%10G\{0.0}");
- test(String.format("%10G", 12345.6), fmt."%10G\{12345.6}");
- test(String.format("%-10G", -12345.6), fmt."%-10G\{-12345.6}");
- test(String.format("%-10G", 0.0), fmt."%-10G\{0.0}");
- test(String.format("%-10G", 12345.6), fmt."%-10G\{12345.6}");
- test(String.format("%,g", -12345.6), fmt."%,g\{-12345.6}");
- test(String.format("%,g", 0.0), fmt."%,g\{0.0}");
- test(String.format("%,g", 12345.6), fmt."%,g\{12345.6}");
- test(String.format("%,10g", -12345.6), fmt."%,10g\{-12345.6}");
- test(String.format("%,10g", 0.0), fmt."%,10g\{0.0}");
- test(String.format("%,10g", 12345.6), fmt."%,10g\{12345.6}");
- test(String.format("%,-10g", -12345.6), fmt."%,-10g\{-12345.6}");
- test(String.format("%,-10g", 0.0), fmt."%,-10g\{0.0}");
- test(String.format("%,-10g", 12345.6), fmt."%,-10g\{12345.6}");
- test(String.format("%,G", -12345.6), fmt."%,G\{-12345.6}");
- test(String.format("%,G", 0.0), fmt."%,G\{0.0}");
- test(String.format("%,G", 12345.6), fmt."%,G\{12345.6}");
- test(String.format("%,10G", -12345.6), fmt."%,10G\{-12345.6}");
- test(String.format("%,10G", 0.0), fmt."%,10G\{0.0}");
- test(String.format("%,10G", 12345.6), fmt."%,10G\{12345.6}");
- test(String.format("%,-10G", -12345.6), fmt."%,-10G\{-12345.6}");
- test(String.format("%,-10G", 0.0), fmt."%,-10G\{0.0}");
- test(String.format("%,-10G", 12345.6), fmt."%,-10G\{12345.6}");
-
- test(String.format("%g", -12345.6), fmt."%g\{-12345.6}");
- test(String.format("%g", 0.0), fmt."%g\{0.0}");
- test(String.format("%g", 12345.6), fmt."%g\{12345.6}");
- test(String.format("%10g", -12345.6), fmt."%10g\{-12345.6}");
- test(String.format("%10g", 0.0), fmt."%10g\{0.0}");
- test(String.format("%10g", 12345.6), fmt."%10g\{12345.6}");
- test(String.format("%-10g", -12345.6), fmt."%-10g\{-12345.6}");
- test(String.format("%-10g", 0.0), fmt."%-10g\{0.0}");
- test(String.format("%-10g", 12345.6), fmt."%-10g\{12345.6}");
- test(String.format("%G", -12345.6), fmt."%G\{-12345.6}");
- test(String.format("%G", 0.0), fmt."%G\{0.0}");
- test(String.format("%G", 12345.6), fmt."%G\{12345.6}");
- test(String.format("%10G", -12345.6), fmt."%10G\{-12345.6}");
- test(String.format("%10G", 0.0), fmt."%10G\{0.0}");
- test(String.format("%10G", 12345.6), fmt."%10G\{12345.6}");
- test(String.format("%-10G", -12345.6), fmt."%-10G\{-12345.6}");
- test(String.format("%-10G", 0.0), fmt."%-10G\{0.0}");
- test(String.format("%-10G", 12345.6), fmt."%-10G\{12345.6}");
- test(String.format("%,g", -12345.6), fmt."%,g\{-12345.6}");
- test(String.format("%,g", 0.0), fmt."%,g\{0.0}");
- test(String.format("%,g", 12345.6), fmt."%,g\{12345.6}");
- test(String.format("%,10g", -12345.6), fmt."%,10g\{-12345.6}");
- test(String.format("%,10g", 0.0), fmt."%,10g\{0.0}");
- test(String.format("%,10g", 12345.6), fmt."%,10g\{12345.6}");
- test(String.format("%,-10g", -12345.6), fmt."%,-10g\{-12345.6}");
- test(String.format("%,-10g", 0.0), fmt."%,-10g\{0.0}");
- test(String.format("%,-10g", 12345.6), fmt."%,-10g\{12345.6}");
- test(String.format("%,G", -12345.6), fmt."%,G\{-12345.6}");
- test(String.format("%,G", 0.0), fmt."%,G\{0.0}");
- test(String.format("%,G", 12345.6), fmt."%,G\{12345.6}");
- test(String.format("%,10G", -12345.6), fmt."%,10G\{-12345.6}");
- test(String.format("%,10G", 0.0), fmt."%,10G\{0.0}");
- test(String.format("%,10G", 12345.6), fmt."%,10G\{12345.6}");
- test(String.format("%,-10G", -12345.6), fmt."%,-10G\{-12345.6}");
- test(String.format("%,-10G", 0.0), fmt."%,-10G\{0.0}");
- test(String.format("%,-10G", 12345.6), fmt."%,-10G\{12345.6}");
- test(String.format("% g", -12345.6), fmt."% g\{-12345.6}");
- test(String.format("% g", 0.0), fmt."% g\{0.0}");
- test(String.format("% g", 12345.6), fmt."% g\{12345.6}");
- test(String.format("% 10g", -12345.6), fmt."% 10g\{-12345.6}");
- test(String.format("% 10g", 0.0), fmt."% 10g\{0.0}");
- test(String.format("% 10g", 12345.6), fmt."% 10g\{12345.6}");
- test(String.format("% -10g", -12345.6), fmt."% -10g\{-12345.6}");
- test(String.format("% -10g", 0.0), fmt."% -10g\{0.0}");
- test(String.format("% -10g", 12345.6), fmt."% -10g\{12345.6}");
- test(String.format("% G", -12345.6), fmt."% G\{-12345.6}");
- test(String.format("% G", 0.0), fmt."% G\{0.0}");
- test(String.format("% G", 12345.6), fmt."% G\{12345.6}");
- test(String.format("% 10G", -12345.6), fmt."% 10G\{-12345.6}");
- test(String.format("% 10G", 0.0), fmt."% 10G\{0.0}");
- test(String.format("% 10G", 12345.6), fmt."% 10G\{12345.6}");
- test(String.format("% -10G", -12345.6), fmt."% -10G\{-12345.6}");
- test(String.format("% -10G", 0.0), fmt."% -10G\{0.0}");
- test(String.format("% -10G", 12345.6), fmt."% -10G\{12345.6}");
- test(String.format("%, g", -12345.6), fmt."%, g\{-12345.6}");
- test(String.format("%, g", 0.0), fmt."%, g\{0.0}");
- test(String.format("%, g", 12345.6), fmt."%, g\{12345.6}");
- test(String.format("%, 10g", -12345.6), fmt."%, 10g\{-12345.6}");
- test(String.format("%, 10g", 0.0), fmt."%, 10g\{0.0}");
- test(String.format("%, 10g", 12345.6), fmt."%, 10g\{12345.6}");
- test(String.format("%, -10g", -12345.6), fmt."%, -10g\{-12345.6}");
- test(String.format("%, -10g", 0.0), fmt."%, -10g\{0.0}");
- test(String.format("%, -10g", 12345.6), fmt."%, -10g\{12345.6}");
- test(String.format("%, G", -12345.6), fmt."%, G\{-12345.6}");
- test(String.format("%, G", 0.0), fmt."%, G\{0.0}");
- test(String.format("%, G", 12345.6), fmt."%, G\{12345.6}");
- test(String.format("%, 10G", -12345.6), fmt."%, 10G\{-12345.6}");
- test(String.format("%, 10G", 0.0), fmt."%, 10G\{0.0}");
- test(String.format("%, 10G", 12345.6), fmt."%, 10G\{12345.6}");
- test(String.format("%, -10G", -12345.6), fmt."%, -10G\{-12345.6}");
- test(String.format("%, -10G", 0.0), fmt."%, -10G\{0.0}");
- test(String.format("%, -10G", 12345.6), fmt."%, -10G\{12345.6}");
-
- test(String.format("%g", -12345.6), fmt."%g\{-12345.6}");
- test(String.format("%g", 0.0), fmt."%g\{0.0}");
- test(String.format("%g", 12345.6), fmt."%g\{12345.6}");
- test(String.format("%10g", -12345.6), fmt."%10g\{-12345.6}");
- test(String.format("%10g", 0.0), fmt."%10g\{0.0}");
- test(String.format("%10g", 12345.6), fmt."%10g\{12345.6}");
- test(String.format("%-10g", -12345.6), fmt."%-10g\{-12345.6}");
- test(String.format("%-10g", 0.0), fmt."%-10g\{0.0}");
- test(String.format("%-10g", 12345.6), fmt."%-10g\{12345.6}");
- test(String.format("%G", -12345.6), fmt."%G\{-12345.6}");
- test(String.format("%G", 0.0), fmt."%G\{0.0}");
- test(String.format("%G", 12345.6), fmt."%G\{12345.6}");
- test(String.format("%10G", -12345.6), fmt."%10G\{-12345.6}");
- test(String.format("%10G", 0.0), fmt."%10G\{0.0}");
- test(String.format("%10G", 12345.6), fmt."%10G\{12345.6}");
- test(String.format("%-10G", -12345.6), fmt."%-10G\{-12345.6}");
- test(String.format("%-10G", 0.0), fmt."%-10G\{0.0}");
- test(String.format("%-10G", 12345.6), fmt."%-10G\{12345.6}");
- test(String.format("%,g", -12345.6), fmt."%,g\{-12345.6}");
- test(String.format("%,g", 0.0), fmt."%,g\{0.0}");
- test(String.format("%,g", 12345.6), fmt."%,g\{12345.6}");
- test(String.format("%,10g", -12345.6), fmt."%,10g\{-12345.6}");
- test(String.format("%,10g", 0.0), fmt."%,10g\{0.0}");
- test(String.format("%,10g", 12345.6), fmt."%,10g\{12345.6}");
- test(String.format("%,-10g", -12345.6), fmt."%,-10g\{-12345.6}");
- test(String.format("%,-10g", 0.0), fmt."%,-10g\{0.0}");
- test(String.format("%,-10g", 12345.6), fmt."%,-10g\{12345.6}");
- test(String.format("%,G", -12345.6), fmt."%,G\{-12345.6}");
- test(String.format("%,G", 0.0), fmt."%,G\{0.0}");
- test(String.format("%,G", 12345.6), fmt."%,G\{12345.6}");
- test(String.format("%,10G", -12345.6), fmt."%,10G\{-12345.6}");
- test(String.format("%,10G", 0.0), fmt."%,10G\{0.0}");
- test(String.format("%,10G", 12345.6), fmt."%,10G\{12345.6}");
- test(String.format("%,-10G", -12345.6), fmt."%,-10G\{-12345.6}");
- test(String.format("%,-10G", 0.0), fmt."%,-10G\{0.0}");
- test(String.format("%,-10G", 12345.6), fmt."%,-10G\{12345.6}");
- test(String.format("%+g", -12345.6), fmt."%+g\{-12345.6}");
- test(String.format("%+g", 0.0), fmt."%+g\{0.0}");
- test(String.format("%+g", 12345.6), fmt."%+g\{12345.6}");
- test(String.format("%+10g", -12345.6), fmt."%+10g\{-12345.6}");
- test(String.format("%+10g", 0.0), fmt."%+10g\{0.0}");
- test(String.format("%+10g", 12345.6), fmt."%+10g\{12345.6}");
- test(String.format("%+-10g", -12345.6), fmt."%+-10g\{-12345.6}");
- test(String.format("%+-10g", 0.0), fmt."%+-10g\{0.0}");
- test(String.format("%+-10g", 12345.6), fmt."%+-10g\{12345.6}");
- test(String.format("%+G", -12345.6), fmt."%+G\{-12345.6}");
- test(String.format("%+G", 0.0), fmt."%+G\{0.0}");
- test(String.format("%+G", 12345.6), fmt."%+G\{12345.6}");
- test(String.format("%+10G", -12345.6), fmt."%+10G\{-12345.6}");
- test(String.format("%+10G", 0.0), fmt."%+10G\{0.0}");
- test(String.format("%+10G", 12345.6), fmt."%+10G\{12345.6}");
- test(String.format("%+-10G", -12345.6), fmt."%+-10G\{-12345.6}");
- test(String.format("%+-10G", 0.0), fmt."%+-10G\{0.0}");
- test(String.format("%+-10G", 12345.6), fmt."%+-10G\{12345.6}");
- test(String.format("%,+g", -12345.6), fmt."%,+g\{-12345.6}");
- test(String.format("%,+g", 0.0), fmt."%,+g\{0.0}");
- test(String.format("%,+g", 12345.6), fmt."%,+g\{12345.6}");
- test(String.format("%,+10g", -12345.6), fmt."%,+10g\{-12345.6}");
- test(String.format("%,+10g", 0.0), fmt."%,+10g\{0.0}");
- test(String.format("%,+10g", 12345.6), fmt."%,+10g\{12345.6}");
- test(String.format("%,+-10g", -12345.6), fmt."%,+-10g\{-12345.6}");
- test(String.format("%,+-10g", 0.0), fmt."%,+-10g\{0.0}");
- test(String.format("%,+-10g", 12345.6), fmt."%,+-10g\{12345.6}");
- test(String.format("%,+G", -12345.6), fmt."%,+G\{-12345.6}");
- test(String.format("%,+G", 0.0), fmt."%,+G\{0.0}");
- test(String.format("%,+G", 12345.6), fmt."%,+G\{12345.6}");
- test(String.format("%,+10G", -12345.6), fmt."%,+10G\{-12345.6}");
- test(String.format("%,+10G", 0.0), fmt."%,+10G\{0.0}");
- test(String.format("%,+10G", 12345.6), fmt."%,+10G\{12345.6}");
- test(String.format("%,+-10G", -12345.6), fmt."%,+-10G\{-12345.6}");
- test(String.format("%,+-10G", 0.0), fmt."%,+-10G\{0.0}");
- test(String.format("%,+-10G", 12345.6), fmt."%,+-10G\{12345.6}");
-
- test(String.format("%g", -12345.6), fmt."%g\{-12345.6}");
- test(String.format("%g", 0.0), fmt."%g\{0.0}");
- test(String.format("%g", 12345.6), fmt."%g\{12345.6}");
- test(String.format("%10g", -12345.6), fmt."%10g\{-12345.6}");
- test(String.format("%10g", 0.0), fmt."%10g\{0.0}");
- test(String.format("%10g", 12345.6), fmt."%10g\{12345.6}");
- test(String.format("%-10g", -12345.6), fmt."%-10g\{-12345.6}");
- test(String.format("%-10g", 0.0), fmt."%-10g\{0.0}");
- test(String.format("%-10g", 12345.6), fmt."%-10g\{12345.6}");
- test(String.format("%G", -12345.6), fmt."%G\{-12345.6}");
- test(String.format("%G", 0.0), fmt."%G\{0.0}");
- test(String.format("%G", 12345.6), fmt."%G\{12345.6}");
- test(String.format("%10G", -12345.6), fmt."%10G\{-12345.6}");
- test(String.format("%10G", 0.0), fmt."%10G\{0.0}");
- test(String.format("%10G", 12345.6), fmt."%10G\{12345.6}");
- test(String.format("%-10G", -12345.6), fmt."%-10G\{-12345.6}");
- test(String.format("%-10G", 0.0), fmt."%-10G\{0.0}");
- test(String.format("%-10G", 12345.6), fmt."%-10G\{12345.6}");
- test(String.format("%,g", -12345.6), fmt."%,g\{-12345.6}");
- test(String.format("%,g", 0.0), fmt."%,g\{0.0}");
- test(String.format("%,g", 12345.6), fmt."%,g\{12345.6}");
- test(String.format("%,10g", -12345.6), fmt."%,10g\{-12345.6}");
- test(String.format("%,10g", 0.0), fmt."%,10g\{0.0}");
- test(String.format("%,10g", 12345.6), fmt."%,10g\{12345.6}");
- test(String.format("%,-10g", -12345.6), fmt."%,-10g\{-12345.6}");
- test(String.format("%,-10g", 0.0), fmt."%,-10g\{0.0}");
- test(String.format("%,-10g", 12345.6), fmt."%,-10g\{12345.6}");
- test(String.format("%,G", -12345.6), fmt."%,G\{-12345.6}");
- test(String.format("%,G", 0.0), fmt."%,G\{0.0}");
- test(String.format("%,G", 12345.6), fmt."%,G\{12345.6}");
- test(String.format("%,10G", -12345.6), fmt."%,10G\{-12345.6}");
- test(String.format("%,10G", 0.0), fmt."%,10G\{0.0}");
- test(String.format("%,10G", 12345.6), fmt."%,10G\{12345.6}");
- test(String.format("%,-10G", -12345.6), fmt."%,-10G\{-12345.6}");
- test(String.format("%,-10G", 0.0), fmt."%,-10G\{0.0}");
- test(String.format("%,-10G", 12345.6), fmt."%,-10G\{12345.6}");
- test(String.format("%(g", -12345.6), fmt."%(g\{-12345.6}");
- test(String.format("%(g", 0.0), fmt."%(g\{0.0}");
- test(String.format("%(g", 12345.6), fmt."%(g\{12345.6}");
- test(String.format("%(10g", -12345.6), fmt."%(10g\{-12345.6}");
- test(String.format("%(10g", 0.0), fmt."%(10g\{0.0}");
- test(String.format("%(10g", 12345.6), fmt."%(10g\{12345.6}");
- test(String.format("%(-10g", -12345.6), fmt."%(-10g\{-12345.6}");
- test(String.format("%(-10g", 0.0), fmt."%(-10g\{0.0}");
- test(String.format("%(-10g", 12345.6), fmt."%(-10g\{12345.6}");
- test(String.format("%(G", -12345.6), fmt."%(G\{-12345.6}");
- test(String.format("%(G", 0.0), fmt."%(G\{0.0}");
- test(String.format("%(G", 12345.6), fmt."%(G\{12345.6}");
- test(String.format("%(10G", -12345.6), fmt."%(10G\{-12345.6}");
- test(String.format("%(10G", 0.0), fmt."%(10G\{0.0}");
- test(String.format("%(10G", 12345.6), fmt."%(10G\{12345.6}");
- test(String.format("%(-10G", -12345.6), fmt."%(-10G\{-12345.6}");
- test(String.format("%(-10G", 0.0), fmt."%(-10G\{0.0}");
- test(String.format("%(-10G", 12345.6), fmt."%(-10G\{12345.6}");
- test(String.format("%,(g", -12345.6), fmt."%,(g\{-12345.6}");
- test(String.format("%,(g", 0.0), fmt."%,(g\{0.0}");
- test(String.format("%,(g", 12345.6), fmt."%,(g\{12345.6}");
- test(String.format("%,(10g", -12345.6), fmt."%,(10g\{-12345.6}");
- test(String.format("%,(10g", 0.0), fmt."%,(10g\{0.0}");
- test(String.format("%,(10g", 12345.6), fmt."%,(10g\{12345.6}");
- test(String.format("%,(-10g", -12345.6), fmt."%,(-10g\{-12345.6}");
- test(String.format("%,(-10g", 0.0), fmt."%,(-10g\{0.0}");
- test(String.format("%,(-10g", 12345.6), fmt."%,(-10g\{12345.6}");
- test(String.format("%,(G", -12345.6), fmt."%,(G\{-12345.6}");
- test(String.format("%,(G", 0.0), fmt."%,(G\{0.0}");
- test(String.format("%,(G", 12345.6), fmt."%,(G\{12345.6}");
- test(String.format("%,(10G", -12345.6), fmt."%,(10G\{-12345.6}");
- test(String.format("%,(10G", 0.0), fmt."%,(10G\{0.0}");
- test(String.format("%,(10G", 12345.6), fmt."%,(10G\{12345.6}");
- test(String.format("%,(-10G", -12345.6), fmt."%,(-10G\{-12345.6}");
- test(String.format("%,(-10G", 0.0), fmt."%,(-10G\{0.0}");
- test(String.format("%,(-10G", 12345.6), fmt."%,(-10G\{12345.6}");
- test(String.format("%+g", -12345.6), fmt."%+g\{-12345.6}");
- test(String.format("%+g", 0.0), fmt."%+g\{0.0}");
- test(String.format("%+g", 12345.6), fmt."%+g\{12345.6}");
- test(String.format("%+10g", -12345.6), fmt."%+10g\{-12345.6}");
- test(String.format("%+10g", 0.0), fmt."%+10g\{0.0}");
- test(String.format("%+10g", 12345.6), fmt."%+10g\{12345.6}");
- test(String.format("%+-10g", -12345.6), fmt."%+-10g\{-12345.6}");
- test(String.format("%+-10g", 0.0), fmt."%+-10g\{0.0}");
- test(String.format("%+-10g", 12345.6), fmt."%+-10g\{12345.6}");
- test(String.format("%+G", -12345.6), fmt."%+G\{-12345.6}");
- test(String.format("%+G", 0.0), fmt."%+G\{0.0}");
- test(String.format("%+G", 12345.6), fmt."%+G\{12345.6}");
- test(String.format("%+10G", -12345.6), fmt."%+10G\{-12345.6}");
- test(String.format("%+10G", 0.0), fmt."%+10G\{0.0}");
- test(String.format("%+10G", 12345.6), fmt."%+10G\{12345.6}");
- test(String.format("%+-10G", -12345.6), fmt."%+-10G\{-12345.6}");
- test(String.format("%+-10G", 0.0), fmt."%+-10G\{0.0}");
- test(String.format("%+-10G", 12345.6), fmt."%+-10G\{12345.6}");
- test(String.format("%,+g", -12345.6), fmt."%,+g\{-12345.6}");
- test(String.format("%,+g", 0.0), fmt."%,+g\{0.0}");
- test(String.format("%,+g", 12345.6), fmt."%,+g\{12345.6}");
- test(String.format("%,+10g", -12345.6), fmt."%,+10g\{-12345.6}");
- test(String.format("%,+10g", 0.0), fmt."%,+10g\{0.0}");
- test(String.format("%,+10g", 12345.6), fmt."%,+10g\{12345.6}");
- test(String.format("%,+-10g", -12345.6), fmt."%,+-10g\{-12345.6}");
- test(String.format("%,+-10g", 0.0), fmt."%,+-10g\{0.0}");
- test(String.format("%,+-10g", 12345.6), fmt."%,+-10g\{12345.6}");
- test(String.format("%,+G", -12345.6), fmt."%,+G\{-12345.6}");
- test(String.format("%,+G", 0.0), fmt."%,+G\{0.0}");
- test(String.format("%,+G", 12345.6), fmt."%,+G\{12345.6}");
- test(String.format("%,+10G", -12345.6), fmt."%,+10G\{-12345.6}");
- test(String.format("%,+10G", 0.0), fmt."%,+10G\{0.0}");
- test(String.format("%,+10G", 12345.6), fmt."%,+10G\{12345.6}");
- test(String.format("%,+-10G", -12345.6), fmt."%,+-10G\{-12345.6}");
- test(String.format("%,+-10G", 0.0), fmt."%,+-10G\{0.0}");
- test(String.format("%,+-10G", 12345.6), fmt."%,+-10G\{12345.6}");
- test(String.format("%(+g", -12345.6), fmt."%(+g\{-12345.6}");
- test(String.format("%(+g", 0.0), fmt."%(+g\{0.0}");
- test(String.format("%(+g", 12345.6), fmt."%(+g\{12345.6}");
- test(String.format("%(+10g", -12345.6), fmt."%(+10g\{-12345.6}");
- test(String.format("%(+10g", 0.0), fmt."%(+10g\{0.0}");
- test(String.format("%(+10g", 12345.6), fmt."%(+10g\{12345.6}");
- test(String.format("%(+-10g", -12345.6), fmt."%(+-10g\{-12345.6}");
- test(String.format("%(+-10g", 0.0), fmt."%(+-10g\{0.0}");
- test(String.format("%(+-10g", 12345.6), fmt."%(+-10g\{12345.6}");
- test(String.format("%(+G", -12345.6), fmt."%(+G\{-12345.6}");
- test(String.format("%(+G", 0.0), fmt."%(+G\{0.0}");
- test(String.format("%(+G", 12345.6), fmt."%(+G\{12345.6}");
- test(String.format("%(+10G", -12345.6), fmt."%(+10G\{-12345.6}");
- test(String.format("%(+10G", 0.0), fmt."%(+10G\{0.0}");
- test(String.format("%(+10G", 12345.6), fmt."%(+10G\{12345.6}");
- test(String.format("%(+-10G", -12345.6), fmt."%(+-10G\{-12345.6}");
- test(String.format("%(+-10G", 0.0), fmt."%(+-10G\{0.0}");
- test(String.format("%(+-10G", 12345.6), fmt."%(+-10G\{12345.6}");
- test(String.format("%,(+g", -12345.6), fmt."%,(+g\{-12345.6}");
- test(String.format("%,(+g", 0.0), fmt."%,(+g\{0.0}");
- test(String.format("%,(+g", 12345.6), fmt."%,(+g\{12345.6}");
- test(String.format("%,(+10g", -12345.6), fmt."%,(+10g\{-12345.6}");
- test(String.format("%,(+10g", 0.0), fmt."%,(+10g\{0.0}");
- test(String.format("%,(+10g", 12345.6), fmt."%,(+10g\{12345.6}");
- test(String.format("%,(+-10g", -12345.6), fmt."%,(+-10g\{-12345.6}");
- test(String.format("%,(+-10g", 0.0), fmt."%,(+-10g\{0.0}");
- test(String.format("%,(+-10g", 12345.6), fmt."%,(+-10g\{12345.6}");
- test(String.format("%,(+G", -12345.6), fmt."%,(+G\{-12345.6}");
- test(String.format("%,(+G", 0.0), fmt."%,(+G\{0.0}");
- test(String.format("%,(+G", 12345.6), fmt."%,(+G\{12345.6}");
- test(String.format("%,(+10G", -12345.6), fmt."%,(+10G\{-12345.6}");
- test(String.format("%,(+10G", 0.0), fmt."%,(+10G\{0.0}");
- test(String.format("%,(+10G", 12345.6), fmt."%,(+10G\{12345.6}");
- test(String.format("%,(+-10G", -12345.6), fmt."%,(+-10G\{-12345.6}");
- test(String.format("%,(+-10G", 0.0), fmt."%,(+-10G\{0.0}");
- test(String.format("%,(+-10G", 12345.6), fmt."%,(+-10G\{12345.6}");
-
- test(String.format("%a", -12345.6), fmt."%a\{-12345.6}");
- test(String.format("%a", 0.0), fmt."%a\{0.0}");
- test(String.format("%a", 12345.6), fmt."%a\{12345.6}");
- test(String.format("%10a", -12345.6), fmt."%10a\{-12345.6}");
- test(String.format("%10a", 0.0), fmt."%10a\{0.0}");
- test(String.format("%10a", 12345.6), fmt."%10a\{12345.6}");
- test(String.format("%-10a", -12345.6), fmt."%-10a\{-12345.6}");
- test(String.format("%-10a", 0.0), fmt."%-10a\{0.0}");
- test(String.format("%-10a", 12345.6), fmt."%-10a\{12345.6}");
- test(String.format("%A", -12345.6), fmt."%A\{-12345.6}");
- test(String.format("%A", 0.0), fmt."%A\{0.0}");
- test(String.format("%A", 12345.6), fmt."%A\{12345.6}");
- test(String.format("%10A", -12345.6), fmt."%10A\{-12345.6}");
- test(String.format("%10A", 0.0), fmt."%10A\{0.0}");
- test(String.format("%10A", 12345.6), fmt."%10A\{12345.6}");
- test(String.format("%-10A", -12345.6), fmt."%-10A\{-12345.6}");
- test(String.format("%-10A", 0.0), fmt."%-10A\{0.0}");
- test(String.format("%-10A", 12345.6), fmt."%-10A\{12345.6}");
-
- test("aaa%false", fmt."aaa%%%b\{false}");
- test("aaa" + System.lineSeparator() + "false", fmt."aaa%n%b\{false}");
-
- assertThrows(
- MissingFormatArgumentException.class,
- () -> fmt. "%10ba\{ false }",
- "Format specifier '%10b is not immediately followed by an embedded expression'");
-
- assertThrows(
- MissingFormatArgumentException.class,
- () ->fmt. "%ba\{ false }",
- "Format specifier '%b is not immediately followed by an embedded expression'");
-
- assertThrows(
- MissingFormatArgumentException.class,
- () ->fmt. "%b",
- "Format specifier '%b is not immediately followed by an embedded expression'");
- assertThrows(
- UnknownFormatConversionException.class,
- () ->fmt. "%0",
- "Conversion = '0'");
- }
-}
diff --git a/test/jdk/java/lang/template/StringTemplateTest.java b/test/jdk/java/lang/template/StringTemplateTest.java
deleted file mode 100644
index 53aca6d83ff..00000000000
--- a/test/jdk/java/lang/template/StringTemplateTest.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (c) 2023, 2024, 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
- * @bug 0000000
- * @summary Exercise runtime handing of templated strings.
- * @enablePreview true
- */
-
-import java.io.ByteArrayOutputStream;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.URI;
-import java.util.*;
-import java.util.function.Supplier;
-import javax.tools.FileObject;
-import javax.tools.ForwardingJavaFileManager;
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-import javax.tools.SimpleJavaFileObject;
-import static javax.tools.StandardLocation.CLASS_OUTPUT;
-import javax.tools.ToolProvider;
-
-public class StringTemplateTest {
- enum Category{GENERAL, CHARACTER, INTEGRAL, BIG_INT, FLOATING, BIG_FLOAT, DATE};
-
- static final String[] GENERAL = {"true", "false", "(Object)null", "STR", "BO", "BOOL", "(Boolean)null"};
- static final String[] CHARS = {"C", "CHAR", "(Character)null"};
- static final String[] INTS = {"L", "LONG", "I", "INT", "S", "SHORT", "BY", "BYTE", "Long.MAX_VALUE", "Long.MIN_VALUE", "(Long)null", "(Integer)null", "(Short)null", "(Byte)null"};
- static final String[] BIGINTS = {};
- static final String[] FLOATS = {"F", "FLOAT", "D", "DOUBLE", "Double.NEGATIVE_INFINITY", "Double.NaN", "Double.MAX_VALUE", "(Double)null", "(Float)null"};
- static final String[] BIGFLOATS = {};
- static final String[] DATES = {};
-
- final Random r = new Random(1);
-
- String randomValue(Category category) {
- return switch (category) {
- case GENERAL -> randomChoice(
- GENERAL,
- () -> randomValue(Category.CHARACTER),
- () -> randomValue(Category.INTEGRAL),
- () -> randomValue(Category.BIG_INT),
- () -> randomValue(Category.FLOATING),
- () -> randomValue(Category.BIG_FLOAT),
- () -> randomValue(Category.DATE),
- () -> "\"" + randomString(r.nextInt(10)) + "\"");
- case CHARACTER -> randomChoice(
- CHARS,
- () -> "\'" + randomString(1) + "\'");
- case INTEGRAL -> randomChoice(
- INTS,
- () -> "(byte)" + String.valueOf(r.nextInt(Byte.MIN_VALUE, Byte.MAX_VALUE)),
- () -> "(short)" + String.valueOf(r.nextInt(Short.MIN_VALUE, Short.MAX_VALUE)),
- () -> String.valueOf(r.nextInt()),
- () -> r.nextLong() + "l");
- case BIG_INT -> randomChoice(
- BIGINTS,
- () -> "new java.math.BigInteger(\"" + r.nextLong() + "\")");
- case FLOATING -> randomChoice(
- FLOATS,
- () -> String.valueOf(r.nextDouble()),
- () -> r.nextFloat() + "f");
- case BIG_FLOAT -> randomChoice(
- BIGFLOATS,
- () -> "new java.math.BigDecimal(" + r.nextDouble() + ")");
- case DATE -> randomChoice(
- DATES,
- () -> "new java.util.Date(" + r.nextLong() + "l)",
- () -> r.nextLong() + "l");
- };
- }
-
- String randomChoice(Supplier... suppl) {
- return suppl[r.nextInt(suppl.length)].get();
- }
-
- String randomChoice(String... values) {
- return values[r.nextInt(values.length)];
- }
-
- String randomChoice(String[] values, Supplier... suppl) {
- int i = r.nextInt(values.length + suppl.length);
- return i < values.length ? values[i] : suppl[i - values.length].get();
- }
-
- String randomString(int length) {
- var sb = new StringBuilder(length << 2);
- while (length-- > 0) {
- char ch = (char)r.nextInt(9, 128);
- var s = switch (ch) {
- case '\t' -> "\\t";
- case '\'' -> "\\\'";
- case '"' -> "\\\"";
- case '\r' -> "\\r";
- case '\\' -> "\\\\";
- case '\n' -> "\\n";
- case '\f' -> "\\f";
- case '\b' -> "\\b";
- default -> ch + "";
- };
- sb.append(s);
- }
- return sb.toString();
- }
-
- String randomFormat(Category category) {
- char c;
- return "%" + switch (category) {
- case GENERAL -> randomWidth("-") + randomPrecision() + randomChar("bBhHsS");
- case CHARACTER -> randomWidth("-") + randomChar("cC");
- case INTEGRAL -> switch (c = randomChar("doxX")) {
- case 'd' -> randomFlags("+ ,(");
- default -> randomFlags("");
- } + randomWidth("-0") + c;
- case BIG_INT -> switch (c = randomChar("doxX")) {
- case 'd' -> randomFlags("+ ,(");
- default -> randomFlags("+ (");
- } + randomWidth("-0") + c;
- case FLOATING -> switch (c = randomChar("eEfaAgG")) {
- case 'a', 'A' -> randomFlags("+ ") + randomWidth("-0");
- case 'e', 'E' -> randomFlags("+ (") + randomWidth("-0") + randomPrecision();
- default -> randomFlags("+ ,(") + randomWidth("-0") + randomPrecision();
- } + c;
- case BIG_FLOAT -> switch (c = randomChar("eEfgG")) {
- case 'e', 'E' -> randomFlags("+ (") + randomWidth("-0") + randomPrecision();
- default -> randomFlags("+ ,(") + randomWidth("-0") + randomPrecision();
- } + c;
- case DATE -> randomWidth("-") + randomChar("tT") + randomChar("BbhAaCYyjmdeRTrDFc");
- };
- }
-
- String randomFlags(String flags) {
- var sb = new StringBuilder(flags.length());
- for (var f : flags.toCharArray()) {
- if (r.nextBoolean() && (f != ' ' || sb.length() == 0 || sb.charAt(sb.length() - 1) != '+')) sb.append(f);
- }
- return sb.toString();
- }
-
- char randomChar(String chars) {
- return chars.charAt(r.nextInt(chars.length()));
- }
-
- String randomWidth(String flags) {
- var f = r.nextInt(flags.length() + 1);
- return r.nextBoolean() ? (r.nextBoolean() ? flags.charAt(r.nextInt(flags.length())) : "") + String.valueOf(r.nextInt(10) + 1) : "";
- }
-
- String randomPrecision() {
- return r.nextBoolean() ? '.' + String.valueOf(r.nextInt(10) + 1) : "";
- }
-
- public Class> compile() throws Exception {
- var classes = new HashMap();
- var fileManager = new ForwardingJavaFileManager(ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null)) {
- @Override
- public ClassLoader getClassLoader(JavaFileManager.Location location) {
- return new ClassLoader() {
- @Override
- public Class> loadClass(String name) throws ClassNotFoundException {
- try {
- return super.loadClass(name);
- } catch (ClassNotFoundException e) {
- byte[] classData = classes.get(name);
- return defineClass(name, classData, 0, classData.length);
- }
- }
- };
- }
- @Override
- public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String name, JavaFileObject.Kind kind, FileObject originatingSource) throws UnsupportedOperationException {
- return new SimpleJavaFileObject(URI.create(name + ".class"), JavaFileObject.Kind.CLASS) {
- @Override
- public OutputStream openOutputStream() {
- return new FilterOutputStream(new ByteArrayOutputStream()) {
- @Override
- public void close() throws IOException {
- classes.put(name, ((ByteArrayOutputStream)out).toByteArray());
- }
- };
- }
- };
- }
- };
- var source = genSource();
-// System.out.println(source);
- if (ToolProvider.getSystemJavaCompiler().getTask(null, fileManager, null,
- List.of("--enable-preview", "-source", String.valueOf(Runtime.version().feature())), null,
- List.of(SimpleJavaFileObject.forSource(URI.create("StringTemplateTest$.java"), source))
- ).call()) {
- return fileManager.getClassLoader(CLASS_OUTPUT).loadClass("StringTemplateTest$");
- } else {
- throw new AssertionError("compilation failed");
- }
- }
-
- String genFragments(Category c) {
- var fragments = new LinkedList();
- for (int i = 0; i < 1500; i++) {
- var format = randomFormat(c);
- var value = randomValue(c);
- var qValue = value.replace("\\", "\\\\").replace("\"", "\\\"");
- fragments.add(STR."test(FMT.\"\{format}\\{\{value}}\", \"\{format}\", \"\{qValue}\", \{value}, log);");
- }
- return String.join("\n ", fragments);
- }
-
- String genSource() {
- return STR."""
- import java.util.FormatProcessor;
- import java.util.Locale;
-
- public class StringTemplateTest$ {
- static final FormatProcessor FMT = FormatProcessor.create(Locale.US);
- static String STR = "this is static String";
- static char C = 'c';
- static Character CHAR = 'C';
- static long L = -12345678910l;
- static Long LONG = 9876543210l;
- static int I = 42;
- static Integer INT = -49;
- static boolean BO = true;
- static Boolean BOOL = false;
- static short S = 13;
- static Short SHORT = -17;
- static byte BY = -3;
- static Byte BYTE = 12;
- static float F = 4.789f;
- static Float FLOAT = -0.000006f;
- static double D = 6545745.6734654563;
- static Double DOUBLE = -4323.7645676574;
-
- public static void run(java.util.List log) {
- runGeneral(log);
- runCharacter(log);
- runIntegral(log);
- runBigInt(log);
- runFloating(log);
- runBigFloat(log);
- runDate(log);
- }
- public static void runGeneral(java.util.List log) {
- \{genFragments(Category.GENERAL)}
- }
- public static void runCharacter(java.util.List log) {
- \{genFragments(Category.CHARACTER)}
- }
- public static void runIntegral(java.util.List log) {
- \{genFragments(Category.INTEGRAL)}
- }
- public static void runBigInt(java.util.List log) {
- \{genFragments(Category.BIG_INT)}
- }
- public static void runFloating(java.util.List log) {
- \{genFragments(Category.FLOATING)}
- }
- public static void runBigFloat(java.util.List log) {
- \{genFragments(Category.BIG_FLOAT)}
- }
- public static void runDate(java.util.List log) {
- \{genFragments(Category.DATE)}
- }
- static void test(String fmt, String format, String expression, Object value, java.util.List log) {
- var formatted = String.format(java.util.Locale.US, format, value);
- if (!fmt.equals(formatted)) {
- log.add(" format: '%s' expression: '%s' value: '%s' expected: '%s' found: '%s'".formatted(format, expression, value, formatted, fmt));
- }
- }
- }
- """;
- }
-
- public static void main(String... args) throws Exception {
- var log = new LinkedList();
- new StringTemplateTest().compile().getMethod("run", List.class).invoke(null, log);
- if (!log.isEmpty()) {
- log.forEach(System.out::println);
- throw new AssertionError(STR."failed \{log.size()} tests");
- }
- }
-}
diff --git a/test/jdk/java/lang/template/T8313809.java b/test/jdk/java/lang/template/T8313809.java
deleted file mode 100644
index b673b2b9c44..00000000000
--- a/test/jdk/java/lang/template/T8313809.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2023, 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
- * @bug 8313809
- * @summary String template fails with java.lang.StringIndexOutOfBoundsException if last fragment is UTF16
-.
- * @enablePreview true
- */
-
-import static java.util.FormatProcessor.FMT;
-
-public class T8313809 {
- public static void main(final String[] args) throws Exception {
- double sum = 12.34;
- final String message = FMT."The sum is : %f\{sum} €"; // this fails
- if (!message.equals("The sum is : 12.340000 €")) {
- throw new RuntimeException("Incorrect result");
- }
- }
-}
-
diff --git a/test/langtools/jdk/jshell/CompletenessTest.java b/test/langtools/jdk/jshell/CompletenessTest.java
index 09fcbfbdd39..06cbc6bd41f 100644
--- a/test/langtools/jdk/jshell/CompletenessTest.java
+++ b/test/langtools/jdk/jshell/CompletenessTest.java
@@ -89,8 +89,7 @@ public class CompletenessTest extends KullaTesting {
"record.any",
"record()",
"record(1)",
- "record.length()",
- "\"\\{0}\""
+ "record.length()"
};
static final String[] complete_with_semi = new String[] {
@@ -235,10 +234,7 @@ public class CompletenessTest extends KullaTesting {
static final String[] unknown = new String[] {
"new ;",
"\"",
- "\"\\",
- "\"\\{",
- "\"\\{0",
- "\"\\{0}",
+ "\"\\"
};
static final Map statusToCases = new HashMap<>();
@@ -384,9 +380,6 @@ public class CompletenessTest extends KullaTesting {
assertStatus("\"\"\"\ntext\\\"\"\"\\\"\"\"", DEFINITELY_INCOMPLETE, null);
assertStatus("\"\"\"\ntext\\\"\"\"\\\"\"\"\"\"\"", COMPLETE, "\"\"\"\ntext\\\"\"\"\\\"\"\"\"\"\"");
assertStatus("\"\"\"\n\\", DEFINITELY_INCOMPLETE, null);
- assertStatus("\"\"\"\n\\{", DEFINITELY_INCOMPLETE, null);
- assertStatus("\"\"\"\n\\{0", DEFINITELY_INCOMPLETE, null);
- assertStatus("\"\"\"\n\\{0}", DEFINITELY_INCOMPLETE, null);
}
public void testMiscSource() {
diff --git a/test/langtools/tools/javac/diags/examples/StringTemplate.java b/test/langtools/tools/javac/diags/examples/StringTemplate.java
deleted file mode 100644
index e35cbab11e4..00000000000
--- a/test/langtools/tools/javac/diags/examples/StringTemplate.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2023, 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.misc.feature.string.templates
- // key: compiler.warn.preview.feature.use.plural
- // options: --enable-preview -source ${jdk.version} -Xlint:preview
-
-class StringTemplate {
- String m() {
- int x = 10, y = 20;
- return STR."\{x} + \{y} = \{x + y}";
- }
-}
diff --git a/test/langtools/tools/javac/diags/examples/StringTemplateNoProcessor.java b/test/langtools/tools/javac/diags/examples/StringTemplateNoProcessor.java
deleted file mode 100644
index f909ec726d2..00000000000
--- a/test/langtools/tools/javac/diags/examples/StringTemplateNoProcessor.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2023, 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.err.processor.missing.from.string.template.expression
- // key: compiler.misc.feature.string.templates
- // key: compiler.warn.preview.feature.use.plural
- // options: --enable-preview -source ${jdk.version} -Xlint:preview
-
-class StringTemplateNoProcessor {
- String m() {
- int x = 10, y = 20;
- return "\{x} + \{y} = \{x + y}";
- }
-}
diff --git a/test/langtools/tools/javac/diags/examples/StringTemplateNotProcessor.java b/test/langtools/tools/javac/diags/examples/StringTemplateNotProcessor.java
deleted file mode 100644
index cd71f7df7e1..00000000000
--- a/test/langtools/tools/javac/diags/examples/StringTemplateNotProcessor.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2023, 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.note.preview.filename
- // key: compiler.err.cant.resolve.location.args
- // key: compiler.misc.location
- // key: compiler.note.preview.recompile
- // key: compiler.err.not.a.processor.type
- // options: --enable-preview -source ${jdk.version}
-
-import java.lang.*;
-
-class StringTemplateNotProcessor {
- String m() {
- String processor = "";
- int x = 10, y = 20;
- return processor."\{x} + \{y} = \{x + y}";
- }
-}
diff --git a/test/langtools/tools/javac/diags/examples/StringTemplateRawProcessor.java b/test/langtools/tools/javac/diags/examples/StringTemplateRawProcessor.java
deleted file mode 100644
index 9ab344fb021..00000000000
--- a/test/langtools/tools/javac/diags/examples/StringTemplateRawProcessor.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2023, 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.note.preview.filename
- // key: compiler.note.preview.recompile
- // key: compiler.misc.unexpected.ret.val
- // key: compiler.err.prob.found.req
- // options: --enable-preview -source ${jdk.version}
-
-import java.lang.*;
-import java.lang.StringTemplate.Processor;
-
-class StringTemplateRawProcessor {
- void m() {
- Processor processor = ts -> ts.interpolate();
- try {
- int x = 10, y = 20;
- return processor."\{x} + \{y} = \{x + y}";
- } catch (Throwable x) {
- throw new RuntimeException(x);
- }
- }
-}
-
diff --git a/test/langtools/tools/javac/diags/examples/StringTemplateUnclosedString.java b/test/langtools/tools/javac/diags/examples/StringTemplateUnclosedString.java
deleted file mode 100644
index c96ccf96ee3..00000000000
--- a/test/langtools/tools/javac/diags/examples/StringTemplateUnclosedString.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2023, 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.note.preview.filename
- // key: compiler.note.preview.recompile
- // key: compiler.err.unclosed.str.lit
- // key: compiler.err.string.template.is.not.well.formed
- // options: --enable-preview -source ${jdk.version}
-
-import java.lang.*;
-
-class StringTemplateUnclosedString {
- String m() {
- int x = 10;
- return STR."\{x";
- }
-}
diff --git a/test/langtools/tools/javac/diags/examples/StringTemplateUnclosedTextBlock.java b/test/langtools/tools/javac/diags/examples/StringTemplateUnclosedTextBlock.java
deleted file mode 100644
index 87460aba029..00000000000
--- a/test/langtools/tools/javac/diags/examples/StringTemplateUnclosedTextBlock.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2023, 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.note.preview.filename
- // key: compiler.note.preview.recompile
- // key: compiler.err.unclosed.text.block
- // key: compiler.err.text.block.template.is.not.well.formed
- // key: compiler.err.premature.eof
- // options: --enable-preview -source ${jdk.version}
-
-import java.lang.*;
-
-class StringTemplateUnclosedTextBlock {
- String m() {
- int x = 10;
- return STR."""
- aaa
- \{x
- """
- ;
- }
-}
diff --git a/test/langtools/tools/javac/parser/JavacParserTest.java b/test/langtools/tools/javac/parser/JavacParserTest.java
index f9ccb39c05e..93b2b51a8fa 100644
--- a/test/langtools/tools/javac/parser/JavacParserTest.java
+++ b/test/langtools/tools/javac/parser/JavacParserTest.java
@@ -1917,52 +1917,6 @@ public class JavacParserTest extends TestCase {
}.scan(cut, null);
}
- @Test
- void testStringTemplate1() throws IOException {
- String code = """
- package test;
- public class Test {
- Test(int a) {
- String s = "prefix \\{a} suffix";
- }
- }
- """;
-
- JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null,
- null, null, Arrays.asList(new MyFileObject(code)));
- CompilationUnitTree cut = ct.parse().iterator().next();
- ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
- MethodTree constr = (MethodTree) clazz.getMembers().get(0);
- VariableTree decl = (VariableTree) constr.getBody().getStatements().get(0);
- SourcePositions sp = Trees.instance(ct).getSourcePositions();
- int initStart = (int) sp.getStartPosition(cut, decl.getInitializer());
- int initEnd = (int) sp.getEndPosition(cut, decl.getInitializer());
- assertEquals("correct templated String span expected", code.substring(initStart, initEnd), "\"prefix \\{a} suffix\"");
- }
-
- @Test
- void testStringTemplate2() throws IOException {
- String code = """
- package test;
- public class Test {
- Test(int a) {
- String s = STR."prefix \\{a} suffix";
- }
- }
- """;
-
- JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null,
- null, null, Arrays.asList(new MyFileObject(code)));
- CompilationUnitTree cut = ct.parse().iterator().next();
- ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
- MethodTree constr = (MethodTree) clazz.getMembers().get(0);
- VariableTree decl = (VariableTree) constr.getBody().getStatements().get(0);
- SourcePositions sp = Trees.instance(ct).getSourcePositions();
- int initStart = (int) sp.getStartPosition(cut, decl.getInitializer());
- int initEnd = (int) sp.getEndPosition(cut, decl.getInitializer());
- assertEquals("correct templated String span expected", code.substring(initStart, initEnd), "STR.\"prefix \\{a} suffix\"");
- }
-
@Test //JDK-8293897
void testImplicitFinalInTryWithResources() throws IOException {
String code = """
@@ -2044,63 +1998,6 @@ public class JavacParserTest extends TestCase {
}.scan(cut, null);
}
- @Test
- void testIncompleteStringTemplate() throws IOException {
- String template = "\"\\{o.toString()}\"";
- String prefix = """
- package t;
- class Test {
- void test(Object o) {
- String s = STR.""";
-
- Worker verifyParseable = task -> {
- try {
- task.parse().iterator().next();
- return null;
- } catch (IOException ex) {
- throw new AssertionError(ex);
- }
- };
- JavacTaskPool pool = new JavacTaskPool(1);
- DiagnosticListener dl = d -> {};
- List options = List.of("--enable-preview",
- "-source", System.getProperty("java.specification.version"));
- for (int i = 0; i < template.length(); i++) {
- pool.getTask(null, fm, dl, options,
- null, Arrays.asList(new MyFileObject(prefix + template.substring(0, i))),
- verifyParseable
- );
- }
- for (int i = 0; i < template.length() - 1; i++) {
- pool.getTask(null, fm, dl, options,
- null, Arrays.asList(new MyFileObject(prefix + template.substring(0, i) + "\"")),
- verifyParseable);
- }
- String incomplete = prefix + "\"\\{o.";
- pool.getTask(null, fm, dl, options,
- null, Arrays.asList(new MyFileObject(incomplete)), task -> {
- try {
- CompilationUnitTree cut = task.parse().iterator().next();
- String result = cut.toString().replaceAll("\\R", "\n");
- System.out.println("RESULT\n" + result);
- assertEquals("incorrect AST",
- result,
- """
- package t;
- \n\
- class Test {
- \n\
- void test(Object o) {
- String s = STR.;
- }
- }""");
- return null;
- } catch (IOException ex) {
- throw new AssertionError(ex);
- }
- });
- }
-
@Test //JDK-8295401
void testModuleInfoProvidesRecovery() throws IOException {
String code = """
diff --git a/test/langtools/tools/javac/template/Basic.java b/test/langtools/tools/javac/template/Basic.java
deleted file mode 100644
index d6d36de18ca..00000000000
--- a/test/langtools/tools/javac/template/Basic.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (c) 2023, 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
- * @bug 0000000
- * @summary Exercise javac handing of templated strings.
- * @library /tools/lib
- * @modules jdk.compiler/com.sun.tools.javac.api
- * jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JavacTask
- * @run main Basic
- */
-
-
-import toolbox.JavacTask;
-import toolbox.JavaTask;
-import toolbox.Task;
-import toolbox.ToolBox;
-
-public class Basic {
- private static ToolBox TOOLBOX = new ToolBox();
- private static final String JAVA_VERSION = System.getProperty("java.specification.version");
-
- public static void main(String... arg) {
- primitivesTest();
- missingPartsTest();
- expressionsTest();
- invalidExpressionsTest();
- processorTest();
- }
-
- /*
- * Primitive types test.
- */
- static void primitivesTest() {
- for (String type : new String[] {
- "byte",
- "short",
- "int",
- "long",
- "float",
- "double"
- }) {
- compPass(type + " x = 10; " + type + " y = 20; StringTemplate result = RAW.\"\\{x} + \\{y} = \\{x + y}\";");
- }
- }
-
- /*
- * Missing parts test.
- */
- static void missingPartsTest() {
- compFail("""
- int x = 10;
- StringTemplate result = RAW."\\{x";
- """);
- compFail("""
- int x = 10;
- StringTemplate result = RAW."\\{{x}";
- """);
- compFail("""
- int x = 10;
- StringTemplate result = RAW."\\{x + }";
- """);
- compFail("""
- int x = 10;
- StringTemplate result = RAW."\\{ * x }";
- """);
- compFail("""
- int x = 10;
- StringTemplate result = RAW."\\{ (x + x }";
- """);
- }
-
- /*
- * Expressions test.
- */
- static void expressionsTest() {
- compPass("""
- int x = 10;
- int[] y = new int[] { 10, 20, 30 };
- StringTemplate result1 = RAW."\\{x + 1}";
- StringTemplate result2 = RAW."\\{x + x}";
- StringTemplate result3 = RAW."\\{x - x}";
- StringTemplate result4 = RAW."\\{x * x}";
- StringTemplate result5 = RAW."\\{x / x}";
- StringTemplate result6 = RAW."\\{x % x}";
- StringTemplate result7 = RAW."\\{x + (x + x)}";
- StringTemplate result8 = RAW."\\{y[x - 9]}";
- StringTemplate result9 = RAW."\\{System.out}";
- StringTemplate result10 = RAW.\"""
- \\{ "a string" }
- \""";
- """);
- compPass("""
- StringTemplate result = RAW.\"""
- \\{
- new Collection() {
- @Override public int size() { return 0; }
- @Override public boolean isEmpty() { return false; }
- @Override public boolean contains(Object o) { return false; }
- @Override public Iterator iterator() { return null; }
- @Override public Object[] toArray() { return new Object[0]; }
- @Override public T[] toArray(T[] a) { return null; }
- @Override public boolean add(String s) { return false; }
- @Override public boolean remove(Object o) { return false; }
- @Override public boolean containsAll(Collection> c) { return false; }
- @Override public boolean addAll(Collection extends String> c) { return false; }
- @Override public boolean removeAll(Collection> c) { return false; }
- @Override public boolean retainAll(Collection> c) { return false; }
- @Override public void clear() { }
- }
- }
- \""";
- """);
- }
-
- /*
- * Invalid expressions test.
- */
- static void invalidExpressionsTest() {
- compFail("""
- int x = 10;
- StringTemplate result = RAW."\\{ (x == x }";
- """);
- compFail("""
- int x = 10;
- StringTemplate result = RAW."\\{ true ? : x - 1 }";
- """);
- compFail("""
- String result = RAW."\\{ 'a }";
- """);
- compFail("""
- int x = 10;
- StringTemplate result = RAW."\\{ Math.min(, x - 1) }";
- """);
- compFail("""
- int x = 10;
- StringTemplate result = RAW."\\{ \\tx }";
- """);
- }
-
- /*
- * Processor test.
- */
- static void processorTest() {
- compPass("""
- int x = 10, y = 20;
- String string = STR."\\{x} + \\{y} = \\{x + y}";
- """);
- compFail("""
- int x = 10, y = 20;
- String processor = "abc";
- String string = processor."\\{x} + \\{y} = \\{x + y}";
- """);
- compFail("""
- int x = 10, y = 20;
- long processor = 100;
- String string = processor."\\{x} + \\{y} = \\{x + y}";
- """);
- }
-
- /*
- * Test source for successful compile.
- */
- static void compPass(String code) {
- String source = """
- import java.lang.*;
- import java.util.*;
- import static java.lang.StringTemplate.RAW;
- public class TEST {
- public static void main(String... arg) {
- """ +
- code.indent(8) +
- """
- }
- }
- """;
- String output = new JavacTask(TOOLBOX)
- .sources(source)
- .classpath(".")
- .options("-encoding", "utf8", "--enable-preview", "-source", JAVA_VERSION)
- .run()
- .writeAll()
- .getOutput(Task.OutputKind.DIRECT);
-
- if (output.contains("compiler.err")) {
- throw new RuntimeException("Error detected");
- }
- }
-
- /*
- * Test source for unsuccessful compile and specific error.
- */
- static void compFail(String code) {
- String source = """
- import java.lang.*;
- import java.util.*;
- import static java.lang.StringTemplate.RAW;
- public class TEST {
- public static void main(String... arg) {
- """ +
- code.indent(8) +
- """
- }
- }
- """;
- String errors = new JavacTask(TOOLBOX)
- .sources(source)
- .classpath(".")
- .options("-XDrawDiagnostics", "-encoding", "utf8", "--enable-preview", "-source", JAVA_VERSION)
- .run(Task.Expect.FAIL)
- .writeAll()
- .getOutput(Task.OutputKind.DIRECT);
-
- if (!errors.contains("compiler.err")) {
- throw new RuntimeException("No error detected");
- }
- }
-}
diff --git a/test/langtools/tools/javac/template/T8312814.java b/test/langtools/tools/javac/template/T8312814.java
deleted file mode 100644
index 15207828a7d..00000000000
--- a/test/langtools/tools/javac/template/T8312814.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2023, 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 T8312814
- * @summary Verify proper behavior of TransType w.r.t. templated Strings
- * @enablePreview
- * @compile T8312814.java
- */
-
-
-import java.util.List;
-
-public class T8312814 {
- void x(List extends StringTemplate.Processor> list) {
- list.get(0)."";
- }
-}
-
diff --git a/test/langtools/tools/javac/template/TreeScannerTest.java b/test/langtools/tools/javac/template/TreeScannerTest.java
deleted file mode 100644
index ffd7112ab47..00000000000
--- a/test/langtools/tools/javac/template/TreeScannerTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2023, 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 Verify proper behavior of TreeScanner w.r.t. templated Strings
- * @modules jdk.compiler
- */
-
-import java.io.*;
-import java.util.*;
-import javax.tools.*;
-import com.sun.source.tree.*;
-import com.sun.source.util.*;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-public class TreeScannerTest {
- private static final String JAVA_VERSION = System.getProperty("java.specification.version");
-
- public static void main(String... args) throws Exception {
- JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
- String code = """
- public class Test {
- private void test(int a) {
- String s1 = TEST."p\\{a}s";
- String s2 = "p\\{a}s";
- }
- }
- """;
- JavacTask task = (JavacTask) compiler.getTask(null, null, null,
- List.of("--enable-preview", "-source", JAVA_VERSION), null, List.of(new TestJFO(code)));
- StringBuilder output = new StringBuilder();
- TreeScanner checker = new TreeScanner() {
- private boolean log;
-
- @Override
- public Void visitStringTemplate(StringTemplateTree node, Void p) {
- boolean prevLog = log;
- try {
- log = true;
- return super.visitStringTemplate(node, p);
- } finally {
- log = prevLog;
- }
- }
-
- @Override
- public Void scan(Tree tree, Void p) {
- if (log) {
- output.append("(");
- output.append(tree != null ? tree.getKind() : "null");
- try {
- return super.scan(tree, p);
- } finally {
- output.append(")");
- }
- } else {
- return super.scan(tree, p);
- }
- }
-
- };
-
- checker.scan(task.parse(), null);
-
- String expected = "(IDENTIFIER)(IDENTIFIER)(null)(IDENTIFIER)";
- if (!expected.equals(output.toString())) {
- throw new AssertionError("expected output not found, found: " + output);
- }
- }
-
- private static final class TestJFO extends SimpleJavaFileObject {
- private final String code;
-
- public TestJFO(String code) throws URISyntaxException, IOException {
- super(new URI("mem://Test.java"), Kind.SOURCE);
- this.code = code;
- }
-
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
- return code;
- }
-
- }
-}
diff --git a/test/langtools/tools/javac/tree/TreeKindTest.java b/test/langtools/tools/javac/tree/TreeKindTest.java
index 626288af168..15b4ae37bbe 100644
--- a/test/langtools/tools/javac/tree/TreeKindTest.java
+++ b/test/langtools/tools/javac/tree/TreeKindTest.java
@@ -123,10 +123,6 @@ public class TreeKindTest {
ok = ok & verify(k, i, i == OpensTree.class);
break;
- case TEMPLATE:
- ok = ok & verify(k, i, i == StringTemplateTree.class);
- break;
-
case OTHER:
ok = ok & verify(k, i, i == null);
break;
diff --git a/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java b/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java
index 63814220c03..aa30682e1bc 100644
--- a/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java
+++ b/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java
@@ -92,7 +92,6 @@ public class ListModuleDeps {
public Object[][] jdkModules() {
return new Object[][]{
{"jdk.compiler", new String[]{
- "java.base/jdk.internal.javac",
"java.base/jdk.internal.jmod",
"java.base/jdk.internal.misc",
"java.base/jdk.internal.module",
diff --git a/test/micro/org/openjdk/bench/java/lang/StringTemplateFMT.java b/test/micro/org/openjdk/bench/java/lang/StringTemplateFMT.java
deleted file mode 100644
index 60a3024c7f8..00000000000
--- a/test/micro/org/openjdk/bench/java/lang/StringTemplateFMT.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2023, 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.
- */
-package org.openjdk.bench.java.lang;
-
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.BenchmarkMode;
-import org.openjdk.jmh.annotations.Fork;
-import org.openjdk.jmh.annotations.Measurement;
-import org.openjdk.jmh.annotations.Mode;
-import org.openjdk.jmh.annotations.OutputTimeUnit;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.Warmup;
-
-import java.util.concurrent.TimeUnit;
-
-import static java.util.FormatProcessor.FMT;
-
-/*
- * This benchmark measures StringTemplate.FMT FormatProcessor performance;
- * exactly mirroring {@link org.openjdk.bench.java.lang.StringFormat} benchmark
- */
-@BenchmarkMode(Mode.AverageTime)
-@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@State(Scope.Thread)
-@Warmup(iterations = 5, time = 1)
-@Measurement(iterations = 5, time = 1)
-@Fork(value = 3, jvmArgsAppend = "--enable-preview")
-public class StringTemplateFMT {
-
- public String s = "str";
- public int i = 17;
-
- @Benchmark
- public String stringFormat() {
- return FMT."%s\{s}";
- }
-
- @Benchmark
- public String stringIntFormat() {
- return FMT."%s\{s} %d\{i}";
- }
-
- @Benchmark
- public String widthStringFormat() {
- return FMT."%3s\{s}";
- }
-
- @Benchmark
- public String widthStringIntFormat() {
- return FMT."%3s\{s} %d\{i}";
- }
-
- @Benchmark
- public String complexFormat() {
- return FMT."%3s\{s} %10d\{i} %4S\{s} %04X\{i} %4S\{s} %04X\{i} %4S\{s} %04X\{i}";
- }
-}