You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2020/09/25 18:16:45 UTC
[groovy] 02/02: GROOVY-9454: STC: check for instanceof type before
using the field type
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit e9173a9b9115721aba818ba9caa4b7f7339a7bec
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Sep 25 13:11:48 2020 -0500
GROOVY-9454: STC: check for instanceof type before using the field type
---
.../transform/stc/StaticTypeCheckingVisitor.java | 7 +++-
.../transform/stc/TypeInferenceSTCTest.groovy | 38 ++++++++++++++++++----
2 files changed, 38 insertions(+), 7 deletions(-)
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 e3d802e..d66d3a0 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -643,7 +643,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
} else {
checkOrMarkPrivateAccess(vexp, fieldNode, isLHSOfEnclosingAssignment(vexp));
- storeType(vexp, getType(vexp));
+ ClassNode inferredType = getInferredTypeFromTempInfo(vexp, null);
+ if (inferredType != null && !inferredType.equals(OBJECT_TYPE)) {
+ vexp.putNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE, inferredType);
+ } else {
+ storeType(vexp, getType(vexp));
+ }
}
}
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index 74af5b2..e81e5d5 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -18,16 +18,16 @@
*/
package groovy.transform.stc
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.MethodNode
-import org.codehaus.groovy.control.customizers.CompilationCustomizer
+import org.codehaus.groovy.ast.tools.WideningCategories
+import org.codehaus.groovy.classgen.GeneratorContext
import org.codehaus.groovy.control.CompilationUnit
import org.codehaus.groovy.control.CompilePhase
import org.codehaus.groovy.control.SourceUnit
-import org.codehaus.groovy.classgen.GeneratorContext
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.control.customizers.CompilationCustomizer
import org.codehaus.groovy.transform.stc.StaticTypesMarker
-import org.codehaus.groovy.ast.tools.WideningCategories
/**
* Unit tests for static type checking : type inference.
@@ -143,6 +143,32 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
''', 'Cannot find matching method java.lang.Object#toUpperCase()'
}
+ // GROOVY-9454
+ void testInstanceOfOnGenericProperty() {
+ assertScript '''
+ interface Face {
+ }
+ class Impl implements Face {
+ String something
+ }
+ class Task<R extends Face> implements java.util.concurrent.Callable<String> {
+ R request
+ @Override
+ String call() {
+ if (request instanceof Impl) {
+ def thing = request.something // No such property: something for class: R
+ def lower = thing.toLowerCase()
+ } else {
+ // ...
+ return null
+ }
+ }
+ }
+ def task = new Task<Impl>(request: new Impl(something: 'Hello World'))
+ assert task.call() == 'hello world'
+ '''
+ }
+
void testMultipleInstanceOf() {
assertScript '''
class A {
@@ -482,7 +508,7 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
keys*.toUpperCase()
values*.toUpperCase()
'''
-
+
shouldFailWithMessages '''
List values = [x:1,y:2,z:3]*.value
values*.toUpperCase()