This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new b52c852 GROOVY-9821: STC: check "T" from "? extends T" for spread
property (closes #1427)
b52c852 is described below
commit b52c852d67435eea3ff1b4ed15a0e12e1299b7af
Author: Eric Milles <[email protected]>
AuthorDate: Thu Nov 19 15:29:06 2020 -0600
GROOVY-9821: STC: check "T" from "? extends T" for spread property (closes
#1427)
---
.../transform/stc/StaticTypeCheckingSupport.java | 2 +-
.../transform/stc/StaticTypeCheckingVisitor.java | 41 +++++++++++-----------
.../groovy/transform/stc/GenericsSTCTest.groovy | 32 +++++++++++++++++
3 files changed, 54 insertions(+), 21 deletions(-)
diff --git
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 126afb0..5034dec 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1900,7 +1900,7 @@ public abstract class StaticTypeCheckingSupport {
return newBound;
}
- private static ClassNode getCombinedBoundType(final GenericsType
genericsType) {
+ static ClassNode getCombinedBoundType(final GenericsType genericsType) {
// TODO: this method should really return some kind of meta ClassNode
// representing the combination of all bounds. The code here, just
picks
// something out to be able to proceed and is not actually correct
diff --git
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 115988c..136f7fe 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -189,6 +189,7 @@ import static
org.codehaus.groovy.ast.tools.GeneralUtils.constX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.getSetterName;
import static org.codehaus.groovy.ast.tools.GeneralUtils.isOrImplements;
import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
import static org.codehaus.groovy.ast.tools.GenericsUtils.toGenericTypesString;
@@ -246,6 +247,7 @@ import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findDG
import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findSetters;
import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findTargetVariable;
import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.fullyResolveType;
+import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getCombinedBoundType;
import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getCorrectedClassNode;
import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getGenericsWithoutArray;
import static
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getOperationName;
@@ -899,12 +901,10 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
private void validateResourceInARM(final BinaryExpression expression,
final ClassNode lType) {
- if (expression instanceof DeclarationExpression) {
- if (TryCatchStatement.isResource(expression)) {
- if (!lType.implementsInterface(AUTOCLOSEABLE_TYPE)) {
- addError("Resource[" + lType.getName() + "] in ARM should
be of type AutoCloseable", expression);
- }
- }
+ if (expression instanceof DeclarationExpression
+ && TryCatchStatement.isResource(expression)
+ && !isOrImplements(lType, AUTOCLOSEABLE_TYPE)) {
+ addError("Resource[" + lType.getName() + "] in ARM should be of
type AutoCloseable", expression);
}
}
@@ -1660,19 +1660,20 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
private ClassNode getTypeForSpreadExpression(final ClassNode testClass,
final ClassNode objectExpressionType, final PropertyExpression pexp) {
- if (!pexp.isSpreadSafe()) return null;
- MethodCallExpression mce = callX(varX("_", testClass), "iterator",
ArgumentListExpression.EMPTY_ARGUMENTS);
- mce.setImplicitThis(false);
- mce.visit(this);
- ClassNode callType = getType(mce);
- if (!implementsInterfaceOrIsSubclassOf(callType, Iterator_TYPE))
return null;
- GenericsType[] types = callType.getGenericsTypes();
- ClassNode contentType = OBJECT_TYPE;
- if (types != null && types.length == 1) contentType =
types[0].getType();
- PropertyExpression subExp = new PropertyExpression(varX("{}",
contentType), pexp.getPropertyAsString());
- AtomicReference<ClassNode> result = new AtomicReference<>();
- if (existsProperty(subExp, true, new PropertyLookupVisitor(result))) {
- return extension.buildListType(result.get());
+ if (pexp.isSpreadSafe()) {
+ MethodCallExpression mce = callX(varX("_", testClass), "iterator");
+ mce.setImplicitThis(false);
+ mce.visit(this);
+ ClassNode iteratorType = getType(mce);
+ if (isOrImplements(iteratorType, Iterator_TYPE)) {
+ GenericsType[] gts = iteratorType.getGenericsTypes();
+ ClassNode itemType = (gts != null && gts.length == 1 ?
getCombinedBoundType(gts[0]) : OBJECT_TYPE);
+
+ AtomicReference<ClassNode> propertyType = new
AtomicReference<>();
+ if (existsProperty(propX(varX("{}", itemType),
pexp.getProperty()), true, new PropertyLookupVisitor(propertyType))) {
+ return extension.buildListType(propertyType.get());
+ }
+ }
}
return null;
}
@@ -2228,7 +2229,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
private boolean looksLikeNamedArgConstructor(final ClassNode receiver,
final ClassNode[] argumentTypes) {
if (argumentTypes.length == 1 || argumentTypes.length == 2 &&
argumentTypes[0].equals(receiver.getOuterClass())) {
- return argumentTypes[argumentTypes.length -
1].implementsInterface(MAP_TYPE);
+ return isOrImplements(argumentTypes[argumentTypes.length - 1],
MAP_TYPE);
}
return false;
}
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 345252b..6cc3a86 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -2232,6 +2232,38 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase
{
}
null
'''
+
+ // GROOVY-9821
+ config.with {
+ targetDirectory = File.createTempDir()
+ jointCompilationOptions = [memStub: true]
+ }
+ File parentDir = File.createTempDir()
+ try {
+ def a = new File(parentDir, 'Types.java')
+ a.write '''
+ interface A {
+ java.util.Collection<? extends B> getBees();
+ }
+ interface B {
+ Object getC();
+ }
+ '''
+ def b = new File(parentDir, 'Script.groovy')
+ b.write '''
+ def test(A a) {
+ a.bees*.c
+ }
+ '''
+
+ def loader = new GroovyClassLoader(this.class.classLoader)
+ def cu = new JavaAwareCompilationUnit(config, loader)
+ cu.addSources(a, b)
+ cu.compile()
+ } finally {
+ parentDir.deleteDir()
+ config.targetDirectory.deleteDir()
+ }
}
// GROOVY-7804