Skip to content

Commit 202b94e

Browse files
committed
GROOVY-9998
1 parent eb24b0c commit 202b94e

File tree

5 files changed

+129
-7
lines changed

5 files changed

+129
-7
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,4 +1471,75 @@ public void testTypeChecked9997() {
14711471

14721472
runConformTest(sources, "");
14731473
}
1474+
1475+
@Test
1476+
public void testTypeChecked9998() {
1477+
if (Float.parseFloat(System.getProperty("java.specification.version")) > 8)
1478+
vmArguments = new String[] {"--add-opens", "java.base/java.util.stream=ALL-UNNAMED"};
1479+
1480+
//@formatter:off
1481+
String[] sources = {
1482+
"Main.groovy",
1483+
"import groovy.transform.*\n" +
1484+
"@TupleConstructor(defaults=false)\n" +
1485+
"class A {\n" +
1486+
" final int order\n" +
1487+
"}\n" +
1488+
"@InheritConstructors @ToString(includeSuperProperties=true)\n" +
1489+
"class B extends A {\n" +
1490+
"}\n" +
1491+
"@TypeChecked\n" +
1492+
"def test() {\n" +
1493+
" Comparator<A> comparator = { a1, a2 -> Integer.compare(a1.order, a2.order) }\n" +
1494+
" [new B(2), new B(3), new B(1), new B(0)].stream().sorted(comparator).toList()\n" +
1495+
"}\n" +
1496+
"print test()\n",
1497+
};
1498+
//@formatter:on
1499+
1500+
runConformTest(sources, "[B(0), B(1), B(2), B(3)]");
1501+
}
1502+
1503+
@Test
1504+
public void testTypeChecked9998a() {
1505+
//@formatter:off
1506+
String[] sources = {
1507+
"Main.groovy",
1508+
"@groovy.transform.TypeChecked\n" +
1509+
"void test() {\n" +
1510+
" List<String> strings = [1].collectMany {\n" +
1511+
" Collections.emptyList()\n" +
1512+
" }\n" +
1513+
" print strings\n" +
1514+
"}\n" +
1515+
"test()\n",
1516+
};
1517+
//@formatter:on
1518+
1519+
runConformTest(sources, "[]");
1520+
}
1521+
1522+
@Test
1523+
public void testTypeChecked9998b() {
1524+
//@formatter:off
1525+
String[] sources = {
1526+
"Main.groovy",
1527+
"import static Type.*\n" +
1528+
"@groovy.transform.TypeChecked\n" +
1529+
"void test() {\n" +
1530+
" CharSequence cs = make(type)\n" +
1531+
" print cs\n" +
1532+
"}\n" +
1533+
"test()\n",
1534+
1535+
"Type.java",
1536+
"class Type {\n" +
1537+
" static <T> T make(Class<T> c) { return null; }\n" +
1538+
" static Class<? extends CharSequence> getType() { return String.class; }\n" +
1539+
"}\n",
1540+
};
1541+
//@formatter:on
1542+
1543+
runConformTest(sources, "null");
1544+
}
14741545
}

base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,11 @@ static void applyGenericsConnections(
17021702
// the original bounds are lost, which can result in accepting an incompatible type as an argument.
17031703
ClassNode replacementType = extractType(newValue);
17041704
if (oldValue.isCompatibleWith(replacementType)) {
1705+
// GRECLIPSE add -- GROOVY-9998
1706+
if (newValue.isWildcard() && newValue.getLowerBound() == null && newValue.getUpperBounds() == null) {
1707+
entry.setValue(new GenericsType(replacementType));
1708+
} else
1709+
// GRECLIPSE end
17051710
entry.setValue(newValue);
17061711
if (newValue.isPlaceholder()) {
17071712
checkForMorePlaceholders = checkForMorePlaceholders || !equalIncludingGenerics(oldValue, newValue);
@@ -1858,6 +1863,7 @@ private static void extractGenericsConnections(Map<GenericsTypeName, GenericsTyp
18581863
extractGenericsConnections(connections, ui.getLowerBound(), di.getLowerBound());
18591864
extractGenericsConnections(connections, ui.getUpperBounds(), di.getUpperBounds());
18601865
} else {
1866+
/* GRECLIPSE edit -- GROOVY-9998
18611867
ClassNode cu = ui.getType();
18621868
extractGenericsConnections(connections, cu, di.getLowerBound());
18631869
ClassNode[] upperBounds = di.getUpperBounds();
@@ -1866,6 +1872,16 @@ private static void extractGenericsConnections(Map<GenericsTypeName, GenericsTyp
18661872
extractGenericsConnections(connections, cu, cn);
18671873
}
18681874
}
1875+
*/
1876+
ClassNode boundType = getCombinedBoundType(di);
1877+
if (boundType.isGenericsPlaceHolder()) {
1878+
String placeholderName = boundType.getUnresolvedName();
1879+
ui = new GenericsType(ui.getType()); ui.setPlaceHolder(false); ui.setWildcard(true);
1880+
connections.put(new GenericsTypeName(placeholderName), ui);
1881+
} else { // di like "? super Collection<T>" and ui like "List<Type>"
1882+
extractGenericsConnections(connections, ui.getType(), boundType);
1883+
}
1884+
// GRECLIPSE end
18691885
}
18701886
} else {
18711887
extractGenericsConnections(connections, ui.getType(), di.getType());

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,7 +1604,7 @@ public static ClassNode resolveClassNodeGenerics(Map<GenericsTypeName, GenericsT
16041604
}
16051605

16061606
static void applyGenericsConnections(final Map<GenericsTypeName, GenericsType> connections, final Map<GenericsTypeName, GenericsType> resolvedPlaceholders) {
1607-
if (connections == null) return;
1607+
if (connections == null || connections.isEmpty()) return;
16081608
int count = 0;
16091609
while (count++ < 10000) {
16101610
boolean checkForMorePlaceholders = false;
@@ -1623,9 +1623,14 @@ static void applyGenericsConnections(final Map<GenericsTypeName, GenericsType> c
16231623
// the original bounds are lost, which can result in accepting an incompatible type as an argument.
16241624
ClassNode replacementType = extractType(newValue);
16251625
if (oldValue.isCompatibleWith(replacementType)) {
1626+
// GRECLIPSE add -- GROOVY-9998
1627+
if (newValue.isWildcard() && newValue.getLowerBound() == null && newValue.getUpperBounds() == null) {
1628+
entry.setValue(new GenericsType(replacementType));
1629+
} else
1630+
// GRECLIPSE end
16261631
entry.setValue(newValue);
1627-
if (newValue.isPlaceholder()) {
1628-
checkForMorePlaceholders = checkForMorePlaceholders || !equalIncludingGenerics(oldValue, newValue);
1632+
if (!checkForMorePlaceholders && newValue.isPlaceholder()) {
1633+
checkForMorePlaceholders = !equalIncludingGenerics(oldValue, newValue);
16291634
}
16301635
}
16311636
}
@@ -1772,6 +1777,7 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
17721777
extractGenericsConnections(connections, ui.getLowerBound(), di.getLowerBound());
17731778
extractGenericsConnections(connections, ui.getUpperBounds(), di.getUpperBounds());
17741779
} else {
1780+
/* GRECLIPSE edit -- GROOVY-9998
17751781
ClassNode cu = ui.getType();
17761782
extractGenericsConnections(connections, cu, di.getLowerBound());
17771783
ClassNode[] upperBounds = di.getUpperBounds();
@@ -1780,6 +1786,16 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
17801786
extractGenericsConnections(connections, cu, cn);
17811787
}
17821788
}
1789+
*/
1790+
ClassNode boundType = getCombinedBoundType(di);
1791+
if (boundType.isGenericsPlaceHolder()) {
1792+
String placeholderName = boundType.getUnresolvedName();
1793+
ui = new GenericsType(ui.getType()); ui.setPlaceHolder(false); ui.setWildcard(true);
1794+
connections.put(new GenericsTypeName(placeholderName), ui);
1795+
} else { // di like "? super Collection<T>" and ui like "List<Type>"
1796+
extractGenericsConnections(connections, ui.getType(), boundType);
1797+
}
1798+
// GRECLIPSE end
17831799
}
17841800
} else {
17851801
extractGenericsConnections(connections, ui.getType(), di.getType());

base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/GenericsType.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public void setName(final String name) {
161161
}
162162

163163
public boolean isResolved() {
164-
return (resolved || isPlaceholder());
164+
return resolved;
165165
}
166166

167167
public void setResolved(final boolean resolved) {
@@ -174,6 +174,8 @@ public boolean isPlaceholder() {
174174

175175
public void setPlaceholder(final boolean placeholder) {
176176
this.placeholder = placeholder;
177+
this.resolved = resolved || placeholder;
178+
this.wildcard = wildcard && !placeholder;
177179
getType().setGenericsPlaceHolder(placeholder);
178180
}
179181

@@ -183,6 +185,7 @@ public boolean isWildcard() {
183185

184186
public void setWildcard(final boolean wildcard) {
185187
this.wildcard = wildcard;
188+
this.placeholder = placeholder && !wildcard;
186189
}
187190

188191
public ClassNode getLowerBound() {

base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,7 +1602,7 @@ public static ClassNode resolveClassNodeGenerics(Map<GenericsTypeName, GenericsT
16021602
}
16031603

16041604
static void applyGenericsConnections(final Map<GenericsTypeName, GenericsType> connections, final Map<GenericsTypeName, GenericsType> resolvedPlaceholders) {
1605-
if (connections == null) return;
1605+
if (connections == null || connections.isEmpty()) return;
16061606
int count = 0;
16071607
while (count++ < 10000) {
16081608
boolean checkForMorePlaceholders = false;
@@ -1621,9 +1621,14 @@ static void applyGenericsConnections(final Map<GenericsTypeName, GenericsType> c
16211621
// the original bounds are lost, which can result in accepting an incompatible type as an argument.
16221622
ClassNode replacementType = extractType(newValue);
16231623
if (oldValue.isCompatibleWith(replacementType)) {
1624+
// GRECLIPSE add -- GROOVY-9998
1625+
if (newValue.isWildcard() && newValue.getLowerBound() == null && newValue.getUpperBounds() == null) {
1626+
entry.setValue(new GenericsType(replacementType));
1627+
} else
1628+
// GRECLIPSE end
16241629
entry.setValue(newValue);
1625-
if (newValue.isPlaceholder()) {
1626-
checkForMorePlaceholders = checkForMorePlaceholders || !equalIncludingGenerics(oldValue, newValue);
1630+
if (!checkForMorePlaceholders && newValue.isPlaceholder()) {
1631+
checkForMorePlaceholders = !equalIncludingGenerics(oldValue, newValue);
16271632
}
16281633
}
16291634
}
@@ -1770,6 +1775,7 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
17701775
extractGenericsConnections(connections, ui.getLowerBound(), di.getLowerBound());
17711776
extractGenericsConnections(connections, ui.getUpperBounds(), di.getUpperBounds());
17721777
} else {
1778+
/* GRECLIPSE edit -- GROOVY-9998
17731779
ClassNode cu = ui.getType();
17741780
extractGenericsConnections(connections, cu, di.getLowerBound());
17751781
ClassNode[] upperBounds = di.getUpperBounds();
@@ -1778,6 +1784,16 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
17781784
extractGenericsConnections(connections, cu, cn);
17791785
}
17801786
}
1787+
*/
1788+
ClassNode boundType = getCombinedBoundType(di);
1789+
if (boundType.isGenericsPlaceHolder()) {
1790+
String placeholderName = boundType.getUnresolvedName();
1791+
ui = new GenericsType(ui.getType()); ui.setWildcard(true);
1792+
connections.put(new GenericsTypeName(placeholderName), ui);
1793+
} else { // di like "? super Collection<T>" and ui like "List<Type>"
1794+
extractGenericsConnections(connections, ui.getType(), boundType);
1795+
}
1796+
// GRECLIPSE end
17811797
}
17821798
} else {
17831799
extractGenericsConnections(connections, ui.getType(), di.getType());

0 commit comments

Comments
 (0)