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/07/04 15:04:20 UTC
[groovy] 01/01: GROOVY-9607: chase down param, local, field,
... for variable expression
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-9607
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 457d709187dd0949efa48b4d7c2bc9ccdea0279f
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Jul 4 10:04:02 2020 -0500
GROOVY-9607: chase down param, local, field, ... for variable expression
---
.../classgen/asm/sc/StaticTypesTypeChooser.java | 34 +++++++-----
src/test/groovy/bugs/Groovy9607.groovy | 64 ++++++++++++++++++++++
2 files changed, 83 insertions(+), 15 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesTypeChooser.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesTypeChooser.java
index 534959c..554a8cd 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesTypeChooser.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesTypeChooser.java
@@ -18,23 +18,22 @@
*/
package org.codehaus.groovy.classgen.asm.sc;
+import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.Variable;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.VariableExpression;
-import org.codehaus.groovy.classgen.AsmClassGenerator;
import org.codehaus.groovy.classgen.asm.StatementMetaTypeChooser;
import org.codehaus.groovy.transform.stc.StaticTypesMarker;
/**
- * A {@link org.codehaus.groovy.classgen.asm.TypeChooser} which reads type information from node metadata
- * generated by the {@link groovy.transform.CompileStatic} annotation.
+ * A {@link org.codehaus.groovy.classgen.asm.TypeChooser TypeChooser} which reads
+ * type information from node metadata generated by the static type checker.
*/
public class StaticTypesTypeChooser extends StatementMetaTypeChooser {
@Override
public ClassNode resolveType(final Expression exp, final ClassNode current) {
- Expression target = exp instanceof VariableExpression ? getTarget((VariableExpression) exp) : exp;
+ ASTNode target = getTarget(exp); // see GROOVY-9344, GROOVY-9607
ClassNode inferredType = target.getNodeMetaData(StaticTypesMarker.DECLARATION_INFERRED_TYPE);
if (inferredType == null) {
@@ -45,7 +44,7 @@ public class StaticTypesTypeChooser extends StatementMetaTypeChooser {
}
// AsmClassGenerator may create "this" expressions that the type checker knows nothing about
- if (AsmClassGenerator.isThisExpression(target)) {
+ if (target instanceof VariableExpression && ((VariableExpression) target).isThisExpression()) {
return current;
}
@@ -53,17 +52,22 @@ public class StaticTypesTypeChooser extends StatementMetaTypeChooser {
}
/**
- * The inferred type, in case of a variable expression, can be set on the accessed variable, so we take it instead
- * of the facade one.
+ * The inferred type, in case of a variable expression, can be set on the
+ * accessed variable, so we take it instead of the reference.
*
- * @param ve the variable expression for which to return the target expression
- * @return the target variable expression
+ * @param exp the expression for which to return the target expression
+ * @return the target node
*/
- private static VariableExpression getTarget(final VariableExpression ve) {
- Variable variable = ve.getAccessedVariable();
- if (variable != ve && variable instanceof VariableExpression) {
- return getTarget((VariableExpression) variable);
+ private static ASTNode getTarget(final Expression exp) {
+ ASTNode target = exp;
+ while (target instanceof VariableExpression) {
+ Object var = ((VariableExpression) target).getAccessedVariable();
+ if (var instanceof ASTNode && var != target) {
+ target = (ASTNode) var;
+ } else {
+ break;
+ }
}
- return ve;
+ return target;
}
}
diff --git a/src/test/groovy/bugs/Groovy9607.groovy b/src/test/groovy/bugs/Groovy9607.groovy
new file mode 100644
index 0000000..7f10357
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9607.groovy
@@ -0,0 +1,64 @@
+/*
+ * 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 org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+final class Groovy9607 {
+
+ @Test
+ void testClosureSharedVariableInferredType1() {
+ assertScript '''
+ static help(Runnable runner) {
+ runner.run()
+ }
+ @groovy.transform.CompileStatic
+ void test(item, MetaProperty prop) {
+ def name = prop.name
+ help(new Runnable() {
+ void run() {
+ assert item[name] == 'bar' // STC throws GBE if 'name' to infers as Object
+ }
+ })
+ }
+ test([foo:'bar'], new MetaBeanProperty('foo', null, null, null))
+ '''
+ }
+
+ @Test
+ void testClosureSharedVariableInferredType2() {
+ assertScript '''
+ static help(Runnable runner) {
+ runner.run()
+ }
+ @groovy.transform.CompileStatic
+ void test(item, name, MetaProperty prop) {
+ name = prop.name
+ help(new Runnable() {
+ void run() {
+ assert item[name] == 'bar' // STC throws GBE if 'name' to infers as Object
+ }
+ })
+ }
+ test([foo:'bar'], null, new MetaBeanProperty('foo', null, null, null))
+ '''
+ }
+}