Skip to content

Commit 4dd0ccc

Browse files
committed
GROOVY-6787, GROOVY-6919
1 parent 845f9fc commit 4dd0ccc

File tree

7 files changed

+136
-14
lines changed

7 files changed

+136
-14
lines changed

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

+28-5
Original file line numberDiff line numberDiff line change
@@ -562,12 +562,12 @@ public void testTypeChecked6787() {
562562
"def <T extends List<? super CharSequence>> void bar(T list) {\n" +
563563
"}\n" +
564564
"@groovy.transform.TypeChecked\n" +
565-
"def <T extends List<Object>> void one(T list) {\n" +
565+
"def <U extends List<Object>> void one(U list) {\n" +
566566
" foo(list)\n" + // no!
567567
" bar(list)\n" + // yes
568568
"}\n" +
569569
"@groovy.transform.TypeChecked\n" +
570-
"def <T extends List<String>> void two(T list) {\n" +
570+
"def <U extends List<String>> void two(U list) {\n" +
571571
" foo(list)\n" + // yes
572572
" bar(list)\n" + // no!
573573
"}\n",
@@ -579,12 +579,12 @@ public void testTypeChecked6787() {
579579
"1. ERROR in Main.groovy (at line 7)\n" +
580580
"\tfoo(list)\n" +
581581
"\t^^^^^^^^^\n" +
582-
"Groovy:[Static type checking] - Cannot call <T extends java.util.List<? extends java.lang.CharSequence>> Main#foo(T) with arguments [java.util.List<java.lang.Object>]\n" +
582+
"Groovy:[Static type checking] - Cannot call <T extends java.util.List<? extends java.lang.CharSequence>> Main#foo(T) with arguments [U]\n" +
583583
"----------\n" +
584584
"2. ERROR in Main.groovy (at line 13)\n" +
585585
"\tbar(list)\n" +
586586
"\t^^^^^^^^^\n" +
587-
"Groovy:[Static type checking] - Cannot call <T extends java.util.List<? super java.lang.CharSequence>> Main#bar(T) with arguments [java.util.List<java.lang.String>]\n" +
587+
"Groovy:[Static type checking] - Cannot call <T extends java.util.List<? super java.lang.CharSequence>> Main#bar(T) with arguments [U]\n" +
588588
"----------\n");
589589
}
590590

@@ -668,6 +668,29 @@ public void testTypeChecked6912a() {
668668
runConformTest(sources);
669669
}
670670

671+
@Test
672+
public void testTypeChecked6919() {
673+
//@formatter:off
674+
String[] sources = {
675+
"Main.groovy",
676+
"interface I1 {\n" +
677+
" String getFoo()\n" +
678+
"}\n" +
679+
"interface I2 {\n" +
680+
" String getBar()\n" +
681+
"}\n" +
682+
"@groovy.transform.TypeChecked\n" +
683+
"def <T extends I1 & I2> void test(T obj) {\n" +
684+
" obj?.foo\n" +
685+
" obj?.bar\n" +
686+
"}\n" +
687+
"test()\n",
688+
};
689+
//@formatter:on
690+
691+
runConformTest(sources);
692+
}
693+
671694
@Test
672695
public void testTypeChecked6938() {
673696
//@formatter:off
@@ -3425,7 +3448,7 @@ public void testTypeChecked10166() {
34253448
"1. ERROR in Main.groovy (at line 17)\n" +
34263449
"\ta.c.get(1)\n" +
34273450
"\t^^^^^^^^^^\n" +
3428-
"Groovy:[Static type checking] - Cannot find matching method A#get(int). Please check if the declared type is correct and if the method exists.\n" +
3451+
"Groovy:[Static type checking] - Cannot find matching method T#get(int). Please check if the declared type is correct and if the method exists.\n" +
34293452
"----------\n");
34303453
}
34313454

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ static String prettyPrintTypeName(final ClassNode type) {
960960
if (type.isArray()) {
961961
return prettyPrintTypeName(type.getComponentType()) + "[]";
962962
}
963-
return type.getText();
963+
return type.isGenericsPlaceHolder() ? type.getUnresolvedName() : type.getText();
964964
}
965965

966966
public static boolean implementsInterfaceOrIsSubclassOf(ClassNode type, ClassNode superOrInterface) {

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

+34-2
Original file line numberDiff line numberDiff line change
@@ -4500,7 +4500,7 @@ else if (isClassClassNodeWrappingConcreteType(receiver)) {
45004500
addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
45014501
owners.add(Receiver.make(receiver)); // Class<Type>
45024502
} else {
4503-
owners.add(Receiver.make(receiver));
4503+
addBoundType(receiver, owners);
45044504
addSelfTypes(receiver, owners);
45054505
addTraitType(receiver, owners);
45064506
if (receiver.isInterface()) {
@@ -4511,6 +4511,25 @@ else if (isClassClassNodeWrappingConcreteType(receiver)) {
45114511
return owners;
45124512
}
45134513

4514+
// GRECLIPSE add
4515+
private static void addBoundType(final ClassNode receiver, final List<Receiver<String>> owners) {
4516+
if (!receiver.isGenericsPlaceHolder() || receiver.getGenericsTypes() == null) {
4517+
owners.add(Receiver.make(receiver));
4518+
return;
4519+
}
4520+
4521+
GenericsType gt = receiver.getGenericsTypes()[0];
4522+
if (gt.getLowerBound() == null && gt.getUpperBounds() != null) {
4523+
for (ClassNode cn : gt.getUpperBounds()) { // T extends C & I
4524+
addBoundType(cn, owners);
4525+
addSelfTypes(cn, owners);
4526+
}
4527+
} else {
4528+
owners.add(Receiver.make(OBJECT_TYPE)); // T or T super Type
4529+
}
4530+
}
4531+
// GRECLIPSE end
4532+
45144533
private static void addSelfTypes(final ClassNode receiver, final List<Receiver<String>> owners) {
45154534
LinkedHashSet<ClassNode> selfTypes = new LinkedHashSet<ClassNode>();
45164535
for (ClassNode selfType : Traits.collectSelfTypes(receiver, selfTypes)) {
@@ -6806,7 +6825,7 @@ protected void addNoMatchingMethodError(ClassNode receiver, final String name, f
68066825
if (isClassClassNodeWrappingConcreteType(receiver)) {
68076826
receiver = receiver.getGenericsTypes()[0].getType();
68086827
}
6809-
addStaticTypeError("Cannot find matching method " + receiver.getText() + "#" + toMethodParametersString(name, args) + ". Please check if the declared type is correct and if the method exists.", call);
6828+
addStaticTypeError("Cannot find matching method " + prettyPrintTypeName(receiver) + "#" + toMethodParametersString(name, args) + ". Please check if the declared type is correct and if the method exists.", call);
68106829
}
68116830

68126831
protected void addAmbiguousErrorMessage(final List<MethodNode> foundMethods, final String name, final ClassNode[] args, final Expression expr) {
@@ -6992,12 +7011,16 @@ private static class ParameterVariableExpression extends VariableExpression {
69927011
ParameterVariableExpression(Parameter parameter) {
69937012
super(parameter);
69947013
this.parameter = parameter;
7014+
/* GRECLIPSE edit -- GROOVY-6919
69957015
ClassNode inferred = parameter.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
69967016
if (inferred == null) {
69977017
inferred = infer(parameter);
69987018
69997019
parameter.setNodeMetaData(StaticTypesMarker.INFERRED_TYPE, inferred);
70007020
}
7021+
*/
7022+
parameter.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE, x -> parameter.getOriginType());
7023+
// GRECLIPSE end
70017024
}
70027025

70037026
@Override
@@ -7030,6 +7053,7 @@ public void setNodeMetaData(Object key, Object value) {
70307053
parameter.setNodeMetaData(key, value);
70317054
}
70327055

7056+
/* GRECLIPSE edit
70337057
@Override
70347058
public int hashCode() {
70357059
return parameter.hashCode();
@@ -7039,8 +7063,15 @@ public int hashCode() {
70397063
public boolean equals(Object other) {
70407064
return parameter.equals(other);
70417065
}
7066+
*/
7067+
@Override
7068+
public <T> T getNodeMetaData(Object key, java.util.function.Function<?, ? extends T> valFn) {
7069+
return parameter.getNodeMetaData(key, valFn);
7070+
}
7071+
// GRECLIPSE end
70427072
}
70437073

7074+
/* GRECLIPSE edit
70447075
private static ClassNode infer(Variable variable) {
70457076
ClassNode originType = variable.getOriginType();
70467077
@@ -7059,4 +7090,5 @@ private static ClassNode infer(Variable variable) {
70597090
70607091
return variable.getOriginType();
70617092
}
7093+
*/
70627094
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ static String prettyPrintTypeName(final ClassNode type) {
907907
if (type.isArray()) {
908908
return prettyPrintTypeName(type.getComponentType()) + "[]";
909909
}
910-
return type.getText();
910+
return type.isGenericsPlaceHolder() ? type.getUnresolvedName() : type.getText();
911911
}
912912

913913
public static boolean implementsInterfaceOrIsSubclassOf(final ClassNode type, final ClassNode superOrInterface) {

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

+35-3
Original file line numberDiff line numberDiff line change
@@ -4157,17 +4157,34 @@ else if (isClassClassNodeWrappingConcreteType(receiver)) {
41574157
addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
41584158
owners.add(Receiver.make(receiver)); // Class<Type>
41594159
} else {
4160-
owners.add(Receiver.make(receiver));
4160+
addBoundType(receiver, owners);
41614161
addSelfTypes(receiver, owners);
41624162
addTraitType(receiver, owners);
4163-
if (receiver.isInterface()) {
4163+
if (receiver.redirect().isInterface()) {
41644164
owners.add(Receiver.make(OBJECT_TYPE));
41654165
}
41664166
}
41674167
// GRECLIPSE end
41684168
return owners;
41694169
}
41704170

4171+
private static void addBoundType(final ClassNode receiver, final List<Receiver<String>> owners) {
4172+
if (!receiver.isGenericsPlaceHolder() || receiver.getGenericsTypes() == null) {
4173+
owners.add(Receiver.make(receiver));
4174+
return;
4175+
}
4176+
4177+
GenericsType gt = receiver.getGenericsTypes()[0];
4178+
if (gt.getLowerBound() == null && gt.getUpperBounds() != null) {
4179+
for (ClassNode cn : gt.getUpperBounds()) { // T extends C & I
4180+
addBoundType(cn, owners);
4181+
addSelfTypes(cn, owners);
4182+
}
4183+
} else {
4184+
owners.add(Receiver.make(OBJECT_TYPE)); // T or T super Type
4185+
}
4186+
}
4187+
41714188
private static void addSelfTypes(final ClassNode receiver, final List<Receiver<String>> owners) {
41724189
for (ClassNode selfType : Traits.collectSelfTypes(receiver, new LinkedHashSet<>())) {
41734190
owners.add(Receiver.make(selfType));
@@ -6430,7 +6447,7 @@ protected void addNoMatchingMethodError(ClassNode receiver, final String name, f
64306447
if (isClassClassNodeWrappingConcreteType(receiver)) {
64316448
receiver = receiver.getGenericsTypes()[0].getType();
64326449
}
6433-
addStaticTypeError("Cannot find matching method " + receiver.getText() + "#" + toMethodParametersString(name, args) + ". Please check if the declared type is correct and if the method exists.", call);
6450+
addStaticTypeError("Cannot find matching method " + prettyPrintTypeName(receiver) + "#" + toMethodParametersString(name, args) + ". Please check if the declared type is correct and if the method exists.", call);
64346451
}
64356452

64366453
protected void addAmbiguousErrorMessage(final List<MethodNode> foundMethods, final String name, final ClassNode[] args, final Expression expr) {
@@ -6593,14 +6610,19 @@ private static class ParameterVariableExpression extends VariableExpression {
65936610
ParameterVariableExpression(final Parameter parameter) {
65946611
super(parameter);
65956612
this.parameter = parameter;
6613+
/* GRECLIPSE edit -- GROOVY-6919
65966614
ClassNode inferred = parameter.getNodeMetaData(INFERRED_TYPE);
65976615
if (inferred == null) {
65986616
inferred = infer(parameter);
65996617
66006618
parameter.setNodeMetaData(INFERRED_TYPE, inferred);
66016619
}
6620+
*/
6621+
parameter.getNodeMetaData(INFERRED_TYPE, x -> parameter.getOriginType());
6622+
// GRECLIPSE end
66026623
}
66036624

6625+
/* GRECLIPSE edit
66046626
private static ClassNode infer(final Variable variable) {
66056627
ClassNode originType = variable.getOriginType();
66066628
@@ -6659,6 +6681,16 @@ public int hashCode() {
66596681
public boolean equals(final Object other) {
66606682
return parameter.equals(other);
66616683
}
6684+
*/
6685+
@Override
6686+
public Map getMetaDataMap() {
6687+
return parameter.getMetaDataMap();
6688+
}
6689+
@Override
6690+
public void setMetaDataMap(final Map map) {
6691+
parameter.setMetaDataMap(map);
6692+
}
6693+
// GRECLIPSE end
66626694
}
66636695

66646696
protected class VariableExpressionTypeMemoizer extends ClassCodeVisitorSupport {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ static String prettyPrintTypeName(final ClassNode type) {
884884
if (type.isArray()) {
885885
return prettyPrintTypeName(type.getComponentType()) + "[]";
886886
}
887-
return type.getText();
887+
return type.isGenericsPlaceHolder() ? type.getUnresolvedName() : type.getText();
888888
}
889889

890890
public static boolean implementsInterfaceOrIsSubclassOf(final ClassNode type, final ClassNode superOrInterface) {

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

+36-1
Original file line numberDiff line numberDiff line change
@@ -3960,17 +3960,37 @@ protected List<Receiver<String>> makeOwnerList(final Expression objectExpression
39603960
addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
39613961
owners.add(Receiver.make(receiver)); // Class<Type>
39623962
} else {
3963+
/* GRECLIPSE edit -- GROOVY-6919
39633964
owners.add(Receiver.make(receiver));
3965+
*/
3966+
addBoundType(receiver, owners);
39643967
addSelfTypes(receiver, owners);
39653968
addTraitType(receiver, owners);
3966-
if (receiver.isInterface()) {
3969+
if (receiver.redirect().isInterface()) {
39673970
owners.add(Receiver.make(OBJECT_TYPE));
39683971
}
39693972
}
39703973
}
39713974
return owners;
39723975
}
39733976

3977+
private static void addBoundType(final ClassNode receiver, final List<Receiver<String>> owners) {
3978+
if (!receiver.isGenericsPlaceHolder() || receiver.getGenericsTypes() == null) {
3979+
owners.add(Receiver.make(receiver));
3980+
return;
3981+
}
3982+
3983+
GenericsType gt = receiver.getGenericsTypes()[0];
3984+
if (gt.getLowerBound() == null && gt.getUpperBounds() != null) {
3985+
for (ClassNode cn : gt.getUpperBounds()) { // T extends C & I
3986+
addBoundType(cn, owners);
3987+
addSelfTypes(cn, owners);
3988+
}
3989+
} else {
3990+
owners.add(Receiver.make(OBJECT_TYPE)); // T or T super Type
3991+
}
3992+
}
3993+
39743994
private static void addSelfTypes(final ClassNode receiver, final List<Receiver<String>> owners) {
39753995
for (ClassNode selfType : Traits.collectSelfTypes(receiver, new LinkedHashSet<>())) {
39763996
owners.add(Receiver.make(selfType));
@@ -6074,14 +6094,19 @@ private static class ParameterVariableExpression extends VariableExpression {
60746094
ParameterVariableExpression(final Parameter parameter) {
60756095
super(parameter);
60766096
this.parameter = parameter;
6097+
/* GRECLIPSE edit -- GROOVY-6919
60776098
ClassNode inferred = parameter.getNodeMetaData(INFERRED_TYPE);
60786099
if (inferred == null) {
60796100
inferred = infer(parameter);
60806101
60816102
parameter.setNodeMetaData(INFERRED_TYPE, inferred);
60826103
}
6104+
*/
6105+
parameter.getNodeMetaData(INFERRED_TYPE, x -> parameter.getOriginType());
6106+
// GRECLIPSE end
60836107
}
60846108

6109+
/* GRECLIPSE edit
60856110
private static ClassNode infer(final Variable variable) {
60866111
ClassNode originType = variable.getOriginType();
60876112
@@ -6140,6 +6165,16 @@ public int hashCode() {
61406165
public boolean equals(final Object other) {
61416166
return parameter.equals(other);
61426167
}
6168+
*/
6169+
@Override
6170+
public Map getMetaDataMap() {
6171+
return parameter.getMetaDataMap();
6172+
}
6173+
@Override
6174+
public void setMetaDataMap(final Map map) {
6175+
parameter.setMetaDataMap(map);
6176+
}
6177+
// GRECLIPSE end
61436178
}
61446179

61456180
protected class VariableExpressionTypeMemoizer extends ClassCodeVisitorSupport {

0 commit comments

Comments
 (0)