jdk-24/test/langtools/tools/javac/patterns/DisambiguatePatterns.java
2024-07-10 09:55:56 +00:00

160 lines
7.2 KiB
Java

/*
* Copyright (c) 2021, 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
* @modules jdk.compiler/com.sun.tools.javac.file
* jdk.compiler/com.sun.tools.javac.main
* jdk.compiler/com.sun.tools.javac.parser
* jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util
*/
import com.sun.source.tree.CaseLabelTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ConstantCaseLabelTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.PatternCaseLabelTree;
import com.sun.source.tree.SwitchTree;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.JavacParser;
import com.sun.tools.javac.parser.ParserFactory;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.util.Options;
import java.nio.charset.Charset;
public class DisambiguatePatterns {
public static void main(String... args) throws Throwable {
DisambiguatePatterns test = new DisambiguatePatterns();
test.disambiguationTest("String s",
ExpressionType.PATTERN);
test.disambiguationTest("String s when s.isEmpty()",
ExpressionType.PATTERN);
test.disambiguationTest("String s",
ExpressionType.PATTERN);
test.disambiguationTest("@Ann String s",
ExpressionType.PATTERN);
test.disambiguationTest("String s",
ExpressionType.PATTERN);
test.disambiguationTest("(String) s",
ExpressionType.EXPRESSION);
test.disambiguationTest("((String) s)",
ExpressionType.EXPRESSION);
test.disambiguationTest("((0x1))",
ExpressionType.EXPRESSION);
test.disambiguationTest("(a > b)",
ExpressionType.EXPRESSION);
test.disambiguationTest("(a >> b)",
ExpressionType.EXPRESSION);
test.disambiguationTest("(a >>> b)",
ExpressionType.EXPRESSION);
test.disambiguationTest("(a < b | a > b)",
ExpressionType.EXPRESSION);
test.disambiguationTest("(a << b | a >> b)",
ExpressionType.EXPRESSION);
test.disambiguationTest("(a << b || a < b | a >>> b)",
ExpressionType.EXPRESSION);
test.disambiguationTest("a < c.d > b",
ExpressionType.PATTERN);
test.disambiguationTest("a<? extends c.d> b",
ExpressionType.PATTERN);
test.disambiguationTest("@Ann a<? extends c.d> b",
ExpressionType.PATTERN);
test.disambiguationTest("a<? extends @Ann c.d> b",
ExpressionType.PATTERN);
test.disambiguationTest("a<? super c.d> b",
ExpressionType.PATTERN);
test.disambiguationTest("a<? super @Ann c.d> b",
ExpressionType.PATTERN);
test.disambiguationTest("a<b<c.d>> b",
ExpressionType.PATTERN);
test.disambiguationTest("a<b<@Ann c.d>> b",
ExpressionType.PATTERN);
test.disambiguationTest("a<b<c<d>>> b",
ExpressionType.PATTERN);
test.disambiguationTest("a[] b",
ExpressionType.PATTERN);
test.disambiguationTest("a[][] b",
ExpressionType.PATTERN);
test.disambiguationTest("int i",
ExpressionType.PATTERN);
test.disambiguationTest("int[] i",
ExpressionType.PATTERN);
test.disambiguationTest("a[a]",
ExpressionType.EXPRESSION);
test.disambiguationTest("a[b][c]",
ExpressionType.EXPRESSION);
test.disambiguationTest("a & b",
ExpressionType.EXPRESSION);
test.disambiguationTest("R r when (x > 0)",
ExpressionType.PATTERN);
test.disambiguationTest("R(int x) when (x > 0)",
ExpressionType.PATTERN);
}
private final ParserFactory factory;
public DisambiguatePatterns() {
Context context = new Context();
JavacFileManager jfm = new JavacFileManager(context, true, Charset.defaultCharset());
Options.instance(context).put(Option.PREVIEW, "");
factory = ParserFactory.instance(context);
}
void disambiguationTest(String snippet, ExpressionType expectedType) {
String code = """
public class Test {
private void test() {
switch (null) {
case SNIPPET -> {}
}
}
}
""".replace("SNIPPET", snippet);
JavacParser parser = factory.newParser(code, false, false, false);
CompilationUnitTree result = parser.parseCompilationUnit();
ClassTree clazz = (ClassTree) result.getTypeDecls().get(0);
MethodTree method = (MethodTree) clazz.getMembers().get(0);
SwitchTree st = (SwitchTree) method.getBody().getStatements().get(0);
CaseLabelTree label = st.getCases().get(0).getLabels().get(0);
ExpressionType actualType = switch (label) {
case ConstantCaseLabelTree et -> ExpressionType.EXPRESSION;
case PatternCaseLabelTree pt -> ExpressionType.PATTERN;
default -> throw new AssertionError("Unexpected result: " + result);
};
if (expectedType != actualType) {
throw new AssertionError("Expected: " + expectedType + ", actual: " + actualType +
", for: " + code + ", parsed: " + result);
}
}
enum ExpressionType {
PATTERN,
EXPRESSION;
}
}