Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8294943: Implement record patterns in enhanced for #10798

Closed
wants to merge 43 commits into from
Closed
Changes from 2 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
05982bb
8294943: Implement record patterns in enhanced for
biboudis Sep 13, 2022
d6682de
Adding @since, adding PreviewFeature, restoring API method.
lahodaj Oct 11, 2022
a4c100f
API cleanup.
lahodaj Oct 19, 2022
a17ec69
8294942: Compiler implementation for Record Patterns (Second Preview)
lahodaj Oct 21, 2022
2b48bea
Store element type calculation result in JCEnhancedForLoop
biboudis Oct 21, 2022
ce2c78c
Fix applicability bug
biboudis Oct 26, 2022
2f0c597
Various cleanup and adjustments to specification updates.
lahodaj Oct 30, 2022
9b0bd99
Some more cleanup.
lahodaj Oct 30, 2022
456e811
Cleanup.
lahodaj Oct 30, 2022
6f1c30d
Fixing test.
lahodaj Oct 30, 2022
6a8b8b7
Address Review
biboudis Oct 31, 2022
45dd405
Merge remote-tracking branch 'lahodaj/JDK-8294942' into for-patterns
biboudis Oct 31, 2022
892fddf
Adjustments to make for-patterns and JDK-8294942 work together.
biboudis Oct 31, 2022
3e07a53
Simplify getDeclarationKind
biboudis Nov 1, 2022
f68756f
Reflecting review feedback.
lahodaj Nov 4, 2022
efe0d21
Adding a kind to InstanceOfTree, as suggested.
lahodaj Nov 4, 2022
77c34fc
Better tests for inference with recursive bounds, and related fixes.
lahodaj Nov 4, 2022
a65bf7a
Address review
biboudis Nov 7, 2022
89e28ab
Apply suggestions from code review
lahodaj Nov 7, 2022
c8f29c4
Reflecting review comment.
lahodaj Nov 7, 2022
5996914
Not looking for common supertype, not solving in a loop.
lahodaj Nov 9, 2022
7e7f63e
Fixing pattern/non-pattern disambiguation in presence of primitive-ty…
lahodaj Nov 10, 2022
260446f
Cleanup
lahodaj Nov 10, 2022
ff0d086
Merge pull request #1 from lahodaj/for-patterns
biboudis Nov 10, 2022
6e57e55
Fix parsing error in presence of nested patterns
biboudis Nov 11, 2022
68955d5
Fix parsing error in presence of lambdas
biboudis Nov 12, 2022
05965c2
Cleanup
biboudis Nov 12, 2022
5afc602
Reflecting review feedback - proper handling of type vars and interse…
lahodaj Nov 15, 2022
025c9f9
Merge branch 'JDK-8294942' into for-patterns
biboudis Nov 15, 2022
e7196a0
Using skipTypeVars as suggested.
lahodaj Nov 15, 2022
42f0cec
Improve error message on non-exhaustive enhanced for
biboudis Nov 15, 2022
f37e8ea
Merge branch 'JDK-8294942' into for-patterns
biboudis Nov 15, 2022
5e8e554
Merge branch 'master' into JDK-8294942
lahodaj Nov 21, 2022
73ca672
Fix selector type
biboudis Nov 22, 2022
44d4f06
Merge branch 'JDK-8294942' into for-patterns
biboudis Nov 24, 2022
861aaa3
Add @enablePreview
biboudis Nov 24, 2022
7892550
Fix some classification issues (#3)
mcimadamore Nov 24, 2022
72264d5
Disable parsing test
biboudis Nov 24, 2022
9e71284
Fixing handling of brackets in for/enhanced for/pattern enhanced for …
lahodaj Nov 25, 2022
9858ee8
Move parsing tests to DisambiguatePatterns.java
biboudis Nov 25, 2022
4d01e00
Merge branch 'master' into JDK-8294942
lahodaj Nov 29, 2022
38795e8
Merge branch 'JDK-8294942' into for-patterns
biboudis Dec 1, 2022
573c7da
Merge branch 'master' into for-patterns
biboudis Dec 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -3045,8 +3045,10 @@ else if(peekToken(lookahead, COLON)) {
}
case LBRACKET:
if (peekToken(lookahead, RBRACKET)) {
return ForInitResult.LocalVarDecl;
return inSelectionAndParenthesis ? ForInitResult.RecordPattern
: ForInitResult.LocalVarDecl;
}
return ForInitResult.LocalVarDecl;
case LT:
typeParameterPossibleStart = lookahead;
break;
103 changes: 102 additions & 1 deletion test/langtools/tools/javac/patterns/DisambiguatePatterns.java
Original file line number Diff line number Diff line change
@@ -35,16 +35,30 @@
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ConstantCaseLabelTree;
import com.sun.source.tree.EnhancedForLoopTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.PatternCaseLabelTree;
import com.sun.source.tree.PatternTree;
import com.sun.source.tree.StatementTree;
import com.sun.source.tree.SwitchTree;
import com.sun.source.tree.Tree.Kind;
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.Log;
import com.sun.tools.javac.util.Options;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;

public class DisambiguatePatterns {

@@ -110,14 +124,44 @@ public static void main(String... args) throws Throwable {
ExpressionType.EXPRESSION);
test.disambiguationTest("a & b",
ExpressionType.EXPRESSION);
test.forDisambiguationTest("T[] a", ForType.ENHANCED_FOR);
test.forDisambiguationTest("T[].class.getName()", ForType.TRADITIONAL_FOR);
test.forDisambiguationTest("T[].class", ForType.TRADITIONAL_FOR, "compiler.err.not.stmt");
test.forDisambiguationTest("R(T[] a)", ForType.ENHANCED_FOR_WITH_PATTERNS);

test.forDisambiguationTest("Point(Integer a, Integer b)", ForType.ENHANCED_FOR_WITH_PATTERNS);
test.forDisambiguationTest("ForEachPatterns.Point(Integer a, Integer b)", ForType.ENHANCED_FOR_WITH_PATTERNS);
test.forDisambiguationTest("GPoint<Integer>(Integer a, Integer b)", ForType.ENHANCED_FOR_WITH_PATTERNS);
test.forDisambiguationTest("@Annot(field = \"test\") Point p", ForType.ENHANCED_FOR);
test.forDisambiguationTest("GPoint<Point>(Point(Integer a, Integer b), Point c)", ForType.ENHANCED_FOR_WITH_PATTERNS);
test.forDisambiguationTest("GPoint<Point>(Point(var a, Integer b), Point c)", ForType.ENHANCED_FOR_WITH_PATTERNS);
test.forDisambiguationTest("GPoint<VoidPoint>(VoidPoint(), VoidPoint())", ForType.ENHANCED_FOR_WITH_PATTERNS);
test.forDisambiguationTest("RecordOfLists(List<Integer> lr)", ForType.ENHANCED_FOR_WITH_PATTERNS);
test.forDisambiguationTest("RecordOfLists2(List<List<Integer>> lr)", ForType.ENHANCED_FOR_WITH_PATTERNS);
test.forDisambiguationTest("GPoint<@Annot(field = \"\") ? extends Point>(var x, var y)", ForType.ENHANCED_FOR_WITH_PATTERNS);

test.forDisambiguationTest("method()", ForType.TRADITIONAL_FOR);
test.forDisambiguationTest("method(), method()", ForType.TRADITIONAL_FOR);
test.forDisambiguationTest("method2((Integer a) -> 42)", ForType.TRADITIONAL_FOR);
test.forDisambiguationTest("m(cond ? b() : i)", ForType.TRADITIONAL_FOR);
test.forDisambiguationTest("m((GPoint<?>)null, cond ? b() : i)", ForType.TRADITIONAL_FOR);
}

private final ParserFactory factory;
private final List<String> errors = new ArrayList<>();

public DisambiguatePatterns() {
public DisambiguatePatterns() throws URISyntaxException {
Context context = new Context();
context.put(DiagnosticListener.class, d -> {
if (d.getKind() == Diagnostic.Kind.ERROR) {
errors.add(d.getCode());
}
});
JavacFileManager jfm = new JavacFileManager(context, true, Charset.defaultCharset());
Options.instance(context).put(Option.PREVIEW, "");
SimpleJavaFileObject source =
new SimpleJavaFileObject(new URI("mem://Test.java"), JavaFileObject.Kind.SOURCE) {};
Log.instance(context).useSource(source);
factory = ParserFactory.instance(context);
}

@@ -148,9 +192,66 @@ private void test() {
}
}

void forDisambiguationTest(String snippet, ForType forType, String... expectedErrors) {
errors.clear();

String codeTemplate = switch (forType) {
case TRADITIONAL_FOR ->
"""
public class Test {
private void test() {
for (SNIPPET; ;) {
}
}
}
""";
case ENHANCED_FOR, ENHANCED_FOR_WITH_PATTERNS ->
"""
public class Test {
private void test() {
for (SNIPPET : collection) {
}
}
}
""";
};

String code = codeTemplate.replace("SNIPPET", snippet);
JavacParser parser = factory.newParser(code, false, false, false);
CompilationUnitTree result = parser.parseCompilationUnit();
if (!Arrays.asList(expectedErrors).equals(errors)) {
throw new AssertionError("Expected errors: " + Arrays.asList(expectedErrors) +
", actual: " + errors +
", for: " + code);
}
ClassTree clazz = (ClassTree) result.getTypeDecls().get(0);
MethodTree method = (MethodTree) clazz.getMembers().get(0);
StatementTree st = method.getBody().getStatements().get(0);
if (forType == ForType.TRADITIONAL_FOR) {
if (st.getKind() != Kind.FOR_LOOP) {
throw new AssertionError("Unpected statement: " + st);
}
} else {
EnhancedForLoopTree ef = (EnhancedForLoopTree) st;
ForType actualType = switch (ef.getVariableOrRecordPattern()) {
case PatternTree pattern -> ForType.ENHANCED_FOR_WITH_PATTERNS;
default -> ForType.ENHANCED_FOR;
};
if (forType != actualType) {
throw new AssertionError("Expected: " + forType + ", actual: " + actualType +
", for: " + code + ", parsed: " + result);
}
}
}

enum ExpressionType {
PATTERN,
EXPRESSION;
}

enum ForType {
TRADITIONAL_FOR,
ENHANCED_FOR,
ENHANCED_FOR_WITH_PATTERNS;
}
}
33 changes: 0 additions & 33 deletions test/langtools/tools/javac/patterns/ForEachPatterns.java
Original file line number Diff line number Diff line change
@@ -158,39 +158,6 @@ static int applicability2(List<Object> points) {
return -1;
}

static void m(int i) { }
static void m(GPoint<?> gpoint, int i) { }
static int b() { return 42; }

static void forParsing(int i, boolean cond) {
List<Point> points = null;
List<GPoint<Integer>> generic_points = null;
List<GPoint<Point>> generic_points_nested = null;
List<GPoint<VoidPoint>> generic_vpoints_nested = null;
List<RecordOfLists> list_of_records = null;
List<RecordOfLists2> list_of_records2 = null;

for (Point(Integer a, Integer b) : points) { }
for (ForEachPatterns.Point(Integer a, Integer b) : points) { }
for (GPoint<Integer>(Integer a, Integer b) : generic_points) { }
for (@Annot(field = "test") Point p : points) {}
for (method(); i == 0;) { i++; }
for (method(), method(); i == 0;) { i++; }
for (ForEachPatterns.<Integer>method(); i == 0;) { i++; }
for (GPoint<Point>(Point(Integer a, Integer b), Point c) : generic_points_nested) { }
for (GPoint<Point>(Point(var a, Integer b), Point c) : generic_points_nested) { }
for (GPoint<VoidPoint>(VoidPoint(), VoidPoint()) : generic_vpoints_nested) { }
for (method2((Integer a) -> 42); i == 0;) { i++; }
for (RecordOfLists(List<Integer> lr) : list_of_records) {}
for (RecordOfLists2(List<List<Integer>> lr) : list_of_records2) {}
for (m(cond ? b() : i) ; i == 0;) {}
for (m((GPoint<?>)null, cond ? b() : i) ; ;) {}
// for (GPoint<@Annot(field = "") ? extends Point>(var x, var y) : generic_points_nested) {}; // TODO: Enable after https://bugs.openjdk.org/browse/JDK-8297602 is fixed
}
//where
static <T> void method() {}
static <T> void method2(Function<Integer, Integer> f) {}

static List<Color> JEPExample() {
Rectangle rect = new Rectangle(
new ColoredPoint(new Point(1,2), Color.RED),