groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pa...@apache.org
Subject groovy git commit: GROOVY-8260: Static compilation requires casting inside instanceof check (handle additional cases)
Date Fri, 29 Sep 2017 12:38:19 GMT
Repository: groovy
Updated Branches:
  refs/heads/master fbb5a1ec5 -> 26d11337c


GROOVY-8260: Static compilation requires casting inside instanceof check (handle additional
cases)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/26d11337
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/26d11337
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/26d11337

Branch: refs/heads/master
Commit: 26d11337cfa4d66eed6eca1f99f5a5309427ebd9
Parents: fbb5a1e
Author: paulk <paulk@asert.com.au>
Authored: Fri Sep 29 22:35:54 2017 +1000
Committer: paulk <paulk@asert.com.au>
Committed: Fri Sep 29 22:35:54 2017 +1000

----------------------------------------------------------------------
 .../stc/StaticTypeCheckingVisitor.java          | 51 ++++++++++++++--
 .../groovy/transform/stc/MiscSTCTest.groovy     | 63 +++++++++++++++++++-
 2 files changed, 105 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/26d11337/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 807449a..bda414b 100644
--- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -480,7 +480,30 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport
{
             }
         }
 
-        if (! (vexp.getAccessedVariable() instanceof DynamicVariable)) return;
+        if (!(vexp.getAccessedVariable() instanceof DynamicVariable)) {
+            VariableExpression variable = null;
+            if (vexp.getAccessedVariable() instanceof Parameter) {
+                variable = new ParameterVariableExpression((Parameter) vexp.getAccessedVariable());
+            } else if (vexp.getAccessedVariable() instanceof VariableExpression) {
+                variable = (VariableExpression) vexp.getAccessedVariable();
+            }
+            if (variable != null) {
+                ClassNode inferredType = getInferredTypeFromTempInfo(variable, variable.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE));
+                if (inferredType != null && !inferredType.getName().equals("java.lang.Object"))
{
+                    if (typeCheckingContext.getEnclosingBinaryExpression() != null) {
+                        // TODO narrow this down to assignment
+                        if (typeCheckingContext.getEnclosingBinaryExpression().getRightExpression()
== vexp) {
+                            vexp.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, inferredType);
+                        }
+                    } else {
+                        // stash away type info that will be lost later to handle case
+                        // where this expression has return added later - piggy back on existing
key
+                        vexp.putNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE, inferredType);
+                    }
+                }
+            }
+            return;
+        }
 
         // a dynamic variable is either an undeclared variable
         // or a member of a class used in a 'with'
@@ -1833,6 +1856,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport
{
         if (typeCheckingContext.getEnclosingClosure()!=null) {
             return type;
         }
+        if ((expression instanceof VariableExpression) && hasInferredReturnType(expression))
{
+            type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
+        }
         MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod();
         if (enclosingMethod != null && typeCheckingContext.getEnclosingClosure()==null)
{
             if (!enclosingMethod.isVoidMethod()
@@ -3205,7 +3231,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport
{
         int depth = typeCheckingContext.temporaryIfBranchTypeInformation.size();
         while (classNodes == null && depth > 0) {
             final Map<Object, List<ClassNode>> tempo = typeCheckingContext.temporaryIfBranchTypeInformation.get(--depth);
-            Object key = extractTemporaryTypeInfoKey(objectExpression);
+            Object key = objectExpression instanceof ParameterVariableExpression
+                    ? ((ParameterVariableExpression) objectExpression).parameter
+                    : extractTemporaryTypeInfoKey(objectExpression);
             classNodes = tempo.get(key);
         }
         return classNodes;
@@ -3393,6 +3421,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport
{
         typeCheckingContext.popTemporaryTypeInfo();
         falseExpression.visit(this);
         ClassNode resultType;
+        ClassNode typeOfFalse = getType(falseExpression);
+        ClassNode typeOfTrue = getType(trueExpression);
+        if (hasInferredReturnType(falseExpression)) {
+            typeOfFalse = falseExpression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
+        }
+        if (hasInferredReturnType(trueExpression)) {
+            typeOfTrue = trueExpression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
+        }
         if (isNullConstant(trueExpression) || isNullConstant(falseExpression)) {
             BinaryExpression enclosingBinaryExpression = typeCheckingContext.getEnclosingBinaryExpression();
             if (enclosingBinaryExpression != null && enclosingBinaryExpression.getRightExpression()==expression)
{
@@ -3400,20 +3436,23 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport
{
             } else if (isNullConstant(trueExpression) && isNullConstant(falseExpression))
{
                 resultType = OBJECT_TYPE;
             } else if (isNullConstant(trueExpression)) {
-                resultType = wrapTypeIfNecessary(getType(falseExpression));
+                resultType = wrapTypeIfNecessary(typeOfFalse);
             } else {
-                resultType = wrapTypeIfNecessary(getType(trueExpression));
+                resultType = wrapTypeIfNecessary(typeOfTrue);
             }
         } else {
             // store type information
-            final ClassNode typeOfTrue = getType(trueExpression);
-            final ClassNode typeOfFalse = getType(falseExpression);
             resultType = lowestUpperBound(typeOfTrue, typeOfFalse);
         }
         storeType(expression, resultType);
         popAssignmentTracking(oldTracker);
     }
 
+    private boolean hasInferredReturnType(Expression expression) {
+        ClassNode type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
+        return type != null && !type.getName().equals("java.lang.Object");
+    }
+
     @Override
     public void visitTryCatchFinally(final TryCatchStatement statement) {
         final List<CatchStatement> catchStatements = statement.getCatchStatements();

http://git-wip-us.apache.org/repos/asf/groovy/blob/26d11337/src/test/groovy/transform/stc/MiscSTCTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/transform/stc/MiscSTCTest.groovy b/src/test/groovy/transform/stc/MiscSTCTest.groovy
index 13bdb40..fadac0a 100644
--- a/src/test/groovy/transform/stc/MiscSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MiscSTCTest.groovy
@@ -22,8 +22,6 @@ import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor
 
 /**
  * Unit tests for static type checking : miscellaneous tests.
- *
- * @author Cedric Champeau
  */
 class MiscSTCTest extends StaticTypeCheckingTestCase {
 
@@ -272,8 +270,67 @@ class MiscSTCTest extends StaticTypeCheckingTestCase {
         }
     }
 
-    public static class MiscSTCTestSupport {
+    static class MiscSTCTestSupport {
         static def foo() { '123' }
     }
+
+    void testTernaryParam() {
+        assertScript '''
+            Date ternaryParam(Object input) {
+                input instanceof Date ? input : null
+            }
+            def d = new Date()
+            assert ternaryParam(42) == null
+            assert ternaryParam('foo') == null
+            assert ternaryParam(d) == d
+        '''
+    }
+
+    void testTernaryLocalVar() {
+        assertScript '''
+            Date ternaryLocalVar(Object input) {
+                Object copy = input
+                copy instanceof Date ? copy : null
+            }
+            def d = new Date()
+            assert ternaryLocalVar(42) == null
+            assert ternaryLocalVar('foo') == null
+            assert ternaryLocalVar(d) == d
+        '''
+    }
+
+    void testIfThenElseParam() {
+        assertScript '''
+            Date ifThenElseParam(Object input) {
+                if (input instanceof Date) {
+                    input
+                } else {
+                    null
+                }
+            }
+            def d = new Date()
+            assert ifThenElseParam(42) == null
+            assert ifThenElseParam('foo') == null
+            assert ifThenElseParam(d) == d
+        '''
+    }
+
+    void testIfThenElseLocalVar() {
+        assertScript '''
+            Date ifThenElseLocalVar(Object input) {
+                Date result
+                if (input instanceof Date) {
+                    result = input
+                } else {
+                    result = null
+                }
+                result
+            }
+            def d = new Date()
+            assert ifThenElseLocalVar(42) == null
+            assert ifThenElseLocalVar('foo') == null
+            assert ifThenElseLocalVar(d) == d
+        '''
+    }
 }
 


Mime
View raw message