Skip to content

Commit 47b80c1

Browse files
committed
GROOVY-10651
1 parent 0d19756 commit 47b80c1

File tree

6 files changed

+144
-26
lines changed

6 files changed

+144
-26
lines changed

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

+80
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,35 @@ public void testTypeChecked26() {
646646
"----------\n");
647647
}
648648

649+
@Test
650+
public void testTypeChecked27() {
651+
//@formatter:off
652+
String[] sources = {
653+
"Main.groovy",
654+
"interface A {\n" +
655+
" def getX()\n" +
656+
"}\n" +
657+
"interface B {\n" +
658+
" def getY()\n" +
659+
"}\n" +
660+
"@groovy.transform.TypeChecked\n" +
661+
"void test(A a) {\n" +
662+
" if (a instanceof B) {\n" +
663+
" @groovy.transform.ASTTest(phase=INSTRUCTION_SELECTION, value={\n" +
664+
" def type = node.rightExpression.objectExpression.getNodeMetaData(\n" +
665+
" org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE)\n" +
666+
" assert type.toString(false) == '<UnionType:A+B>'\n" +
667+
" })\n" +
668+
" def x = a.x\n" +
669+
" def y = a.y\n" +
670+
" }\n" +
671+
"}\n",
672+
};
673+
//@formatter:on
674+
675+
runConformTest(sources);
676+
}
677+
649678
@Test
650679
public void testTypeChecked5450() {
651680
//@formatter:off
@@ -2450,6 +2479,35 @@ public void testTypeChecked9762() {
24502479
runConformTest(sources, "[123]");
24512480
}
24522481

2482+
@Test
2483+
public void testTypeChecked9769() {
2484+
//@formatter:off
2485+
String[] sources = {
2486+
"Main.groovy",
2487+
"interface A {\n" +
2488+
" def m()\n" +
2489+
"}\n" +
2490+
"interface B extends A {\n" +
2491+
" def n()\n" +
2492+
"}\n" +
2493+
"@groovy.transform.TypeChecked\n" +
2494+
"void test(A a) {\n" +
2495+
" if (a instanceof B) {\n" +
2496+
" @groovy.transform.ASTTest(phase=INSTRUCTION_SELECTION, value={\n" +
2497+
" def type = node.rightExpression.objectExpression.getNodeMetaData(\n" +
2498+
" org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE)\n" +
2499+
" assert type.toString(false) == 'B'\n" + // not <UnionType:A+B>
2500+
" })\n" +
2501+
" def x = a.m()\n" +
2502+
" def y = a.n()\n" +
2503+
" }\n" +
2504+
"}\n",
2505+
};
2506+
//@formatter:on
2507+
2508+
runConformTest(sources);
2509+
}
2510+
24532511
@Test
24542512
public void testTypeChecked9821() {
24552513
//@formatter:off
@@ -5666,4 +5724,26 @@ public void testTypeChecked10624() {
56665724

56675725
runConformTest(sources);
56685726
}
5727+
5728+
@Test
5729+
public void testTypeChecked10651() {
5730+
//@formatter:off
5731+
String[] sources = {
5732+
"Main.groovy",
5733+
"@groovy.transform.TypeChecked\n" +
5734+
"void test(NodeType node) {\n" +
5735+
" node.each { child ->\n" +
5736+
" test(child)\n" +
5737+
" }\n" +
5738+
"}\n" +
5739+
"test()\n",
5740+
5741+
"NodeType.java",
5742+
"public abstract class NodeType<T extends NodeType<?>> implements Iterable<T> {\n" +
5743+
"}\n",
5744+
};
5745+
//@formatter:on
5746+
5747+
runConformTest(sources);
5748+
}
56695749
}

base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/ASTNode.java

+3
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,14 @@ public void copyNodeMetaData(ASTNode other) {
175175
* data under that key
176176
*/
177177
public void setNodeMetaData(Object key, Object value) {
178+
/* GRECLIPSE edit
178179
if (key==null) throw new GroovyBugError("Tried to set meta data with null key on "+this+".");
179180
if (metaDataMap == null) {
180181
metaDataMap = new ListHashMap();
181182
}
182183
Object old = metaDataMap.put(key,value);
184+
*/
185+
Object old = putNodeMetaData(key,value);
183186
if (old!=null) throw new GroovyBugError("Tried to overwrite existing meta data "+this+".");
184187
}
185188

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

+19-12
Original file line numberDiff line numberDiff line change
@@ -6985,23 +6985,31 @@ private SetterInfo(final ClassNode receiverType, final String name, final List<M
69856985

69866986
/**
69876987
* Wrapper for a Parameter so it can be treated like a VariableExpression
6988-
* and tracked in the ifElseForWhileAssignmentTracker.
6989-
* <p>
6990-
* This class purposely does not adhere to the normal equals and hashCode
6991-
* contract on the Object class and delegates those calls to the wrapped
6992-
* variable.
6988+
* and tracked in the {@code ifElseForWhileAssignmentTracker}.
69936989
*/
6994-
private static class ParameterVariableExpression extends VariableExpression {
6990+
private class ParameterVariableExpression extends VariableExpression {
69956991

69966992
private final Parameter parameter;
69976993

6998-
ParameterVariableExpression(Parameter parameter) {
6994+
ParameterVariableExpression(final Parameter parameter) {
69996995
super(parameter);
70006996
this.parameter = parameter;
6997+
/* GRECLIPSE edit -- GROOVY-10651
70016998
ClassNode inferred = parameter.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
70026999
if (inferred == null) {
70037000
parameter.setNodeMetaData(StaticTypesMarker.INFERRED_TYPE, parameter.getOriginType());
70047001
}
7002+
*/
7003+
ClassNode inferredType = getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
7004+
if (inferredType == null) {
7005+
inferredType = typeCheckingContext.controlStructureVariables.get(parameter); // for/catch/closure
7006+
if (inferredType == null) {
7007+
TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure();
7008+
if (enclosingClosure != null) inferredType = getTypeFromClosureArguments(parameter, enclosingClosure);
7009+
}
7010+
setNodeMetaData(StaticTypesMarker.INFERRED_TYPE, inferredType != null ? inferredType : parameter.getType());
7011+
}
7012+
// GRECLIPSE end
70057013
}
70067014

70077015
@Override
@@ -7030,14 +7038,13 @@ public <T> T getNodeMetaData(Object key) {
70307038
}
70317039

70327040
@Override
7041+
/* GRECLIPSE edit
70337042
public void setNodeMetaData(Object key, Object value) {
70347043
parameter.setNodeMetaData(key, value);
7035-
}
7036-
// GRECLIPSE add
7037-
@Override
7038-
public <T> T getNodeMetaData(Object key, java.util.function.Function<?, ? extends T> valFn) {
7044+
*/
7045+
public <T> T getNodeMetaData(Object key, Function<?, ? extends T> valFn) {
70397046
return parameter.getNodeMetaData(key, valFn);
7040-
}
70417047
// GRECLIPSE end
7048+
}
70427049
}
70437050
}

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

+14-6
Original file line numberDiff line numberDiff line change
@@ -6756,20 +6756,28 @@ private SetterInfo(final ClassNode receiverType, final String name, final List<M
67566756

67576757
/**
67586758
* Wrapper for a Parameter so it can be treated like a VariableExpression
6759-
* and tracked in the ifElseForWhileAssignmentTracker.
6760-
* <p>
6761-
* This class purposely does not adhere to the normal equals and hashCode
6762-
* contract on the Object class and delegates those calls to the wrapped
6763-
* variable.
6759+
* and tracked in the {@code ifElseForWhileAssignmentTracker}.
67646760
*/
6765-
private static class ParameterVariableExpression extends VariableExpression {
6761+
private class ParameterVariableExpression extends VariableExpression {
67666762

67676763
private final Parameter parameter;
67686764

67696765
ParameterVariableExpression(final Parameter parameter) {
67706766
super(parameter);
67716767
this.parameter = parameter;
6768+
/* GRECLIPSE edit -- GROOVY-10651
67726769
this.parameter.getNodeMetaData(INFERRED_TYPE, x -> parameter.getOriginType());
6770+
*/
6771+
ClassNode inferredType = getNodeMetaData(INFERRED_TYPE);
6772+
if (inferredType == null) {
6773+
inferredType = typeCheckingContext.controlStructureVariables.get(parameter); // for/catch/closure
6774+
if (inferredType == null) {
6775+
TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure();
6776+
if (enclosingClosure != null) inferredType = getTypeFromClosureArguments(parameter, enclosingClosure);
6777+
}
6778+
setNodeMetaData(INFERRED_TYPE, inferredType != null ? inferredType : parameter.getType()); // to parameter
6779+
}
6780+
// GRECLIPSE end
67736781
}
67746782

67756783
@Override

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

+14-6
Original file line numberDiff line numberDiff line change
@@ -5982,20 +5982,28 @@ private SetterInfo(final ClassNode receiverType, final String name, final List<M
59825982

59835983
/**
59845984
* Wrapper for a Parameter so it can be treated like a VariableExpression
5985-
* and tracked in the ifElseForWhileAssignmentTracker.
5986-
* <p>
5987-
* This class purposely does not adhere to the normal equals and hashCode
5988-
* contract on the Object class and delegates those calls to the wrapped
5989-
* variable.
5985+
* and tracked in the {@code ifElseForWhileAssignmentTracker}.
59905986
*/
5991-
private static class ParameterVariableExpression extends VariableExpression {
5987+
private class ParameterVariableExpression extends VariableExpression {
59925988

59935989
private final Parameter parameter;
59945990

59955991
ParameterVariableExpression(final Parameter parameter) {
59965992
super(parameter);
59975993
this.parameter = parameter;
5994+
/* GRECLIPSE edit -- GROOVY-10651
59985995
this.parameter.getNodeMetaData(INFERRED_TYPE, x -> parameter.getOriginType());
5996+
*/
5997+
ClassNode inferredType = getNodeMetaData(INFERRED_TYPE);
5998+
if (inferredType == null) {
5999+
inferredType = typeCheckingContext.controlStructureVariables.get(parameter); // for/catch/closure
6000+
if (inferredType == null) {
6001+
TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure();
6002+
if (enclosingClosure != null) inferredType = getTypeFromClosureArguments(parameter, enclosingClosure);
6003+
}
6004+
setNodeMetaData(INFERRED_TYPE, inferredType != null ? inferredType : parameter.getType()); // to parameter
6005+
}
6006+
// GRECLIPSE end
59996007
}
60006008

60016009
@Override

ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/inference/STCTypeLookup.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2021 the original author or authors.
2+
* Copyright 2009-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
2626
import org.codehaus.groovy.ast.ClassNode;
2727
import org.codehaus.groovy.ast.FieldNode;
2828
import org.codehaus.groovy.ast.MethodNode;
29+
import org.codehaus.groovy.ast.Parameter;
2930
import org.codehaus.groovy.ast.Variable;
3031
import org.codehaus.groovy.ast.expr.ClassExpression;
3132
import org.codehaus.groovy.ast.expr.ConstantExpression;
@@ -149,7 +150,7 @@ public TypeLookupResult lookupType(final Expression expr, final VariableScope sc
149150
}
150151

151152
@Override
152-
public TypeLookupResult lookupType(final FieldNode node, final VariableScope scope) {
153+
public TypeLookupResult lookupType(final FieldNode node, final VariableScope scope) {
153154
if (isEnabled) {
154155
Object inferredType = node.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
155156
if (inferredType instanceof ClassNode) {
@@ -170,6 +171,17 @@ public TypeLookupResult lookupType(final MethodNode node, final VariableScope sc
170171
return null;
171172
}
172173

174+
@Override
175+
public TypeLookupResult lookupType(final Parameter param, final VariableScope scope) {
176+
if (isEnabled) {
177+
Object inferredType = param.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
178+
if (inferredType instanceof ClassNode) {
179+
return new TypeLookupResult((ClassNode) inferredType, scope.getEnclosingTypeDeclaration(), param, TypeConfidence.INFERRED, scope);
180+
}
181+
}
182+
return null;
183+
}
184+
173185
//--------------------------------------------------------------------------
174186

175187
/**

0 commit comments

Comments
 (0)