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 2022/01/31 18:00:22 UTC
[groovy] 03/05: GROOVY-7686: AIC: place local variable references above super ctor call
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 8f4baead5215c96b6cd08d4c218a11e6d9f0c849
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Mar 17 09:00:00 2021 -0500
GROOVY-7686: AIC: place local variable references above super ctor call
Conflicts:
src/main/java/org/codehaus/groovy/classgen/Verifier.java
src/test/gls/innerClass/InnerClassTest.groovy
---
.../org/codehaus/groovy/classgen/Verifier.java | 36 +++++++++++++++++++--
src/test/gls/innerClass/InnerClassTest.groovy | 37 ++++++++++++++++++++++
2 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index 4a7e627..14e6e19 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -81,6 +81,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
@@ -1050,8 +1051,6 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- statements.addAll(node.getObjectInitializerStatements());
-
Statement code = constructorNode.getCode();
BlockStatement block = new BlockStatement();
List<Statement> otherStatements = block.getStatements();
@@ -1066,6 +1065,12 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
// it is super(..) since this(..) is already covered
otherStatements.remove(0);
statements.add(0, firstStatement);
+ // GROOVY-7686: place local variable references above super ctor call
+ if (node instanceof InnerClassNode && ((InnerClassNode) node).isAnonymous()) {
+ for (Statement stmt : extractVariableReferenceInitializers(statements)) {
+ statements.add(0, stmt);
+ }
+ }
}
Statement stmtThis$0 = getImplicitThis$0StmtIfInnerClass(otherStatements);
if (stmtThis$0 != null) {
@@ -1073,8 +1078,12 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
// that uses this$0, it needs to bubble up before the super call itself (GROOVY-4471)
statements.add(0, stmtThis$0);
}
+ statements.addAll(node.getObjectInitializerStatements());
statements.addAll(otherStatements);
+ } else {
+ statements.addAll(node.getObjectInitializerStatements());
}
+
BlockStatement newBlock = new BlockStatement(statements, block.getVariableScope());
newBlock.setSourcePosition(block);
constructorNode.setCode(newBlock);
@@ -1142,6 +1151,29 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return null;
}
+ private static List<Statement> extractVariableReferenceInitializers(List<Statement> statements) {
+ List<Statement> localVariableReferences = new ArrayList<>();
+ for (ListIterator<Statement> it = statements.listIterator(1); it.hasNext(); ) {
+ // the first statement is the super constructor call ^
+
+ Statement stmt = it.next();
+ if (stmt instanceof ExpressionStatement
+ && ((ExpressionStatement) stmt).getExpression() instanceof BinaryExpression) {
+ BinaryExpression expr = (BinaryExpression) ((ExpressionStatement) stmt).getExpression();
+
+ if (expr.getOperation().getType() == Types.ASSIGN
+ && expr.getLeftExpression() instanceof FieldExpression
+ && expr.getLeftExpression().getType().equals(ClassHelper.REFERENCE_TYPE)
+ && (((FieldExpression) expr.getLeftExpression()).getField().getModifiers() & Opcodes.ACC_SYNTHETIC) != 0
+ /* also could check if the right expression is a variable expression that references ctor parameter */) {
+ localVariableReferences.add(stmt);
+ it.remove();
+ }
+ }
+ }
+ return localVariableReferences;
+ }
+
protected void addFieldInitialization(List list, List staticList, FieldNode fieldNode,
boolean isEnumClassNode, List initStmtsAfterEnumValuesInit, Set explicitStaticPropsInEnum) {
Expression expression = fieldNode.getInitialExpression();
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 3a3a73c..73e7fb7 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -1001,6 +1001,43 @@ final class InnerClassTest {
'''
}
+ @Test // GROOVY-7686
+ void testReferencedVariableInAIC3() {
+ assertScript '''
+ abstract class A {
+ A() {
+ m()
+ }
+ abstract void m();
+ }
+ void test() {
+ def v = false
+ def a = new A() {
+ // run by super ctor
+ @Override void m() {
+ assert v != null
+ }
+ }
+ v = true
+ a.m()
+ }
+ test()
+ '''
+ }
+
+ @Test // GROOVY-5754
+ void testResolveInnerOfSuperType() {
+ assertScript '''
+ interface I { class C { } }
+
+ class Outer implements I {
+ static class Inner extends C {}
+ }
+
+ print I.C
+ '''
+ }
+
@Test // GROOVY-5989
void testReferenceToOuterClassNestedInterface() {
assertScript '''