groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sun...@apache.org
Subject groovy git commit: GROOVY-7753: regression of return type from ternary operator
Date Mon, 14 May 2018 11:21:45 GMT
Repository: groovy
Updated Branches:
  refs/heads/GROOVY_2_5_X 8341c825f -> 9d7c1bf1b


GROOVY-7753: regression of return type from ternary operator

(cherry picked from commit adfc7e3)


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

Branch: refs/heads/GROOVY_2_5_X
Commit: 9d7c1bf1b07d43c1efd16c9252b209d29d739ced
Parents: 8341c82
Author: sunlan <sunlan@apache.org>
Authored: Mon May 14 19:17:04 2018 +0800
Committer: sunlan <sunlan@apache.org>
Committed: Mon May 14 19:21:41 2018 +0800

----------------------------------------------------------------------
 .../stc/StaticTypeCheckingVisitor.java          | 48 +++++++---
 src/test/groovy/bugs/Groovy7753Bug.groovy       | 94 ++++++++++++++++++++
 2 files changed, 130 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/9d7c1bf1/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
----------------------------------------------------------------------
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 edddd7d..65ab493 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1985,15 +1985,35 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport
{
             super.visitConstructorOrMethod(node, isConstructor);
         }
         if (!isConstructor) {
-            returnAdder.visitMethod(node);
+            returnAdder.visitMethod(node); // return statement added after visitConstructorOrMethod
finished... we can not count these auto-generated return statements(GROOVY-7753), see `this.visitingReturnStatementCnt`
         }
         typeCheckingContext.popEnclosingMethod();
     }
 
+    // GROOVY-7753 return statement added after visitConstructorOrMethod finished... current
solution can not solve auto return
+    private int visitingReturnStatementCnt = 0;
+
     @Override
     public void visitReturnStatement(ReturnStatement statement) {
-        super.visitReturnStatement(statement);
-        returnListener.returnStatementAdded(statement);
+        visitingReturnStatementCnt++;
+        try {
+            super.visitReturnStatement(statement);
+            returnListener.returnStatementAdded(statement);
+        } finally {
+            visitingReturnStatementCnt--;
+        }
+    }
+
+    private ClassNode infer(ClassNode target, ClassNode source) {
+        DeclarationExpression virtualDecl = new DeclarationExpression(
+                varX("{target}", target),
+                Token.newSymbol(EQUAL, -1, -1),
+                varX("{source}", source)
+        );
+        virtualDecl.visit(this);
+        ClassNode newlyInferred = (ClassNode) virtualDecl.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
+
+        return !missesGenericsTypes(newlyInferred) ? newlyInferred : null;
     }
 
     protected ClassNode checkReturnType(final ReturnStatement statement) {
@@ -2022,15 +2042,11 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport
{
                 ClassNode inferred = previousType == null ? type : lowestUpperBound(type,
previousType);
                 if (implementsInterfaceOrIsSubclassOf(inferred, enclosingMethod.getReturnType()))
{
                     if (missesGenericsTypes(inferred)) {
-                        DeclarationExpression virtualDecl = new DeclarationExpression(
-                                varX("{target}", enclosingMethod.getReturnType()),
-                                Token.newSymbol(EQUAL, -1, -1),
-                                varX("{source}", type)
-                        );
-                        virtualDecl.setSourcePosition(statement);
-                        virtualDecl.visit(this);
-                        ClassNode newlyInferred = (ClassNode) virtualDecl.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
-                        if (!missesGenericsTypes(newlyInferred)) type = newlyInferred;
+                        ClassNode newlyInferred = infer(enclosingMethod.getReturnType(),
type);
+
+                        if (null != newlyInferred) {
+                            type = newlyInferred;
+                        }
                     } else {
                         checkTypeGenerics(enclosingMethod.getReturnType(), inferred, expression);
                     }
@@ -3225,6 +3241,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport
{
                         }
                         if (typeCheckMethodsWithGenericsOrFail(chosenReceiver.getType(),
args, mn.get(0), call)) {
                             returnType = adjustWithTraits(directMethodCallCandidate, chosenReceiver.getType(),
args, returnType);
+
+                            if (1 == visitingReturnStatementCnt) { // the method call is
within return statement, we can try to infer type further
+                                ClassNode inferredType = infer(returnType, typeCheckingContext.getEnclosingMethod().getReturnType());
+                                if (null != inferredType) {
+                                    returnType = inferredType;
+                                }
+                            }
+
                             storeType(call, returnType);
                             storeTargetMethod(call, directMethodCallCandidate);
                             String data = chosenReceiver.getData();

http://git-wip-us.apache.org/repos/asf/groovy/blob/9d7c1bf1/src/test/groovy/bugs/Groovy7753Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/bugs/Groovy7753Bug.groovy b/src/test/groovy/bugs/Groovy7753Bug.groovy
new file mode 100644
index 0000000..a650444
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy7753Bug.groovy
@@ -0,0 +1,94 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.bugs
+
+import groovy.transform.NotYetImplemented
+
+class Groovy7753Bug extends GroovyTestCase {
+    @NotYetImplemented
+    void testGroovy7753() {
+        assertScript '''
+        @groovy.transform.Field
+        String x = "X"
+        
+        @groovy.transform.CompileStatic
+        public List<String> getStrings() {
+            x ? [x] : Collections.emptyList()
+        }
+        
+        getStrings()
+        '''
+    }
+
+    void testGroovy7753WithReturn() {
+        assertScript '''
+        @groovy.transform.Field
+        String x = "X"
+        
+        @groovy.transform.CompileStatic
+        public List<String> getStrings() {
+            return x ? [x] : Collections.emptyList()
+        }
+        
+        getStrings()
+        '''
+    }
+
+    void testGroovy7753WithReturn2() {
+        assertScript '''
+        @groovy.transform.Field
+        String x = "X"
+        
+        @groovy.transform.CompileStatic
+        public List<String> getStrings() {
+            return x ? Collections.emptyList() : [x]
+        }
+        
+        getStrings()
+        '''
+    }
+
+    void test2() {
+        assertScript '''
+        @groovy.transform.Field
+        String x = "X"
+        
+        @groovy.transform.CompileStatic
+        public List<String> getStrings() {
+            Collections.emptyList()
+        }
+        
+        getStrings()
+        '''
+    }
+
+    void test3() {
+        assertScript '''
+        @groovy.transform.Field
+        String x = "X"
+        
+        @groovy.transform.CompileStatic
+        public List<String> getStrings() {
+            [x]
+        }
+        
+        getStrings()
+        '''
+    }
+}


Mime
View raw message