Skip to content

Commit ef0931b

Browse files
committed
GROOVY-10179, GROOVY-10180
#1281
1 parent 9553b6c commit ef0931b

File tree

4 files changed

+162
-18
lines changed

4 files changed

+162
-18
lines changed

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

+58
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,24 @@ public void testTypeChecked6232() {
436436
runConformTest(sources);
437437
}
438438

439+
@Test
440+
public void testTypeChecked6240() {
441+
//@formatter:off
442+
String[] sources = {
443+
"Main.groovy",
444+
"@groovy.transform.TypeChecked\n" +
445+
"void test(Map<String,Number> map) {\n" +
446+
" for (e in map) {\n" +
447+
" print \"${e.key.toUpperCase()}${e.value.intValue()}\"\n" +
448+
" }\n" +
449+
"}\n" +
450+
"test(a:1,b:2,c:3.14)\n",
451+
};
452+
//@formatter:on
453+
454+
runConformTest(sources, "A1B2C3");
455+
}
456+
439457
@Test
440458
public void testTypeChecked6786() {
441459
//@formatter:off
@@ -3036,4 +3054,44 @@ public void testTypeChecked10111a() {
30363054

30373055
runConformTest(sources);
30383056
}
3057+
3058+
@Test
3059+
public void testTypeChecked10179() {
3060+
//@formatter:off
3061+
String[] sources = {
3062+
"Main.groovy",
3063+
"@groovy.transform.TypeChecked\n" +
3064+
"void test(args) {\n" +
3065+
" if (args instanceof Map) {\n" +
3066+
" for (e in args) {\n" +
3067+
" print \"${e.key}${e.value}\"\n" +
3068+
" }\n" +
3069+
" }\n" +
3070+
"}\n" +
3071+
"test(a:1,b:2,c:3.14)\n",
3072+
};
3073+
//@formatter:on
3074+
3075+
runConformTest(sources, "a1b2c3.14");
3076+
}
3077+
3078+
@Test
3079+
public void testTypeChecked10180() {
3080+
//@formatter:off
3081+
String[] sources = {
3082+
"Main.groovy",
3083+
"@groovy.transform.TypeChecked\n" +
3084+
"void test(args) {\n" +
3085+
" if (args instanceof Map) {\n" +
3086+
" args.each { e ->\n" +
3087+
" print \"${e.key}${e.value}\"\n" +
3088+
" }\n" +
3089+
" }\n" +
3090+
"}\n" +
3091+
"test(a:1,b:2,c:3.14)\n",
3092+
};
3093+
//@formatter:on
3094+
3095+
runConformTest(sources, "a1b2c3.14");
3096+
}
30393097
}

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

+34-17
Original file line numberDiff line numberDiff line change
@@ -2308,7 +2308,16 @@ public void visitForLoop(final ForStatement forLoop) {
23082308
super.visitForLoop(forLoop);
23092309
} else {
23102310
collectionExpression.visit(this);
2311+
/* GRECLIPSE edit -- GROOVY-10179
23112312
final ClassNode collectionType = getType(collectionExpression);
2313+
*/
2314+
ClassNode collectionType;
2315+
if (collectionExpression instanceof VariableExpression && hasInferredReturnType(collectionExpression)) {
2316+
collectionType = getInferredReturnType(collectionExpression);
2317+
} else {
2318+
collectionType = getType(collectionExpression);
2319+
}
2320+
// GRECLIPSE end
23122321
ClassNode forLoopVariableType = forLoop.getVariableType();
23132322
ClassNode componentType;
23142323
if (Character_TYPE.equals(ClassHelper.getWrapper(forLoopVariableType)) && STRING_TYPE.equals(collectionType)) {
@@ -3932,8 +3941,16 @@ public void visitMethodCallExpression(MethodCallExpression call) {
39323941

39333942
// for arguments, we need to visit closures *after* the method has been chosen
39343943

3935-
3944+
/* GRECLIPSE edit
39363945
ClassNode receiver = getType(objectExpression);
3946+
*/
3947+
ClassNode receiver;
3948+
if (objectExpression instanceof VariableExpression && hasInferredReturnType(objectExpression)) {
3949+
receiver = getInferredReturnType(objectExpression);
3950+
} else {
3951+
receiver = getType(objectExpression);
3952+
}
3953+
// GRECLIPSE end
39373954
visitMethodCallArguments(receiver, argumentList, false, null);
39383955

39393956
ClassNode[] args = getArgumentTypes(argumentList);
@@ -4345,8 +4362,8 @@ protected ClassNode getInferredReturnTypeFromWithClosureArgument(Expression call
43454362
*/
43464363
protected List<Receiver<String>> makeOwnerList(final Expression objectExpression) {
43474364
final ClassNode receiver = getType(objectExpression);
4348-
/* GRECLIPSE edit -- GROOVY-9586
43494365
List<Receiver<String>> owners = new LinkedList<Receiver<String>>();
4366+
/* GRECLIPSE edit -- GROOVY-9586, GROOVY-10180
43504367
owners.add(Receiver.<String>make(receiver));
43514368
if (isClassClassNodeWrappingConcreteType(receiver)) {
43524369
GenericsType clazzGT = receiver.getGenericsTypes()[0];
@@ -4357,21 +4374,6 @@ protected List<Receiver<String>> makeOwnerList(final Expression objectExpression
43574374
}
43584375
addSelfTypes(receiver, owners);
43594376
*/
4360-
List<Receiver<String>> owners = new ArrayList<>();
4361-
if (isClassClassNodeWrappingConcreteType(receiver)) {
4362-
ClassNode staticType = receiver.getGenericsTypes()[0].getType();
4363-
owners.add(Receiver.make(staticType)); // Type from Class<Type>
4364-
addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
4365-
owners.add(Receiver.make(receiver)); // Class<Type>
4366-
} else {
4367-
owners.add(Receiver.make(receiver));
4368-
if (receiver.isInterface()) {
4369-
owners.add(Receiver.make(OBJECT_TYPE));
4370-
}
4371-
addSelfTypes(receiver, owners);
4372-
addTraitType(receiver, owners);
4373-
}
4374-
// GRECLIPSE end
43754377
if (!typeCheckingContext.temporaryIfBranchTypeInformation.empty()) {
43764378
List<ClassNode> potentialReceiverType = getTemporaryTypesForExpression(objectExpression);
43774379
if (potentialReceiverType != null) {
@@ -4394,6 +4396,21 @@ protected List<Receiver<String>> makeOwnerList(final Expression objectExpression
43944396
Receiver.<String>make(typeCheckingContext.getEnclosingClassNode()));
43954397
addReceivers(owners, enclosingClass, typeCheckingContext.delegationMetadata.getParent(), "owner.");
43964398
}
4399+
// GRECLIPSE add
4400+
else if (isClassClassNodeWrappingConcreteType(receiver)) {
4401+
ClassNode staticType = receiver.getGenericsTypes()[0].getType();
4402+
owners.add(Receiver.make(staticType)); // Type from Class<Type>
4403+
addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
4404+
owners.add(Receiver.make(receiver)); // Class<Type>
4405+
} else {
4406+
owners.add(Receiver.make(receiver));
4407+
addSelfTypes(receiver, owners);
4408+
addTraitType(receiver, owners);
4409+
if (receiver.isInterface()) {
4410+
owners.add(Receiver.make(OBJECT_TYPE));
4411+
}
4412+
}
4413+
// GRECLIPSE end
43974414
return owners;
43984415
}
43994416

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

+35-1
Original file line numberDiff line numberDiff line change
@@ -2121,7 +2121,16 @@ public void visitForLoop(final ForStatement forLoop) {
21212121
super.visitForLoop(forLoop);
21222122
} else {
21232123
collectionExpression.visit(this);
2124+
/* GRECLIPSE edit -- GROOVY-10179
21242125
ClassNode collectionType = getType(collectionExpression);
2126+
*/
2127+
ClassNode collectionType;
2128+
if (collectionExpression instanceof VariableExpression && hasInferredReturnType(collectionExpression)) {
2129+
collectionType = getInferredReturnType(collectionExpression);
2130+
} else {
2131+
collectionType = getType(collectionExpression);
2132+
}
2133+
// GRECLIPSE end
21252134
ClassNode forLoopVariableType = forLoop.getVariableType();
21262135
ClassNode componentType;
21272136
if (Character_TYPE.equals(getWrapper(forLoopVariableType)) && STRING_TYPE.equals(collectionType)) {
@@ -3642,8 +3651,16 @@ public void visitMethodCallExpression(final MethodCallExpression call) {
36423651
checkForbiddenSpreadArgument(argumentList);
36433652

36443653
// for arguments, we need to visit closures *after* the method has been chosen
3645-
3654+
/* GRECLIPSE edit
36463655
ClassNode receiver = getType(objectExpression);
3656+
*/
3657+
ClassNode receiver;
3658+
if (objectExpression instanceof VariableExpression && hasInferredReturnType(objectExpression)) {
3659+
receiver = getInferredReturnType(objectExpression);
3660+
} else {
3661+
receiver = getType(objectExpression);
3662+
}
3663+
// GRECLIPSE end
36473664
visitMethodCallArguments(receiver, argumentList, false, null);
36483665

36493666
ClassNode[] args = getArgumentTypes(argumentList);
@@ -4080,6 +4097,7 @@ protected ClassNode getInferredReturnTypeFromWithClosureArgument(final Expressio
40804097
protected List<Receiver<String>> makeOwnerList(final Expression objectExpression) {
40814098
ClassNode receiver = getType(objectExpression);
40824099
List<Receiver<String>> owners = new ArrayList<>();
4100+
/* GRECLIPSE edit -- GROOVY-10180
40834101
if (isClassClassNodeWrappingConcreteType(receiver)) {
40844102
ClassNode staticType = receiver.getGenericsTypes()[0].getType();
40854103
owners.add(Receiver.make(staticType)); // Type from Class<Type>
@@ -4093,6 +4111,7 @@ protected List<Receiver<String>> makeOwnerList(final Expression objectExpression
40934111
addSelfTypes(receiver, owners);
40944112
addTraitType(receiver, owners);
40954113
}
4114+
*/
40964115
if (!typeCheckingContext.temporaryIfBranchTypeInformation.isEmpty()) {
40974116
List<ClassNode> potentialReceiverType = getTemporaryTypesForExpression(objectExpression);
40984117
if (potentialReceiverType != null && !potentialReceiverType.isEmpty()) {
@@ -4115,6 +4134,21 @@ protected List<Receiver<String>> makeOwnerList(final Expression objectExpression
41154134
Receiver.make(typeCheckingContext.getEnclosingClassNode()));
41164135
addReceivers(owners, enclosingClass, typeCheckingContext.delegationMetadata.getParent(), "owner.");
41174136
}
4137+
// GRECLIPSE add
4138+
else if (isClassClassNodeWrappingConcreteType(receiver)) {
4139+
ClassNode staticType = receiver.getGenericsTypes()[0].getType();
4140+
owners.add(Receiver.make(staticType)); // Type from Class<Type>
4141+
addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
4142+
owners.add(Receiver.make(receiver)); // Class<Type>
4143+
} else {
4144+
owners.add(Receiver.make(receiver));
4145+
addSelfTypes(receiver, owners);
4146+
addTraitType(receiver, owners);
4147+
if (receiver.isInterface()) {
4148+
owners.add(Receiver.make(OBJECT_TYPE));
4149+
}
4150+
}
4151+
// GRECLIPSE end
41184152
return owners;
41194153
}
41204154

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

+35
Original file line numberDiff line numberDiff line change
@@ -2037,7 +2037,16 @@ public void visitForLoop(final ForStatement forLoop) {
20372037
super.visitForLoop(forLoop);
20382038
} else {
20392039
collectionExpression.visit(this);
2040+
/* GRECLIPSE edit -- GROOVY-10179
20402041
ClassNode collectionType = getType(collectionExpression);
2042+
*/
2043+
ClassNode collectionType;
2044+
if (collectionExpression instanceof VariableExpression && hasInferredReturnType(collectionExpression)) {
2045+
collectionType = getInferredReturnType(collectionExpression);
2046+
} else {
2047+
collectionType = getType(collectionExpression);
2048+
}
2049+
// GRECLIPSE end
20412050
ClassNode forLoopVariableType = forLoop.getVariableType();
20422051
ClassNode componentType;
20432052
if (Character_TYPE.equals(getWrapper(forLoopVariableType)) && STRING_TYPE.equals(collectionType)) {
@@ -3518,7 +3527,16 @@ public void visitMethodCallExpression(final MethodCallExpression call) {
35183527
objectExpression.visit(this);
35193528
call.getMethod().visit(this);
35203529

3530+
/* GRECLIPSE edit
35213531
ClassNode receiver = getType(objectExpression);
3532+
*/
3533+
ClassNode receiver;
3534+
if (objectExpression instanceof VariableExpression && hasInferredReturnType(objectExpression)) {
3535+
receiver = getInferredReturnType(objectExpression);
3536+
} else {
3537+
receiver = getType(objectExpression);
3538+
}
3539+
// GRECLIPSE end
35223540
// if it's a spread operator call, then make sure receiver is array or collection
35233541
if (call.isSpreadSafe()) {
35243542
if (!receiver.isArray() && !implementsInterfaceOrIsSubclassOf(receiver, Collection_TYPE)) {
@@ -3985,6 +4003,7 @@ protected ClassNode getInferredReturnTypeFromWithClosureArgument(final Expressio
39854003
protected List<Receiver<String>> makeOwnerList(final Expression objectExpression) {
39864004
ClassNode receiver = getType(objectExpression);
39874005
List<Receiver<String>> owners = new ArrayList<>();
4006+
/* GRECLIPSE edit -- GROOVY-10180
39884007
if (isClassClassNodeWrappingConcreteType(receiver)) {
39894008
ClassNode staticType = receiver.getGenericsTypes()[0].getType();
39904009
owners.add(Receiver.make(staticType)); // Type from Class<Type>
@@ -3998,6 +4017,7 @@ protected List<Receiver<String>> makeOwnerList(final Expression objectExpression
39984017
addSelfTypes(receiver, owners);
39994018
addTraitType(receiver, owners);
40004019
}
4020+
*/
40014021
if (!typeCheckingContext.temporaryIfBranchTypeInformation.isEmpty()) {
40024022
List<ClassNode> potentialReceiverType = getTemporaryTypesForExpression(objectExpression);
40034023
if (potentialReceiverType != null && !potentialReceiverType.isEmpty()) {
@@ -4020,6 +4040,21 @@ protected List<Receiver<String>> makeOwnerList(final Expression objectExpression
40204040
Receiver.make(typeCheckingContext.getEnclosingClassNode()));
40214041
addReceivers(owners, enclosingClass, typeCheckingContext.delegationMetadata.getParent(), "owner.");
40224042
}
4043+
// GRECLIPSE add
4044+
else if (isClassClassNodeWrappingConcreteType(receiver)) {
4045+
ClassNode staticType = receiver.getGenericsTypes()[0].getType();
4046+
owners.add(Receiver.make(staticType)); // Type from Class<Type>
4047+
addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
4048+
owners.add(Receiver.make(receiver)); // Class<Type>
4049+
} else {
4050+
owners.add(Receiver.make(receiver));
4051+
addSelfTypes(receiver, owners);
4052+
addTraitType(receiver, owners);
4053+
if (receiver.isInterface()) {
4054+
owners.add(Receiver.make(OBJECT_TYPE));
4055+
}
4056+
}
4057+
// GRECLIPSE end
40234058
return owners;
40244059
}
40254060

0 commit comments

Comments
 (0)