You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/09/12 16:26:13 UTC
[groovy] branch GROOVY_3_0_X updated (32d5dcc -> f7b8601)
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a change to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git.
from 32d5dcc GROOVY-9738: Bump xstream to 1.4.13
new d093ed3 GROOVY-9672: replace "this" argument with "Type" for static super call
new 1837fff GROOVY-9691: don't make SMCE within closure outside of special ctor call
new c3ada8f fix parameter generics and modifiers
new 6a4f4c4 minor refactor
new 1c07ed8 GROOVY-8000: pass interface with adjusted generics to recursive collect
new c77a608 minor refactor
new 1591c02 minor refactor
new 6a10018 GROOVY-9699: SC: reposition checkOrMarkPrivateAccess for field reference
new 0d7f98f minor refactor
new 80400b1 GROOVY-9700: SC: transform variable assignment to direct setter call
new d26be15 GROOVY-9702: source retention for @ASTTest and improved AST modification (closes #1352)
new d257cbf promote early returns, remove extra calls, and other minor edits
new 33e1277 minor refactor
new 0357ffa reuse CachedField#getProperty
new 68ded92 GROOVY-9570: collect context generics starting at innermost class/method
new 4c324a9 reduce use of dynamic features
new 800badd minor refactor
new 3184da9 GROOVY-9704: load minus one as long integer (closes #1358)
new f7b8601 reduce impact of makeAccessible(AccessibleObject) (closes #1357)
The 19 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
src/main/groovy/groovy/grape/GrapeIvy.groovy | 506 +++++++++------------
.../groovy/transform/ASTTestTransformation.groovy | 72 ++-
.../tailrec/VariableExpressionReplacer.groovy | 2 +-
src/main/java/groovy/transform/ASTTest.java | 13 +-
.../codehaus/groovy/ast/expr/FieldExpression.java | 10 +-
.../org/codehaus/groovy/classgen/Verifier.java | 401 ++++++++--------
.../groovy/classgen/asm/UnaryExpressionHelper.java | 2 +-
.../asm/sc/StaticPropertyAccessHelper.java | 20 +-
...icTypesBinaryExpressionMultiTypeDispatcher.java | 43 +-
.../asm/sc/StaticTypesUnaryExpressionHelper.java | 134 +++---
.../groovy/control/StaticImportVisitor.java | 28 +-
.../codehaus/groovy/reflection/CachedField.java | 64 +--
.../groovy/reflection/ReflectionUtils.java | 92 ++--
.../callsite/GetEffectivePogoFieldSite.java | 58 +--
.../callsite/GetEffectivePojoFieldSite.java | 36 +-
.../transform/sc/TemporaryVariableExpression.java | 6 +-
.../transformers/BinaryExpressionTransformer.java | 61 ++-
.../transform/stc/StaticTypeCheckingSupport.java | 12 +-
.../transform/stc/StaticTypeCheckingVisitor.java | 195 ++++----
.../transform/trait/SuperCallTraitTransformer.java | 32 +-
.../codehaus/groovy/transform/trait/Traits.java | 21 +-
src/spec/test/DifferencesFromJavaTest.groovy | 63 ++-
src/spec/test/TestingASTTransformsTest.groovy | 5 -
src/test/gls/innerClass/InnerClassTest.groovy | 6 -
src/test/groovy/IllegalAccessScenariosTest.groovy | 41 --
src/test/groovy/IllegalAccessTests.groovy | 88 ++++
src/test/groovy/bugs/Groovy8002.groovy | 1 -
src/test/groovy/bugs/Groovy8169.groovy | 1 -
.../bugs/{Groovy3719.groovy => Groovy8816.groovy} | 15 +-
src/test/groovy/bugs/Groovy8816Bug.groovy | 38 --
.../bugs/{Groovy8648.groovy => Groovy9691.groovy} | 36 +-
.../groovy/bugs/ImportNodeLineNumberTest.groovy | 48 +-
.../transform/AnnotationCollectorLegacyTest.groovy | 12 +-
.../transform/AnnotationCollectorTest.groovy | 8 +-
.../stc/ClosureParamTypeInferenceSTCTest.groovy | 24 +
.../transform/stc/UnaryOperatorSTCTest.groovy | 276 +++++++++--
.../sc/FieldsAndPropertiesStaticCompileTest.groovy | 337 ++++++++------
.../asm/sc/UnaryOperatorStaticCompileTest.groovy | 26 +-
.../classgen/asm/sc/bugs/Groovy7361Bug.groovy | 64 ++-
.../groovy/transform/AutoFinalTransformTest.groovy | 8 +-
.../groovy/transform/DelegateTransformTest.groovy | 17 +-
.../transform/TupleConstructorTransformTest.groovy | 2 -
.../traitx/TraitASTTransformationTest.groovy | 176 ++++++-
43 files changed, 1737 insertions(+), 1363 deletions(-)
delete mode 100644 src/test/groovy/IllegalAccessScenariosTest.groovy
create mode 100644 src/test/groovy/IllegalAccessTests.groovy
copy src/test/groovy/bugs/{Groovy3719.groovy => Groovy8816.groovy} (71%)
delete mode 100644 src/test/groovy/bugs/Groovy8816Bug.groovy
copy src/test/groovy/bugs/{Groovy8648.groovy => Groovy9691.groovy} (60%)
[groovy] 17/19: minor refactor
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 800badd1e88a40773c92f0ef7d2e12c6b9854b3b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Sep 1 00:42:34 2020 +0800
minor refactor
(cherry picked from commit 03c21a3190b52fe3e9c868fd93b3250eb38e875a)
---
.../groovy/classgen/asm/UnaryExpressionHelper.java | 2 +-
.../asm/sc/StaticTypesUnaryExpressionHelper.java | 134 +++++-----
.../transform/stc/UnaryOperatorSTCTest.groovy | 278 ++++++++++++++++++---
.../asm/sc/UnaryOperatorStaticCompileTest.groovy | 26 +-
4 files changed, 322 insertions(+), 118 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/UnaryExpressionHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/UnaryExpressionHelper.java
index 9ed2792..842ea6d 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/UnaryExpressionHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/UnaryExpressionHelper.java
@@ -41,7 +41,7 @@ public class UnaryExpressionHelper {
static final MethodCaller unaryMinus = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "unaryMinus");
static final MethodCaller bitwiseNegate = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "bitwiseNegate");
- private final WriterController controller;
+ protected final WriterController controller;
public UnaryExpressionHelper(final WriterController controller) {
this.controller = controller;
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java
index b1986e8..a46bf94 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java
@@ -25,7 +25,6 @@ import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.NotExpression;
import org.codehaus.groovy.ast.expr.UnaryMinusExpression;
import org.codehaus.groovy.ast.expr.UnaryPlusExpression;
-import org.codehaus.groovy.classgen.BytecodeExpression;
import org.codehaus.groovy.classgen.asm.TypeChooser;
import org.codehaus.groovy.classgen.asm.UnaryExpressionHelper;
import org.codehaus.groovy.classgen.asm.WriterController;
@@ -38,66 +37,59 @@ import static org.codehaus.groovy.ast.ClassHelper.char_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.double_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.float_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.int_TYPE;
-import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveType;
import static org.codehaus.groovy.ast.ClassHelper.long_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.short_TYPE;
import static org.codehaus.groovy.ast.tools.GeneralUtils.bytecodeX;
/**
- * An unary expression helper which generates optimized bytecode depending on
- * the current type on top of the operand stack.
+ * An expression helper which generates optimized bytecode depending on the
+ * current type on top of the operand stack.
*/
public class StaticTypesUnaryExpressionHelper extends UnaryExpressionHelper implements Opcodes {
+
+ private static final BitwiseNegationExpression EMPTY_BITWISE_NEGATE = new BitwiseNegationExpression(EmptyExpression.INSTANCE);
private static final UnaryMinusExpression EMPTY_UNARY_MINUS = new UnaryMinusExpression(EmptyExpression.INSTANCE);
private static final UnaryPlusExpression EMPTY_UNARY_PLUS = new UnaryPlusExpression(EmptyExpression.INSTANCE);
- private static final BitwiseNegationExpression EMPTY_BITWISE_NEGATE = new BitwiseNegationExpression(EmptyExpression.INSTANCE);
-
- private final WriterController controller;
public StaticTypesUnaryExpressionHelper(final WriterController controller) {
super(controller);
- this.controller = controller;
}
@Override
public void writeBitwiseNegate(final BitwiseNegationExpression expression) {
expression.getExpression().visit(controller.getAcg());
- if (isPrimitiveOnTop()) {
- ClassNode top = getTopOperand();
- if (top == int_TYPE || top == short_TYPE || top == byte_TYPE || top == char_TYPE || top == long_TYPE) {
- BytecodeExpression bytecodeExpression = bytecodeX(mv -> {
- if (long_TYPE == top) {
- mv.visitLdcInsn(-1L);
- mv.visitInsn(LXOR);
- } else {
- mv.visitInsn(ICONST_M1);
- mv.visitInsn(IXOR);
- if (byte_TYPE == top) {
- mv.visitInsn(I2B);
- } else if (char_TYPE == top) {
- mv.visitInsn(I2C);
- } else if (short_TYPE == top) {
- mv.visitInsn(I2S);
- }
+ ClassNode top = controller.getOperandStack().getTopOperand();
+ if (top == int_TYPE || top == long_TYPE || top == short_TYPE || top == byte_TYPE || top == char_TYPE) {
+ bytecodeX(mv -> {
+ if (top == long_TYPE) {
+ mv.visitLdcInsn(-1);
+ mv.visitInsn(LXOR);
+ } else {
+ mv.visitInsn(ICONST_M1);
+ mv.visitInsn(IXOR);
+ if (top == byte_TYPE) {
+ mv.visitInsn(I2B);
+ } else if (top == char_TYPE) {
+ mv.visitInsn(I2C);
+ } else if (top == short_TYPE) {
+ mv.visitInsn(I2S);
}
- });
- bytecodeExpression.visit(controller.getAcg());
- controller.getOperandStack().remove(1);
- return;
- }
+ }
+ }).visit(controller.getAcg());
+ controller.getOperandStack().remove(1);
+ } else {
+ super.writeBitwiseNegate(EMPTY_BITWISE_NEGATE);
}
- super.writeBitwiseNegate(EMPTY_BITWISE_NEGATE);
}
@Override
public void writeNotExpression(final NotExpression expression) {
- TypeChooser typeChooser = controller.getTypeChooser();
Expression subExpression = expression.getExpression();
- ClassNode classNode = controller.getClassNode();
- if (typeChooser.resolveType(subExpression, classNode) == boolean_TYPE) {
+ TypeChooser typeChooser = controller.getTypeChooser();
+ if (typeChooser.resolveType(subExpression, controller.getClassNode()) == boolean_TYPE) {
subExpression.visit(controller.getAcg());
controller.getOperandStack().doGroovyCast(boolean_TYPE);
- BytecodeExpression bytecodeExpression = bytecodeX(mv -> {
+ bytecodeX(mv -> {
Label ne = new Label();
mv.visitJumpInsn(IFNE, ne);
mv.visitInsn(ICONST_1);
@@ -106,62 +98,50 @@ public class StaticTypesUnaryExpressionHelper extends UnaryExpressionHelper impl
mv.visitLabel(ne);
mv.visitInsn(ICONST_0);
mv.visitLabel(out);
- });
- bytecodeExpression.visit(controller.getAcg());
+ }).visit(controller.getAcg());
controller.getOperandStack().remove(1);
- return;
+ } else {
+ super.writeNotExpression(expression);
}
- super.writeNotExpression(expression);
}
@Override
public void writeUnaryMinus(final UnaryMinusExpression expression) {
expression.getExpression().visit(controller.getAcg());
- if (isPrimitiveOnTop()) {
- ClassNode top = getTopOperand();
- if (top != boolean_TYPE) {
- BytecodeExpression bytecodeExpression = bytecodeX(mv -> {
- if (int_TYPE == top || short_TYPE == top || byte_TYPE == top || char_TYPE == top) {
- mv.visitInsn(INEG);
- if (byte_TYPE == top) {
- mv.visitInsn(I2B);
- } else if (char_TYPE == top) {
- mv.visitInsn(I2C);
- } else if (short_TYPE == top) {
- mv.visitInsn(I2S);
- }
- } else if (long_TYPE == top) {
- mv.visitInsn(LNEG);
- } else if (float_TYPE == top) {
- mv.visitInsn(FNEG);
- } else if (double_TYPE == top) {
- mv.visitInsn(DNEG);
+ ClassNode top = controller.getOperandStack().getTopOperand();
+ if (top == int_TYPE || top == long_TYPE || top == short_TYPE || top == float_TYPE || top == double_TYPE || top == byte_TYPE || top == char_TYPE) {
+ bytecodeX(mv -> {
+ if (top == int_TYPE || top == short_TYPE || top == byte_TYPE || top == char_TYPE) {
+ mv.visitInsn(INEG);
+ if (top == byte_TYPE) {
+ mv.visitInsn(I2B);
+ } else if (top == char_TYPE) {
+ mv.visitInsn(I2C);
+ } else if (top == short_TYPE) {
+ mv.visitInsn(I2S);
}
- });
- bytecodeExpression.visit(controller.getAcg());
- controller.getOperandStack().remove(1);
- return;
- }
+ } else if (top == long_TYPE) {
+ mv.visitInsn(LNEG);
+ } else if (top == float_TYPE) {
+ mv.visitInsn(FNEG);
+ } else if (top == double_TYPE) {
+ mv.visitInsn(DNEG);
+ }
+ }).visit(controller.getAcg());
+ controller.getOperandStack().remove(1);
+ } else {
+ super.writeUnaryMinus(EMPTY_UNARY_MINUS);
}
- // we already visited the sub expression
- super.writeUnaryMinus(EMPTY_UNARY_MINUS);
}
@Override
public void writeUnaryPlus(final UnaryPlusExpression expression) {
expression.getExpression().visit(controller.getAcg());
- if (isPrimitiveOnTop()) {
- // only visit the expression
- return;
+ ClassNode top = controller.getOperandStack().getTopOperand();
+ if (top == int_TYPE || top == long_TYPE || top == short_TYPE || top == float_TYPE || top == double_TYPE || top == byte_TYPE || top == char_TYPE) {
+ // only visit the sub-expression
+ } else {
+ super.writeUnaryPlus(EMPTY_UNARY_PLUS);
}
- super.writeUnaryPlus(EMPTY_UNARY_PLUS);
- }
-
- private boolean isPrimitiveOnTop() {
- return isPrimitiveType(getTopOperand());
- }
-
- private ClassNode getTopOperand() {
- return controller.getOperandStack().getTopOperand();
}
}
diff --git a/src/test/groovy/transform/stc/UnaryOperatorSTCTest.groovy b/src/test/groovy/transform/stc/UnaryOperatorSTCTest.groovy
index e26dbfa..b4854c6 100644
--- a/src/test/groovy/transform/stc/UnaryOperatorSTCTest.groovy
+++ b/src/test/groovy/transform/stc/UnaryOperatorSTCTest.groovy
@@ -19,130 +19,333 @@
package groovy.transform.stc
/**
- * Unit tests for static type checking : unary operator tests.
+ * Unit tests for static type checking : unary operators.
*/
class UnaryOperatorSTCTest extends StaticTypeCheckingTestCase {
+ void testUnaryPlus_int() {
+ assertScript '''
+ int x = 1
+ assert +x == 1
+ '''
+ }
+
+ void testUnaryMinus_int() {
+ assertScript '''
+ int x = 1
+ assert -x == -1
+ '''
+ }
+
+ void testBitwiseNegate_int() {
+ assertScript '''
+ int x = 1
+ assert ~x == -2
+ '''
+ }
+
+ //
+
+ void testUnaryPlus_long() {
+ assertScript '''
+ long x = 1L
+ assert +x == 1L
+ '''
+ }
+
+ void testUnaryMinus_long() {
+ assertScript '''
+ long x = 1L
+ assert -x == -1L
+ '''
+ }
+
// GROOVY-9704
- void testBitwiseNegate_long() {
+ void _FIXME_testBitwiseNegate_long() {
assertScript '''
long x = 1L
assert ~x == -2L
'''
}
- void testUnaryPlusOnInt() {
+ //
+
+ void testUnaryPlus_short() {
assertScript '''
- int x = 1
+ short x = 1
assert +x == 1
'''
}
- void testUnaryPlusOnInteger() {
+ void testUnaryMinus_short() {
assertScript '''
- Integer x = new Integer(1)
+ short x = 1
+ assert -x == -1
+ '''
+ }
+
+ void testBitwiseNegate_short() {
+ assertScript '''
+ short x = 1
+ assert ~x == -2
+ '''
+ }
+
+ //
+
+ void testUnaryPlus_byte() {
+ assertScript '''
+ byte x = 1
assert +x == 1
'''
}
- void testUnaryMinusOnInt() {
+ void testUnaryMinus_byte() {
assertScript '''
- int x = 1
+ byte x = 1
assert -x == -1
'''
}
- void testUnaryMinusOnInteger() {
+ void testBitwiseNegate_byte() {
+ assertScript '''
+ byte x = 1
+ assert ~x == -2
+ '''
+ }
+
+ //
+
+ void testUnaryPlus_char() {
+ shouldFail MissingMethodException, '''
+ char x = 1
+ +x
+ '''
+ }
+
+ void testUnaryMinus_char() {
+ shouldFail MissingMethodException, '''
+ char x = 1
+ -x
+ '''
+ }
+
+ void testBitwiseNegate_char() {
+ shouldFail MissingMethodException, '''
+ char x = 1
+ ~x
+ '''
+ }
+
+ //
+
+ void testUnaryPlus_float() {
+ assertScript '''
+ float x = 1f
+ assert +x == 1f
+ '''
+ }
+
+ void testUnaryMinus_float() {
+ assertScript '''
+ float x = 1f
+ assert -x == -1f
+ '''
+ }
+
+ void testBitwiseNegate_float() {
+ shouldFail UnsupportedOperationException, '''
+ float x = 1f
+ ~x
+ '''
+ }
+
+ //
+
+ void testUnaryPlus_double() {
+ assertScript '''
+ double x = 1d
+ assert +x == 1d
+ '''
+ }
+
+ void testUnaryMinus_double() {
+ assertScript '''
+ double x = 1d
+ assert -x == -1d
+ '''
+ }
+
+ void testBitwiseNegate_double() {
+ shouldFail UnsupportedOperationException, '''
+ double x = 1d
+ ~x
+ '''
+ }
+
+ //
+
+ void testUnaryPlus_Integer() {
+ assertScript '''
+ Integer x = new Integer(1)
+ assert +x == 1
+ '''
+ }
+
+ void testUnaryMinus_Integer() {
assertScript '''
Integer x = new Integer(1)
assert -x == -1
'''
}
- void testUnaryPlusOnShort() {
+ void testBitwiseNegate_Integer() {
assertScript '''
- short x = 1
- assert +x == 1
+ Integer x = new Integer(1)
+ assert ~x == -2
+ '''
+ }
+
+ //
+
+ void testUnaryPlus_Long() {
+ assertScript '''
+ Long x = new Long(1L)
+ assert +x == 1L
'''
}
- void testUnaryPlusOnBoxedShort() {
+ void testUnaryMinus_Long() {
+ assertScript '''
+ Long x = new Long(1L)
+ assert -x == -1L
+ '''
+ }
+
+ void testBitwiseNegate_Long() {
+ assertScript '''
+ Long x = new Long(1L)
+ assert ~x == -2L
+ '''
+ }
+
+ //
+
+ void testUnaryPlus_Short() {
assertScript '''
Short x = new Short((short)1)
assert +x == 1
'''
}
- void testUnaryMinusOnShort() {
+ void testUnaryMinus_Short() {
assertScript '''
- short x = 1
+ Short x = new Short((short)1)
assert -x == -1
'''
}
- void testUnaryMinusOnBoxedShort() {
+ void testBitwiseNegate_Short() {
assertScript '''
Short x = new Short((short)1)
- assert -x == -1
+ assert ~x == -2
'''
}
- void testUnaryPlusOnFloat() {
+ //
+
+ void testUnaryPlus_Byte() {
assertScript '''
- float x = 1f
- assert +x == 1f
+ Byte x = new Byte((byte)1)
+ assert +x == 1
'''
}
- void testUnaryPlusOnBoxedFloat() {
+ void testUnaryMinus_Byte() {
assertScript '''
- Float x = new Float(1f)
- assert +x == 1f
+ Byte x = new Byte((byte)1)
+ assert -x == -1
'''
}
- void testUnaryMinusOnFloat() {
+ void testBitwiseNegate_Byte() {
assertScript '''
- float x = 1f
- assert -x == -1f
+ Byte x = new Byte((byte)1)
+ assert ~x == -2
+ '''
+ }
+
+ //
+
+ void testUnaryPlus_Character() {
+ shouldFail MissingMethodException, '''
+ Character x = new Character((char)1)
+ +x
+ '''
+ }
+
+ void testUnaryMinus_Character() {
+ shouldFail MissingMethodException, '''
+ Character x = new Character((char)1)
+ -x
+ '''
+ }
+
+ void testBitwiseNegate_Character() {
+ shouldFail MissingMethodException, '''
+ Character x = new Character((char)1)
+ ~x
'''
}
- void testUnaryMinusOnBoxedFloat() {
+ //
+
+ void testUnaryPlus_Float() {
assertScript '''
Float x = new Float(1f)
- assert -x == -1f
+ assert +x == 1f
'''
}
- void testUnaryPlusOnDouble() {
+ void testUnaryMinus_Float() {
assertScript '''
- double x = 1d
- assert +x == 1d
+ Float x = new Float(1f)
+ assert -x == -1f
+ '''
+ }
+
+ void testBitwiseNegate_Float() {
+ shouldFail UnsupportedOperationException, '''
+ Float x = new Float(1f)
+ ~x
'''
}
- void testUnaryPlusOnBoxedDouble() {
+ //
+
+ void testUnaryPlus_Double() {
assertScript '''
Double x = new Double(1d)
assert +x == 1d
'''
}
- void testUnaryMinusOnDouble() {
+ void testUnaryMinus_Double() {
assertScript '''
- double x = 1d
+ Double x = new Double(1d)
assert -x == -1d
'''
}
- void testUnaryMinusOnBoxedDouble() {
- assertScript '''
+ void testBitwiseNegate_Double() {
+ shouldFail UnsupportedOperationException, '''
Double x = new Double(1d)
- assert -x == -1d
+ ~x
'''
}
+ //
+
void testIntXIntInferredType() {
assertScript '''
int x = 1
@@ -325,4 +528,3 @@ class UnaryOperatorSTCTest extends StaticTypeCheckingTestCase {
'''
}
}
-
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/UnaryOperatorStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/UnaryOperatorStaticCompileTest.groovy
index 520325b..f330eae 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/UnaryOperatorStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/UnaryOperatorStaticCompileTest.groovy
@@ -21,9 +21,31 @@ package org.codehaus.groovy.classgen.asm.sc
import groovy.transform.stc.UnaryOperatorSTCTest
/**
- * Unit tests for static type checking : unary operator.
+ * Unit tests for static compilation : unary operators.
*/
class UnaryOperatorStaticCompileTest extends UnaryOperatorSTCTest implements StaticCompilationTestSupport {
-}
+ @Override
+ void testUnaryPlus_char() {
+ assertScript '''
+ char x = 1
+ assert +x == 1
+ '''
+ }
+
+ @Override
+ void testUnaryMinus_char() {
+ assertScript '''
+ char x = 1
+ assert -x == 0xFFFF
+ '''
+ }
+ @Override
+ void testBitwiseNegate_char() {
+ assertScript '''
+ char x = 1
+ assert ~x == 0xFFFE
+ '''
+ }
+}
[groovy] 16/19: reduce use of dynamic features
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 4c324a9d77d73885e3c7084d6d4a4fa53f35d13f
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Aug 30 09:45:13 2020 -0500
reduce use of dynamic features
(cherry picked from commit 58abc9e4d4e397dc148b6b7333c350a105894d93)
---
src/main/groovy/groovy/grape/GrapeIvy.groovy | 506 ++++++++++++---------------
1 file changed, 219 insertions(+), 287 deletions(-)
diff --git a/src/main/groovy/groovy/grape/GrapeIvy.groovy b/src/main/groovy/groovy/grape/GrapeIvy.groovy
index 9da4a92..9dbc44f 100644
--- a/src/main/groovy/groovy/grape/GrapeIvy.groovy
+++ b/src/main/groovy/groovy/grape/GrapeIvy.groovy
@@ -18,9 +18,7 @@
*/
package groovy.grape
-import groovy.transform.CompileStatic
-import groovy.transform.NamedParam
-import groovy.transform.NamedParams
+import groovy.transform.*
import org.apache.groovy.plugin.GroovyRunner
import org.apache.groovy.plugin.GroovyRunnerRegistry
import org.apache.ivy.Ivy
@@ -61,65 +59,58 @@ import java.util.zip.ZipFile
/**
* Implementation supporting {@code @Grape} and {@code @Grab} annotations based on Ivy.
*/
+@AutoFinal @CompileStatic
class GrapeIvy implements GrapeEngine {
private static final String METAINF_PREFIX = 'META-INF/services/'
- private static final String RUNNER_PROVIDER_CONFIG = GroovyRunner.name
- private static final List<String> DEF_CONFIG = ['default']
-
- private final exclusiveGrabArgs = [
+ private static final String RUNNER_PROVIDER_CONFIG = GroovyRunner.getName()
+ private static final List<String> DEFAULT_CONF = Collections.singletonList('default')
+ private static final Map<String, Set<String>> MUTUALLY_EXCLUSIVE_KEYS = processGrabArgs([
['group', 'groupId', 'organisation', 'organization', 'org'],
['module', 'artifactId', 'artifact'],
['version', 'revision', 'rev'],
['conf', 'scope', 'configuration'],
- ].inject([:], { m, g -> g.each { a -> m[a] = (g - a) as Set }; m })
+ ])
+
+ @CompileDynamic // maps a->[b,c], b->[a,c] and c->[a,b] given [a,b,c]
+ private static Map<String, Set<String>> processGrabArgs(List<List<String>> grabArgs) {
+ grabArgs.inject([:]) { Map m, List g -> g.each { a -> m[a] = (g - a) as Set }; m }
+ }
+
+ boolean enableGrapes = true
- boolean enableGrapes
Ivy ivyInstance
- Set<String> resolvedDependencies
- Set<String> downloadedArtifacts
- // weak hash map so we don't leak loaders directly
- Map<ClassLoader, Set<IvyGrabRecord>> loadedDeps = new WeakHashMap<ClassLoader, Set<IvyGrabRecord>>()
- // set that stores the IvyGrabRecord(s) for all the dependencies in each grab() call
- Set<IvyGrabRecord> grabRecordsForCurrDependencies = new LinkedHashSet<IvyGrabRecord>()
- // we keep the settings so that addResolver can add to the resolver chain
IvySettings settings
+ Set<String> downloadedArtifacts = []
+ Set<String> resolvedDependencies = []
+ // weak hash map so we don't leak loaders directly
+ final Map<ClassLoader, Set<IvyGrabRecord>> loadedDeps = [] as WeakHashMap
+ /** Stores the IvyGrabRecord(s) for all dependencies in each grab() call. */
+ final Set<IvyGrabRecord> grabRecordsForCurrDependencies = [] as LinkedHashSet
GrapeIvy() {
- // if we are already initialized, quit
- if (enableGrapes) return
+ Message.setDefaultLogger(new DefaultMessageLogger(System.getProperty('ivy.message.logger.level', '-1') as int))
- // start ivy
- Message.defaultLogger = new DefaultMessageLogger(System.getProperty('ivy.message.logger.level', '-1') as int)
settings = new IvySettings()
settings.setVariable('user.home.url', new File(System.getProperty('user.home')).toURI().toURL() as String)
-
- // configure settings
- def grapeConfig = localGrapeConfig
- if (!grapeConfig.exists()) {
- grapeConfig = GrapeIvy.getResource('defaultGrapeConfig.xml')
- }
- try {
- settings.load(grapeConfig) // exploit multi-methods for convenience
- } catch (java.text.ParseException ex) {
- def configLocation = grapeConfig instanceof File ? grapeConfig.canonicalPath : grapeConfig.toString()
- System.err.println "Local Ivy config file '$configLocation' appears corrupt - ignoring it and using default config instead\nError was: ${ex.message}"
+ File grapeConfig = getLocalGrapeConfig()
+ if (grapeConfig.exists()) {
+ try {
+ settings.load(grapeConfig)
+ } catch (java.text.ParseException e) {
+ System.err.println("Local Ivy config file '${grapeConfig.getCanonicalPath()}' appears corrupt - ignoring it and using default config instead\nError was: ${e.getMessage()}")
+ settings.load(GrapeIvy.getResource('defaultGrapeConfig.xml'))
+ }
+ } else {
settings.load(GrapeIvy.getResource('defaultGrapeConfig.xml'))
}
-
- // set up the cache dirs
- settings.defaultCache = grapeCacheDir
-
+ settings.setDefaultCache(getGrapeCacheDir())
settings.setVariable('ivy.default.configuration.m2compatible', 'true')
- ivyInstance = Ivy.newInstance(settings)
- IvyContext.context.ivy = ivyInstance
- resolvedDependencies = []
- downloadedArtifacts = []
- enableGrapes = true
+ ivyInstance = Ivy.newInstance(settings)
+ IvyContext.getContext().setIvy(ivyInstance)
}
- @CompileStatic
File getGroovyRoot() {
String root = System.getProperty('groovy.root')
def groovyRoot
@@ -129,38 +120,27 @@ class GrapeIvy implements GrapeEngine {
groovyRoot = new File(root)
}
try {
- groovyRoot = groovyRoot.canonicalFile
+ groovyRoot = groovyRoot.getCanonicalFile()
} catch (IOException ignore) {
// skip canonicalization then, it may not exist yet
}
groovyRoot
}
- @CompileStatic
- File getLocalGrapeConfig() {
- String grapeConfig = System.getProperty('grape.config')
- if (grapeConfig) {
- return new File(grapeConfig)
- }
- new File(grapeDir, 'grapeConfig.xml')
- }
-
- @CompileStatic
File getGrapeDir() {
String root = System.getProperty('grape.root')
if (root == null) {
- return groovyRoot
+ return getGroovyRoot()
}
File grapeRoot = new File(root)
try {
- grapeRoot = grapeRoot.canonicalFile
+ grapeRoot = grapeRoot.getCanonicalFile()
} catch (IOException ignore) {
// skip canonicalization then, it may not exist yet
}
grapeRoot
}
- @CompileStatic
File getGrapeCacheDir() {
File cache = new File(grapeDir, 'grapes')
if (!cache.exists()) {
@@ -171,22 +151,30 @@ class GrapeIvy implements GrapeEngine {
cache
}
- @CompileStatic
+ File getLocalGrapeConfig() {
+ String grapeConfig = System.getProperty('grape.config')
+ if (grapeConfig) {
+ new File(grapeConfig)
+ } else {
+ new File(getGrapeDir(), 'grapeConfig.xml')
+ }
+ }
+
ClassLoader chooseClassLoader(Map args) {
ClassLoader loader = (ClassLoader) args.classLoader
if (!isValidTargetClassLoader(loader)) {
- loader = ((Class) ((args.refObject?.class
- ?: ReflectionUtils.getCallingClass((int) (args.calleeDepth ?: 1))
- )))?.classLoader
+ Class caller = args.refObject?.getClass() ?:
+ ReflectionUtils.getCallingClass((int) args.calleeDepth ?: 1)
+ loader = caller?.getClassLoader()
while (loader && !isValidTargetClassLoader(loader)) {
- loader = loader.parent
+ loader = loader.getParent()
+ }
+ /*if (!isValidTargetClassLoader(loader)) {
+ loader = Thread.currentThread().getContextClassLoader()
}
- //if (!isValidTargetClassLoader(loader)) {
- // loader = Thread.currentThread().contextClassLoader
- //}
- //if (!isValidTargetClassLoader(loader)) {
- // loader = GrapeIvy.class.classLoader
- //}
+ if (!isValidTargetClassLoader(loader)) {
+ loader = GrapeIvy.getClass().getClassLoader()
+ }*/
if (!isValidTargetClassLoader(loader)) {
throw new RuntimeException('No suitable ClassLoader found for grab')
}
@@ -194,67 +182,61 @@ class GrapeIvy implements GrapeEngine {
loader
}
- @CompileStatic
- private boolean isValidTargetClassLoader(loader) {
- isValidTargetClassLoaderClass(loader?.class)
+ private boolean isValidTargetClassLoader(ClassLoader loader) {
+ isValidTargetClassLoaderClass(loader?.getClass())
}
- @CompileStatic
private boolean isValidTargetClassLoaderClass(Class loaderClass) {
- loaderClass != null &&
- (
- (loaderClass.name == 'groovy.lang.GroovyClassLoader') ||
- (loaderClass.name == 'org.codehaus.groovy.tools.RootLoader') ||
- isValidTargetClassLoaderClass(loaderClass.superclass)
- )
- }
-
- @SuppressWarnings('Instanceof')
- IvyGrabRecord createGrabRecord(Map deps) {
- // parse the actual dependency arguments
- String module = deps.module ?: deps.artifactId ?: deps.artifact
+ loaderClass != null && (loaderClass.getName() == 'groovy.lang.GroovyClassLoader'
+ || loaderClass.getName() == 'org.codehaus.groovy.tools.RootLoader'
+ || isValidTargetClassLoaderClass(loaderClass.getSuperclass()))
+ }
+
+ IvyGrabRecord createGrabRecord(Map dep) {
+ String module = dep.module ?: dep.artifactId ?: dep.artifact
if (!module) {
throw new RuntimeException('grab requires at least a module: or artifactId: or artifact: argument')
}
- String groupId = deps.group ?: deps.groupId ?: deps.organisation ?: deps.organization ?: deps.org ?: ''
- String ext = deps.ext ?: deps.type ?: ''
- String type = deps.type ?: ''
-
- //TODO accept ranges and decode them? except '1.0.0'..<'2.0.0' won't work in groovy
- String version = deps.version ?: deps.revision ?: deps.rev ?: '*'
- if ('*' == version) version = 'latest.default'
+ String groupId = dep.group ?: dep.groupId ?: dep.organisation ?: dep.organization ?: dep.org ?: ''
+ // TODO: accept ranges and decode them? except '1.0.0'..<'2.0.0' won't work in groovy
+ String version = dep.version ?: dep.revision ?: dep.rev ?: '*'
+ if (version == '*') version = 'latest.default'
+ String classifier = dep.classifier ?: null
+ String ext = dep.ext ?: dep.type ?: ''
+ String type = dep.type ?: ''
ModuleRevisionId mrid = ModuleRevisionId.newInstance(groupId, module, version)
- boolean force = deps.containsKey('force') ? deps.force : true
- boolean changing = deps.containsKey('changing') ? deps.changing : false
- boolean transitive = deps.containsKey('transitive') ? deps.transitive : true
- def conf = deps.conf ?: deps.scope ?: deps.configuration ?: DEF_CONFIG
+ boolean force = dep.containsKey('force') ? dep.force : true
+ boolean changing = dep.containsKey('changing') ? dep.changing : false
+ boolean transitive = dep.containsKey('transitive') ? dep.transitive : true
+
+ new IvyGrabRecord(mrid: mrid, conf: getConfList(dep), force: force, changing: changing, transitive: transitive, ext: ext, type: type, classifier: classifier)
+ }
+
+ @CompileDynamic
+ private List<String> getConfList(Map dep) {
+ def conf = dep.conf ?: dep.scope ?: dep.configuration ?: DEFAULT_CONF
if (conf instanceof String) {
if (conf.startsWith('[') && conf.endsWith(']')) conf = conf[1..-2]
conf = conf.split(',').toList()
}
- def classifier = deps.classifier ?: null
-
- new IvyGrabRecord(mrid: mrid, conf: conf, changing: changing, transitive: transitive, force: force, classifier: classifier, ext: ext, type: type)
+ conf
}
@Override
- @CompileStatic
grab(String endorsedModule) {
- grab(group: 'groovy.endorsed', module: endorsedModule, version: GroovySystem.version)
+ grab(group: 'groovy.endorsed', module: endorsedModule, version: GroovySystem.getVersion())
}
@Override
- @CompileStatic
grab(Map args) {
args.calleeDepth = args.calleeDepth ?: DEFAULT_CALLEE_DEPTH + 1
grab(args, args)
}
@Override
- @CompileStatic
grab(Map args, Map... dependencies) {
ClassLoader loader = null
grabRecordsForCurrDependencies.clear()
@@ -262,22 +244,22 @@ class GrapeIvy implements GrapeEngine {
try {
// identify the target classloader early, so we fail before checking repositories
loader = chooseClassLoader(
- classLoader: args.remove('classLoader'),
refObject: args.remove('refObject'),
+ classLoader: args.remove('classLoader'),
calleeDepth: args.calleeDepth ?: DEFAULT_CALLEE_DEPTH,
)
- // check for non-fail null.
- // If we were in fail mode we would have already thrown an exception
+ // check for non-fail null
+ // if we were in fail mode we would have already thrown an exception
if (!loader) return
- def uris = resolve(loader, args, dependencies)
- for (URI uri in uris) {
+ URI[] uris = resolve(loader, args, dependencies)
+ for (URI uri : uris) {
addURL(loader, uri)
}
boolean runnerServicesFound = false
- for (URI uri in uris) {
- //TODO check artifact type, jar vs library, etc
+ for (URI uri : uris) {
+ // TODO: check artifact type, jar vs library, etc.
File file = new File(uri)
processCategoryMethods(loader, file)
Collection<String> services = processMetaInfServices(loader, file)
@@ -286,7 +268,7 @@ class GrapeIvy implements GrapeEngine {
}
}
if (runnerServicesFound) {
- GroovyRunnerRegistry.instance.load(loader)
+ GroovyRunnerRegistry.getInstance().load(loader)
}
} catch (Exception e) {
// clean-up the state first
@@ -302,19 +284,18 @@ class GrapeIvy implements GrapeEngine {
null
}
+ @CompileDynamic
private void addURL(ClassLoader loader, URI uri) {
loader.addURL(uri.toURL())
}
- @SuppressWarnings('Instanceof')
- @CompileStatic
private processCategoryMethods(ClassLoader loader, File file) {
// register extension methods if jar
- if (file.name.toLowerCase().endsWith('.jar')) {
- def mcRegistry = GroovySystem.metaClassRegistry
+ if (file.getName().toLowerCase().endsWith('.jar')) {
+ def mcRegistry = GroovySystem.getMetaClassRegistry()
if (mcRegistry instanceof MetaClassRegistryImpl) {
try (JarFile jar = new JarFile(file)) {
- def entry = jar.getEntry(ExtensionModuleScanner.MODULE_META_INF_FILE)
+ ZipEntry entry = jar.getEntry(ExtensionModuleScanner.MODULE_META_INF_FILE)
if (!entry) {
entry = jar.getEntry(ExtensionModuleScanner.LEGACY_MODULE_META_INF_FILE)
}
@@ -325,7 +306,7 @@ class GrapeIvy implements GrapeEngine {
props.load(is)
}
- Map<CachedClass, List<MetaMethod>> metaMethods = new HashMap<CachedClass, List<MetaMethod>>()
+ Map<CachedClass, List<MetaMethod>> metaMethods = [:]
mcRegistry.registerExtensionModuleFromProperties(props, loader, metaMethods)
// add old methods to the map
metaMethods.each { CachedClass c, List<MetaMethod> methods ->
@@ -333,21 +314,20 @@ class GrapeIvy implements GrapeEngine {
// have their own ClassInfo, and we must change them as well!
Set<CachedClass> classesToBeUpdated = [c].toSet()
ClassInfo.onAllClassInfo { ClassInfo info ->
- if (c.theClass.isAssignableFrom(info.cachedClass.theClass)) {
- classesToBeUpdated << info.cachedClass
+ if (c.getTheClass().isAssignableFrom(info.getCachedClass().getTheClass())) {
+ classesToBeUpdated << info.getCachedClass()
}
}
classesToBeUpdated*.addNewMopMethods(methods)
}
}
- } catch (ZipException zipException) {
- throw new RuntimeException("Grape could not load jar '$file'", zipException)
+ } catch (ZipException e) {
+ throw new RuntimeException("Grape could not load jar '$file'", e)
}
}
}
}
- @CompileStatic
void processOtherServices(ClassLoader loader, File f) {
processMetaInfServices(loader, f) // ignore result
}
@@ -360,9 +340,8 @@ class GrapeIvy implements GrapeEngine {
* @param f ZipFile in which to search for services
* @return a collection of service provider files that were found
*/
- @CompileStatic
private Collection<String> processMetaInfServices(ClassLoader loader, File f) {
- List<String> services = new ArrayList<>()
+ List<String> services = []
try (ZipFile zf = new ZipFile(f)) {
String providerConfig = 'org.codehaus.groovy.runtime.SerializedCategoryMethods'
ZipEntry serializedCategoryMethods = zf.getEntry(METAINF_PREFIX + providerConfig)
@@ -380,7 +359,7 @@ class GrapeIvy implements GrapeEngine {
services.add(providerConfig)
try (InputStream is = zf.getInputStream(pluginRunners)) {
- processRunners(is, f.name, loader)
+ processRunners(is, f.getName(), loader)
}
}
// GroovyRunners are loaded per ClassLoader using a ServiceLoader so here
@@ -390,44 +369,42 @@ class GrapeIvy implements GrapeEngine {
}
} catch (ZipException ignore) {
// ignore files we can't process, e.g. non-jar/zip artifacts
- // TODO log a warning
+ // TODO: log a warning
}
services
}
- @CompileStatic
void processSerializedCategoryMethods(InputStream is) {
- is.text.readLines().each {
- System.err.println it.trim() // TODO implement this or delete it
+ is.getText().readLines().each {
+ System.err.println(it.trim()) // TODO: implement this or delete it
}
}
- @CompileStatic
void processRunners(InputStream is, String name, ClassLoader loader) {
- GroovyRunnerRegistry registry = GroovyRunnerRegistry.instance
- is.text.readLines()*.trim().findAll { String line -> !line.isEmpty() && line[0] != '#' }.each {
- String line = (String) it
+ GroovyRunnerRegistry registry = GroovyRunnerRegistry.getInstance()
+ is.getText().readLines()*.trim().each { String line ->
+ if (!line.isEmpty() && line[0] != '#')
try {
registry[name] = (GroovyRunner) loader.loadClass(line).newInstance()
- } catch (Exception ex) {
- throw new IllegalStateException("Error registering runner class '$it'", ex)
+ } catch (Exception e) {
+ throw new IllegalStateException("Error registering runner class '$line'", e)
}
}
}
ResolveReport getDependencies(Map args, IvyGrabRecord... grabRecords) {
- def cacheManager = ivyInstance.resolutionCacheManager
+ def cacheManager = ivyInstance.getResolutionCacheManager()
def millis = System.currentTimeMillis()
def md = new DefaultModuleDescriptor(ModuleRevisionId.newInstance('caller', 'all-caller', 'working' + millis.toString()[-2..-1]), 'integration', null, true)
md.addConfiguration(new Configuration('default'))
- md.lastModified = millis
+ md.setLastModified(millis)
addExcludesIfNeeded(args, md)
for (IvyGrabRecord grabRecord : grabRecords) {
- def confs = grabRecord.conf ?: ['*']
- DefaultDependencyDescriptor dd = (DefaultDependencyDescriptor) md.dependencies.find {
- it.dependencyRevisionId == grabRecord.mrid
+ List<String> confs = grabRecord.conf ?: ['*']
+ DefaultDependencyDescriptor dd = (DefaultDependencyDescriptor) md.getDependencies().find {
+ it.getDependencyRevisionId() == grabRecord.mrid
}
if (!dd) {
dd = new DefaultDependencyDescriptor(md, grabRecord.mrid, grabRecord.force, grabRecord.changing, grabRecord.transitive)
@@ -446,13 +423,12 @@ class GrapeIvy implements GrapeEngine {
// resolve grab and dependencies
def resolveOptions = new ResolveOptions(
- confs: DEF_CONFIG as String[],
- outputReport: false,
- validate: (boolean) (args.containsKey('validate') ? args.validate : false)
+ confs: DEFAULT_CONF as String[], outputReport: false,
+ validate: (args.containsKey('validate') ? (boolean) args.validate : false)
)
- ivyInstance.settings.defaultResolver = args.autoDownload ? 'downloadGrapes' : 'cachedGrapes'
+ ivyInstance.getSettings().setDefaultResolver(args.autoDownload ? 'downloadGrapes' : 'cachedGrapes')
if (args.disableChecksums) {
- ivyInstance.settings.setVariable('ivy.checksums', '')
+ ivyInstance.getSettings().setVariable('ivy.checksums', '')
}
boolean reportDownloads = Boolean.getBoolean('groovy.grape.report.downloads')
if (reportDownloads) {
@@ -465,28 +441,27 @@ class GrapeIvy implements GrapeEngine {
try {
report = ivyInstance.resolve(md, resolveOptions)
break
- } catch (IOException ioe) {
+ } catch (IOException e) {
if (attempt--) {
- if (reportDownloads)
- System.err.println 'Grab Error: retrying...'
- sleep attempt > 4 ? 350 : 1000
+ if (reportDownloads) System.err.println('Grab Error: retrying...')
+ sleep(attempt > 4 ? 350 : 1000)
continue
}
- throw new RuntimeException("Error grabbing grapes -- $ioe.message")
+ throw new RuntimeException("Error grabbing grapes -- ${e.getMessage()}")
}
}
if (report.hasError()) {
- throw new RuntimeException("Error grabbing Grapes -- $report.allProblemMessages")
+ throw new RuntimeException("Error grabbing Grapes -- ${report.getAllProblemMessages()}")
}
- if (report.downloadSize && reportDownloads) {
- System.err.println "Downloaded ${report.downloadSize >> 10} Kbytes in ${report.downloadTime}ms:\n ${report.allArtifactsReports*.toString().join('\n ')}"
+ if (report.getDownloadSize() && reportDownloads) {
+ System.err.println("Downloaded ${report.getDownloadSize() >> 10} Kbytes in ${report.getDownloadTime()}ms:\n ${report.getAllArtifactsReports()*.toString().join('\n ')}")
}
- md = report.moduleDescriptor
+ md = report.getModuleDescriptor()
if (!args.preserveFiles) {
- cacheManager.getResolvedIvyFileInCache(md.moduleRevisionId).delete()
- cacheManager.getResolvedIvyPropertiesInCache(md.moduleRevisionId).delete()
+ cacheManager.getResolvedIvyFileInCache(md.getModuleRevisionId()).delete()
+ cacheManager.getResolvedIvyPropertiesInCache(md.getModuleRevisionId()).delete()
}
report
@@ -496,20 +471,18 @@ class GrapeIvy implements GrapeEngine {
ivyInstance.eventManager.addIvyListener { ivyEvent ->
switch (ivyEvent) {
case StartResolveEvent:
- ivyEvent.moduleDescriptor.dependencies.each {
+ ((StartResolveEvent) ivyEvent).getModuleDescriptor().getDependencies().each {
def name = it.toString()
- if (!resolvedDependencies.contains(name)) {
- resolvedDependencies << name
- System.err.println "Resolving $name"
+ if (resolvedDependencies.add(name)) {
+ System.err.println("Resolving $name")
}
}
break
case PrepareDownloadEvent:
- ivyEvent.artifacts.each {
+ ((PrepareDownloadEvent) ivyEvent).getArtifacts().each {
def name = it.toString()
- if (!downloadedArtifacts.contains(name)) {
- downloadedArtifacts << name
- System.err.println "Preparing to download artifact $name"
+ if (downloadedArtifacts.add(name)) {
+ System.err.println("Preparing to download artifact $name")
}
}
break
@@ -518,21 +491,21 @@ class GrapeIvy implements GrapeEngine {
}
void uninstallArtifact(String group, String module, String rev) {
- // TODO consider transitive uninstall as an option
- Pattern ivyFilePattern = ~/ivy-(.*)\.xml/ //TODO get pattern from ivy conf
+ // TODO: consider transitive uninstall as an option
+ Pattern ivyFilePattern = ~/ivy-(.*)\.xml/ // TODO: get pattern from ivy conf
grapeCacheDir.eachDir { File groupDir ->
- if (groupDir.name == group) groupDir.eachDir { File moduleDir ->
- if (moduleDir.name == module) moduleDir.eachFileMatch(ivyFilePattern) { File ivyFile ->
- def m = ivyFilePattern.matcher(ivyFile.name)
+ if (groupDir.getName() == group) groupDir.eachDir { File moduleDir ->
+ if (moduleDir.getName() == module) moduleDir.eachFileMatch(ivyFilePattern) { File ivyFile ->
+ def m = ivyFilePattern.matcher(ivyFile.getName())
if (m.matches() && m.group(1) == rev) {
- // TODO handle other types? e.g. 'dlls'
+ // TODO: handle other types? e.g. 'dlls'
def jardir = new File(moduleDir, 'jars')
if (!jardir.exists()) return
def db = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder()
- def root = db.parse(ivyFile).documentElement
+ def root = db.parse(ivyFile).getDocumentElement()
def publis = root.getElementsByTagName('publications')
- for (int i = 0; i < publis.length; i++) {
- def artifacts = publis.item(i).getElementsByTagName('artifact')
+ for (int i = 0; i < publis.length; i += 1) {
+ def artifacts = ((org.w3c.dom.Element) publis.item(i)).getElementsByTagName('artifact')
processArtifacts(artifacts, rev, jardir)
}
ivyFile.delete()
@@ -542,106 +515,102 @@ class GrapeIvy implements GrapeEngine {
}
}
- private void processArtifacts(artifacts, String rev, File jardir) {
- for (int j = 0; j < artifacts.length; j++) {
- def artifact = artifacts.item(j)
- def attrs = artifact.attributes
- def name = attrs.getNamedItem('name').textContent + "-$rev"
- def classifier = attrs.getNamedItemNS('m', 'classifier')?.textContent
+ private void processArtifacts(org.w3c.dom.NodeList artifacts, String rev, File jardir) {
+ for (int i = 0, n = artifacts.getLength(); i < n; i += 1) {
+ org.w3c.dom.Node artifact = artifacts.item(i)
+ def attrs = artifact.getAttributes()
+ def name = attrs.getNamedItem('name').getTextContent() + "-$rev"
+ def classifier = attrs.getNamedItemNS('m', 'classifier')?.getTextContent()
if (classifier) name += "-$classifier"
- name += ".${attrs.getNamedItem('ext').textContent}"
+ name += ".${attrs.getNamedItem('ext').getTextContent()}"
def jarfile = new File(jardir, name)
if (jarfile.exists()) {
- System.err.println "Deleting ${jarfile.name}"
+ System.err.println("Deleting ${jarfile.getName()}")
jarfile.delete()
}
}
}
private addExcludesIfNeeded(Map args, DefaultModuleDescriptor md) {
- if (!args.containsKey('excludes')) return
- args.excludes.each { map ->
- def excludeRule = new DefaultExcludeRule(new ArtifactId(
- new ModuleId(map.group, map.module), PatternMatcher.ANY_EXPRESSION,
- PatternMatcher.ANY_EXPRESSION,
- PatternMatcher.ANY_EXPRESSION),
- ExactPatternMatcher.INSTANCE, null)
+ args.excludes?.each { Map<String, String> map ->
+ def excludeRule = new DefaultExcludeRule(
+ new ArtifactId(
+ new ModuleId(map.group, map.module),
+ PatternMatcher.ANY_EXPRESSION,
+ PatternMatcher.ANY_EXPRESSION,
+ PatternMatcher.ANY_EXPRESSION),
+ ExactPatternMatcher.INSTANCE,
+ null)
excludeRule.addConfiguration('default')
md.addExcludeRule(excludeRule)
}
}
@Override
- @CompileStatic
Map<String, Map<String, List<String>>> enumerateGrapes() {
Map<String, Map<String, List<String>>> bunches = [:]
- Pattern ivyFilePattern = ~/ivy-(.*)\.xml/ //TODO get pattern from ivy conf
+ Pattern ivyFilePattern = ~/ivy-(.*)\.xml/ // TODO: get pattern from ivy conf
grapeCacheDir.eachDir { File groupDir ->
Map<String, List<String>> grapes = [:]
- bunches[groupDir.name] = grapes
+ bunches[groupDir.getName()] = grapes
groupDir.eachDir { File moduleDir ->
List<String> versions = []
moduleDir.eachFileMatch(ivyFilePattern) { File ivyFile ->
- def m = ivyFilePattern.matcher(ivyFile.name)
+ def m = ivyFilePattern.matcher(ivyFile.getName())
if (m.matches()) versions += m.group(1)
}
- grapes[moduleDir.name] = versions
+ grapes[moduleDir.getName()] = versions
}
}
bunches
}
@Override
- @CompileStatic
URI[] resolve(Map args, Map... dependencies) {
resolve(args, null, dependencies)
}
@Override
- @CompileStatic
URI[] resolve(Map args, List depsInfo, Map... dependencies) {
// identify the target classloader early, so we fail before checking repositories
ClassLoader loader = chooseClassLoader(
- classLoader: args.remove('classLoader'),
refObject: args.remove('refObject'),
+ classLoader: args.remove('classLoader'),
calleeDepth: args.calleeDepth ?: DEFAULT_CALLEE_DEPTH,
)
- // check for non-fail null.
- // If we were in fail mode we would have already thrown an exception
+ // check for non-fail null
+ // if we were in fail mode we would have already thrown an exception
if (!loader) {
- return [] as URI[]
+ return new URI[0]
}
resolve(loader, args, depsInfo, dependencies)
}
- @CompileStatic
URI[] resolve(ClassLoader loader, Map args, Map... dependencies) {
resolve(loader, args, null, dependencies)
}
URI[] resolve(ClassLoader loader, Map args, List depsInfo, Map... dependencies) {
// check for mutually exclusive arguments
- Set keys = args.keySet()
- keys.each { a ->
- Set badArgs = exclusiveGrabArgs[a]
+ Set<String> keys = args.keySet()
+ keys.each { key ->
+ Set<String> badArgs = MUTUALLY_EXCLUSIVE_KEYS[key]
if (badArgs && !badArgs.disjoint(keys)) {
- throw new RuntimeException("Mutually exclusive arguments passed into grab: ${keys.intersect(badArgs) + a}")
+ throw new RuntimeException("Mutually exclusive arguments passed into grab: ${keys.intersect(badArgs) + key}")
}
}
// check the kill switch
if (!enableGrapes) {
- return [] as URI[]
+ return new URI[0]
}
boolean populateDepsInfo = (depsInfo != null)
-
Set<IvyGrabRecord> localDeps = getLoadedDepsForLoader(loader)
-
- dependencies.each {
- IvyGrabRecord igr = createGrabRecord(it)
+ dependencies.each { Map dep ->
+ IvyGrabRecord igr = createGrabRecord(dep)
grabRecordsForCurrDependencies.add(igr)
localDeps.add(igr)
}
@@ -653,26 +622,24 @@ class GrapeIvy implements GrapeEngine {
// with a different version
ResolveReport report = null
try {
- report = getDependencies(args, *localDeps.asList().reverse())
+ report = getDependencies(args, (localDeps as IvyGrabRecord[]).reverse(true))
} catch (Exception e) {
- // clean-up the state first
localDeps.removeAll(grabRecordsForCurrDependencies)
grabRecordsForCurrDependencies.clear()
throw e
}
List<URI> results = []
- for (ArtifactDownloadReport adl in report.allArtifactsReports) {
- //TODO check artifact type, jar vs library, etc
- if (adl.localFile) {
- results += adl.localFile.toURI()
+ for (ArtifactDownloadReport adl : report.getAllArtifactsReports()) {
+ // TODO: check artifact type, jar vs library, etc.
+ if (adl.getLocalFile()) {
+ results += adl.getLocalFile().toURI()
}
}
if (populateDepsInfo) {
- def deps = report.dependencies
- deps.each { depNode ->
- def id = depNode.id
+ report.getDependencies().each { ivyNode ->
+ def id = ivyNode.id
depsInfo << ['group': id.organisation, 'module': id.name, 'revision': id.revision]
}
}
@@ -680,57 +647,46 @@ class GrapeIvy implements GrapeEngine {
results as URI[]
}
- @CompileStatic
private Set<IvyGrabRecord> getLoadedDepsForLoader(ClassLoader loader) {
- Set<IvyGrabRecord> localDeps = loadedDeps.get(loader)
- if (localDeps == null) {
- // use a linked set to preserve initial insertion order
- localDeps = new LinkedHashSet<IvyGrabRecord>()
- loadedDeps.put(loader, localDeps)
- }
- localDeps
+ // use a LinkedHashSet to preserve the initial insertion order
+ loadedDeps.computeIfAbsent(loader, k -> [] as LinkedHashSet)
}
@Override
Map[] listDependencies(ClassLoader classLoader) {
- if (loadedDeps.containsKey(classLoader)) {
- List<Map> results = []
- loadedDeps[classLoader].each { IvyGrabRecord grabbed ->
- def dep = [
- group : grabbed.mrid.organisation,
- module : grabbed.mrid.name,
- version: grabbed.mrid.revision
- ]
- if (grabbed.conf != DEF_CONFIG) {
- dep.conf = grabbed.conf
- }
- if (grabbed.changing) {
- dep.changing = grabbed.changing
- }
- if (!grabbed.transitive) {
- dep.transitive = grabbed.transitive
- }
- if (!grabbed.force) {
- dep.force = grabbed.force
- }
- if (grabbed.classifier) {
- dep.classifier = grabbed.classifier
- }
- if (grabbed.ext) {
- dep.ext = grabbed.ext
- }
- if (grabbed.type) {
- dep.type = grabbed.type
- }
- results << dep
+ List<? extends Map> results = loadedDeps[classLoader]?.collect { IvyGrabRecord grabbed ->
+ def dep = [
+ group : grabbed.mrid.getOrganisation(),
+ module : grabbed.mrid.getName(),
+ version: grabbed.mrid.getRevision()
+ ]
+ if (grabbed.conf != DEFAULT_CONF) {
+ dep.conf = grabbed.conf
+ }
+ if (grabbed.changing) {
+ dep.changing = grabbed.changing
+ }
+ if (!grabbed.transitive) {
+ dep.transitive = grabbed.transitive
+ }
+ if (!grabbed.force) {
+ dep.force = grabbed.force
}
- return results
+ if (grabbed.classifier) {
+ dep.classifier = grabbed.classifier
+ }
+ if (grabbed.ext) {
+ dep.ext = grabbed.ext
+ }
+ if (grabbed.type) {
+ dep.type = grabbed.type
+ }
+ dep
}
- null
+ results as Map[]
}
@Override
- @CompileStatic
void addResolver(@NamedParams([
@NamedParam(value='name', type=String, required=true),
@NamedParam(value='root', type=String, required=true),
@@ -739,8 +695,8 @@ class GrapeIvy implements GrapeEngine {
def resolver = new IBiblioResolver(
name: (String) args.name,
root: (String) args.root,
- m2compatible: (boolean) args.getOrDefault('m2Compatible', Boolean.TRUE),
- settings: (ResolverSettings) settings
+ settings: (ResolverSettings) settings,
+ m2compatible: (boolean) args.getOrDefault('m2Compatible', Boolean.TRUE)
)
def chainResolver = (ChainResolver) settings.getResolver('downloadGrapes')
@@ -753,38 +709,14 @@ class GrapeIvy implements GrapeEngine {
}
@CompileStatic
+@EqualsAndHashCode
class IvyGrabRecord {
ModuleRevisionId mrid
List<String> conf
- boolean changing
- boolean transitive
- boolean force
- String classifier
String ext
String type
-
- @Override
- int hashCode() {
- (mrid.hashCode() ^ conf.hashCode()
- ^ (changing ? 0xaaaaaaaa : 0x55555555)
- ^ (transitive ? 0xbbbbbbbb : 0x66666666)
- ^ (force ? 0xcccccccc : 0x77777777)
- ^ (classifier ? classifier.hashCode() : 0)
- ^ (ext ? ext.hashCode() : 0)
- ^ (type ? type.hashCode() : 0))
- }
-
- @Override
- boolean equals(Object that) {
- if (that instanceof IvyGrabRecord) {
- return (this.mrid == that.mrid)
- && (this.conf == that.conf)
- && (this.changing == that.changing)
- && (this.transitive == that.transitive)
- && (this.force == that.force)
- && (this.classifier == that.classifier)
- && (this.ext == that.ext)
- && (this.type == that.type)
- }
- }
+ String classifier
+ boolean force
+ boolean changing
+ boolean transitive
}
[groovy] 05/19: GROOVY-8000: pass interface with adjusted generics
to recursive collect
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 1c07ed8d904c3fdf93a60dafd619af33d0a47c48
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Aug 20 17:26:24 2020 -0500
GROOVY-8000: pass interface with adjusted generics to recursive collect
closes #1347
(cherry picked from commit c514ae0c6889e5edd127f7a890cbbec07f1517c4)
---
.../codehaus/groovy/transform/trait/Traits.java | 21 +++++++---------
.../traitx/TraitASTTransformationTest.groovy | 29 ++++++++++++++++++++++
2 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/Traits.java b/src/main/java/org/codehaus/groovy/transform/trait/Traits.java
index b752ebb..e051ad2 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/Traits.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/Traits.java
@@ -284,15 +284,12 @@ public abstract class Traits {
* @param cNode a class node
* @param interfaces ordered set of interfaces
*/
- public static LinkedHashSet<ClassNode> collectAllInterfacesReverseOrder(ClassNode cNode, LinkedHashSet<ClassNode> interfaces) {
- if (cNode.isInterface())
- interfaces.add(cNode);
-
+ public static LinkedHashSet<ClassNode> collectAllInterfacesReverseOrder(final ClassNode cNode, final LinkedHashSet<ClassNode> interfaces) {
+ if (cNode.isInterface()) interfaces.add(cNode);
ClassNode[] directInterfaces = cNode.getInterfaces();
- for (int i = directInterfaces.length-1; i >=0 ; i--) {
- final ClassNode anInterface = directInterfaces[i];
- interfaces.add(GenericsUtils.parameterizeType(cNode,anInterface));
- collectAllInterfacesReverseOrder(anInterface, interfaces);
+ for (int i = directInterfaces.length - 1; i >= 0; i -= 1) {
+ ClassNode iNode = GenericsUtils.parameterizeType(cNode, directInterfaces[i]);
+ if (interfaces.add(iNode)) collectAllInterfacesReverseOrder(iNode, interfaces);
}
return interfaces;
}
@@ -363,15 +360,15 @@ public abstract class Traits {
}
/**
- * Find all traits associated with the given classnode
+ * Find all traits associated with the given type.
*
* @param cNode the given classnode
* @return the list of ordered trait classnodes
*/
- public static List<ClassNode> findTraits(ClassNode cNode) {
- LinkedHashSet<ClassNode> interfaces = new LinkedHashSet<ClassNode>();
+ public static List<ClassNode> findTraits(final ClassNode cNode) {
+ LinkedHashSet<ClassNode> interfaces = new LinkedHashSet<>();
collectAllInterfacesReverseOrder(cNode, interfaces);
- List<ClassNode> traits = new LinkedList<ClassNode>();
+ List<ClassNode> traits = new LinkedList<>();
for (ClassNode candidate : interfaces) {
if (isAnnotatedWithTrait(candidate)) {
traits.add(candidate);
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index e785703..9c1c7c9 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -3206,6 +3206,35 @@ final class TraitASTTransformationTest {
'''
}
+ @Test // GROOVY-8000
+ void testTraitMultiLevelGenerics() {
+ assertScript '''
+ trait TopTrait<X> { X getSomeThing() {}
+ }
+ trait MiddleTrait<Y> implements TopTrait<Y> {
+ }
+ trait BottomTrait<Z> implements MiddleTrait<Z> {
+ }
+ class Implementation implements BottomTrait<String> {
+ }
+
+ assert new Implementation().getSomeThing() == null
+ '''
+
+ assertScript '''
+ trait TopTrait<T> { T getSomeThing() {}
+ }
+ trait MiddleTrait<T> implements TopTrait<T> {
+ }
+ trait BottomTrait<T> implements MiddleTrait<T> {
+ }
+ class Implementation implements BottomTrait<String> {
+ }
+
+ assert new Implementation().getSomeThing() == null
+ '''
+ }
+
@Test // GROOVY-9660
void testAsGenericsParam() {
assertScript '''
[groovy] 11/19: GROOVY-9702: source retention for @ASTTest and
improved AST modification (closes #1352)
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit d26be15efc8a2bdf15f8001fc308b9a5eb320504
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Aug 25 12:14:50 2020 -0500
GROOVY-9702: source retention for @ASTTest and improved AST modification (closes #1352)
(cherry picked from commit 74c37bdd7979c4461862e14c2016e74679dbd3d2)
---
.../org/codehaus/groovy/transform/ASTTestTransformation.groovy | 6 +++++-
src/main/java/groovy/transform/ASTTest.java | 5 +++--
src/test/groovy/transform/AnnotationCollectorLegacyTest.groovy | 6 +++---
src/test/groovy/transform/AnnotationCollectorTest.groovy | 2 +-
4 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy b/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
index 15ca578..e14a8fe 100644
--- a/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
+++ b/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
@@ -25,9 +25,11 @@ import org.codehaus.groovy.ast.ClassCodeVisitorSupport
import org.codehaus.groovy.ast.ClassHelper
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.Parameter
import org.codehaus.groovy.ast.expr.ClosureExpression
import org.codehaus.groovy.ast.expr.PropertyExpression
import org.codehaus.groovy.ast.expr.VariableExpression
+import org.codehaus.groovy.ast.stmt.EmptyStatement
import org.codehaus.groovy.ast.stmt.Statement
import org.codehaus.groovy.control.CompilationUnit
import org.codehaus.groovy.control.CompilePhase
@@ -72,7 +74,9 @@ class ASTTestTransformation implements ASTTransformation, CompilationUnitAware {
}
// convert value into node metadata so that the expression doesn't mix up with other AST xforms like STC
annotationNode.setNodeMetaData(ASTTestTransformation, member)
- annotationNode.members.remove('value')
+ annotationNode.setMember('value', new ClosureExpression(
+ Parameter.EMPTY_ARRAY, EmptyStatement.INSTANCE))
+ member.variableScope.@parent = null
def pcallback = compilationUnit.progressCallback
def callback = new CompilationUnit.ProgressCallback() {
diff --git a/src/main/java/groovy/transform/ASTTest.java b/src/main/java/groovy/transform/ASTTest.java
index 1779161..1c144a8 100644
--- a/src/main/java/groovy/transform/ASTTest.java
+++ b/src/main/java/groovy/transform/ASTTest.java
@@ -18,6 +18,7 @@
*/
package groovy.transform;
+import groovy.lang.Closure;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.transform.GroovyASTTransformationClass;
@@ -52,7 +53,7 @@ import java.lang.annotation.Target;
* @since 2.0.0
*/
@Documented
-@Retention(RetentionPolicy.RUNTIME)
+@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.PACKAGE, ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@GroovyASTTransformationClass("org.codehaus.groovy.transform.ASTTestTransformation")
public @interface ASTTest {
@@ -64,5 +65,5 @@ public @interface ASTTest {
/**
* A closure which is executed against the annotated node after the specified phase has completed.
*/
- Class value();
+ Class<? extends /*@ClosureParams(value=FromString.class,options="")*/ Closure<?>> value();
}
diff --git a/src/test/groovy/transform/AnnotationCollectorLegacyTest.groovy b/src/test/groovy/transform/AnnotationCollectorLegacyTest.groovy
index 0268602..304c03c 100644
--- a/src/test/groovy/transform/AnnotationCollectorLegacyTest.groovy
+++ b/src/test/groovy/transform/AnnotationCollectorLegacyTest.groovy
@@ -162,7 +162,7 @@ class AnnotationCollectorLegacyTest extends GroovyTestCase {
}
void testAST() {
- assertScript """
+ assertScript '''
import groovy.transform.*
@AnnotationCollector(value = [ToString, EqualsAndHashCode, Sortable], serializeClass = Alias)
@interface Alias {}
@@ -178,11 +178,11 @@ class AnnotationCollectorLegacyTest extends GroovyTestCase {
class Foo {
Integer a, b
}
- assert Foo.class.annotations.size() == 4
+ assert Foo.class.annotations.size() == 3
assert new Foo(a: 1, b: 2).toString() == "Foo(2)"
assert Alias.value().length == 0
assert Alias.value() instanceof Object[][]
- """
+ '''
}
void testConflictingAnnotations() {
diff --git a/src/test/groovy/transform/AnnotationCollectorTest.groovy b/src/test/groovy/transform/AnnotationCollectorTest.groovy
index 6f519a5..f78235b 100644
--- a/src/test/groovy/transform/AnnotationCollectorTest.groovy
+++ b/src/test/groovy/transform/AnnotationCollectorTest.groovy
@@ -185,7 +185,7 @@ class AnnotationCollectorTest extends GroovyTestCase {
class Foo {
Integer a, b
}
- assert Foo.class.annotations.size() == 4
+ assert Foo.class.annotations.size() == 3
assert new Foo(a: 1, b: 2).toString() == "Foo(2)"
def data = Alias.getAnnotation(AnnotationCollector).serializeClass().value()
assert data.length == 0
[groovy] 03/19: fix parameter generics and modifiers
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit c3ada8f45165de47dbf41dcfcfb8ad96016eda70
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Aug 18 13:08:48 2020 -0500
fix parameter generics and modifiers
(cherry picked from commit 5a3bf184104c65e6a4bb5d30a13a93e1629bc82e)
---
.../org/codehaus/groovy/classgen/Verifier.java | 401 ++++++++++-----------
1 file changed, 189 insertions(+), 212 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index 1be8f1f..6a97311 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -74,7 +74,6 @@ import org.objectweb.asm.Opcodes;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -90,17 +89,23 @@ import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;
import static java.util.stream.Collectors.joining;
import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated;
-import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
import static org.apache.groovy.ast.tools.ConstructorNodeUtils.getFirstIfSpecialConstructorCall;
import static org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants;
+import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
import static org.apache.groovy.ast.tools.MethodNodeUtils.getPropertyName;
import static org.apache.groovy.ast.tools.MethodNodeUtils.methodDescriptorWithoutReturnType;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
import static org.codehaus.groovy.ast.tools.GeneralUtils.bytecodeX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.getSetterName;
import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
import static org.codehaus.groovy.ast.tools.GenericsUtils.addMethodGenerics;
import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpec;
@@ -130,22 +135,19 @@ import static org.codehaus.groovy.ast.tools.PropertyNodeUtils.adjustPropertyModi
*/
public class Verifier implements GroovyClassVisitor, Opcodes {
- public static final String STATIC_METACLASS_BOOL = "__$stMC";
public static final String SWAP_INIT = "__$swapInit";
+ public static final String STATIC_METACLASS_BOOL = "__$stMC";
public static final String INITIAL_EXPRESSION = "INITIAL_EXPRESSION";
public static final String DEFAULT_PARAMETER_GENERATED = "DEFAULT_PARAMETER_GENERATED";
-
- // NOTE: timeStamp constants shouldn't belong to Verifier but kept here
- // for binary compatibility
- public static final String __TIMESTAMP = "__timeStamp";
- public static final String __TIMESTAMP__ = "__timeStamp__239_neverHappen";
- private static final Parameter[] SET_METACLASS_PARAMS = new Parameter[]{
- new Parameter(ClassHelper.METACLASS_TYPE, "mc")
- };
+ private static final Parameter[] SET_METACLASS_PARAMS = {new Parameter(ClassHelper.METACLASS_TYPE, "mc")};
private static final Class<?> GENERATED_ANNOTATION = Generated.class;
private static final Class<?> INTERNAL_ANNOTATION = Internal.class;
+ // NOTE: timeStamp constants shouldn't belong to Verifier but kept here for binary compatibility
+ public static final String __TIMESTAMP = "__timeStamp";
+ public static final String __TIMESTAMP__ = "__timeStamp__239_neverHappen";
+
private ClassNode classNode;
private MethodNode methodNode;
@@ -153,7 +155,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return classNode;
}
- protected void setClassNode(ClassNode classNode) {
+ protected void setClassNode(final ClassNode classNode) {
this.classNode = classNode;
}
@@ -161,7 +163,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return methodNode;
}
- private static FieldNode setMetaClassFieldIfNotExists(ClassNode node, FieldNode metaClassField) {
+ private static FieldNode setMetaClassFieldIfNotExists(final ClassNode node, FieldNode metaClassField) {
if (metaClassField != null) return metaClassField;
final String classInternalName = BytecodeHelper.getClassInternalName(node);
metaClassField =
@@ -175,7 +177,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return metaClassField;
}
- private static FieldNode getMetaClassField(ClassNode node) {
+ private static FieldNode getMetaClassField(final ClassNode node) {
FieldNode ret = node.getDeclaredField("metaClass");
if (ret != null) {
ClassNode mcFieldType = ret.getType();
@@ -216,11 +218,11 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
ClassNode[] classNodes = classNode.getInterfaces();
- List<String> interfaces = new ArrayList<String>();
+ List<String> interfaces = new ArrayList<>();
for (ClassNode classNode : classNodes) {
interfaces.add(classNode.getName());
}
- Set<String> interfaceSet = new HashSet<String>(interfaces);
+ Set<String> interfaceSet = new HashSet<>(interfaces);
if (interfaceSet.size() != interfaces.size()) {
throw new RuntimeParserException("Duplicate interfaces in implements list: " + interfaces, classNode);
}
@@ -251,16 +253,15 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
checkFinalVariables(node);
}
- private void checkFinalVariables(ClassNode node) {
- FinalVariableAnalyzer analyzer = new FinalVariableAnalyzer(null, getFinalVariablesCallback());
- analyzer.visitClass(node);
-
+ private void checkFinalVariables(final ClassNode node) {
+ GroovyClassVisitor visitor = new FinalVariableAnalyzer(null, getFinalVariablesCallback());
+ visitor.visitClass(node);
}
protected FinalVariableAnalyzer.VariableNotFinalCallback getFinalVariablesCallback() {
return new FinalVariableAnalyzer.VariableNotFinalCallback() {
@Override
- public void variableNotFinal(Variable var, Expression bexp) {
+ public void variableNotFinal(Variable var, final Expression bexp) {
if (var instanceof VariableExpression) {
var = ((VariableExpression) var).getAccessedVariable();
}
@@ -280,8 +281,8 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
};
}
- private static void checkForDuplicateMethods(ClassNode cn) {
- Set<String> descriptors = new HashSet<String>();
+ private static void checkForDuplicateMethods(final ClassNode cn) {
+ Set<String> descriptors = new HashSet<>();
for (MethodNode mn : cn.getMethods()) {
if (mn.isSynthetic()) continue;
String mySig = methodDescriptorWithoutReturnType(mn);
@@ -298,14 +299,14 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- private static String scriptBodySignatureWithoutReturnType(ClassNode cn) {
+ private static String scriptBodySignatureWithoutReturnType(final ClassNode cn) {
for (MethodNode mn : cn.getMethods()) {
if (mn.isScriptBody()) return methodDescriptorWithoutReturnType(mn);
}
return null;
}
- private static FieldNode checkFieldDoesNotExist(ClassNode node, String fieldName) {
+ private static FieldNode checkFieldDoesNotExist(final ClassNode node, final String fieldName) {
FieldNode ret = node.getDeclaredField(fieldName);
if (ret != null) {
if (isPublic(ret.getModifiers()) &&
@@ -319,7 +320,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return null;
}
- private static void addFastPathHelperFieldsAndHelperMethod(ClassNode node, final String classInternalName, boolean knownSpecialCase) {
+ private static void addFastPathHelperFieldsAndHelperMethod(final ClassNode node, final String classInternalName, final boolean knownSpecialCase) {
if (node.getNodeMetaData(ClassNodeSkip.class) != null) return;
FieldNode stMCB = checkFieldDoesNotExist(node, STATIC_METACLASS_BOOL);
if (stMCB == null) {
@@ -331,7 +332,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- protected void addDefaultConstructor(ClassNode node) {
+ protected void addDefaultConstructor(final ClassNode node) {
if (!node.getDeclaredConstructors().isEmpty()) return;
ConstructorNode constructor = new ConstructorNode(ACC_PUBLIC, new BlockStatement());
@@ -357,7 +358,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
ClassNode.EMPTY_ARRAY,
new BytecodeSequence(new BytecodeInstruction() {
@Override
- public void visit(MethodVisitor mv) {
+ public void visit(final MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
if (BytecodeHelper.isClassLiteralPossible(node) || BytecodeHelper.isSameCompilationUnit(classNode, node)) {
@@ -397,7 +398,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
);
}
- protected void addGroovyObjectInterfaceAndMethods(ClassNode node, final String classInternalName) {
+ protected void addGroovyObjectInterfaceAndMethods(final ClassNode node, final String classInternalName) {
if (!node.isDerivedFromGroovyObject()) node.addInterface(ClassHelper.make(GroovyObject.class));
FieldNode metaClassField = getMetaClassField(node);
@@ -415,7 +416,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
ClassNode.EMPTY_ARRAY,
new BytecodeSequence(new BytecodeInstruction() {
@Override
- public void visit(MethodVisitor mv) {
+ public void visit(final MethodVisitor mv) {
Label nullLabel = new Label();
/*
* the code is:
@@ -464,7 +465,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
} else {
setMetaClassCode = new BytecodeSequence(new BytecodeInstruction() {
@Override
- public void visit(MethodVisitor mv) {
+ public void visit(final MethodVisitor mv) {
/*
* the code is (meta class is stored in 1):
* this.metaClass = <1>
@@ -496,8 +497,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
* call will either be made to ClassNode.addSyntheticMethod() or ClassNode.addMethod(). If a non-synthetic method
* is to be added the ACC_SYNTHETIC modifier is removed if it has been accidentally supplied.
*/
- protected MethodNode addMethod(ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters,
- ClassNode[] exceptions, Statement code) {
+ protected MethodNode addMethod(final ClassNode node, final boolean shouldBeSynthetic, final String name, final int modifiers, final ClassNode returnType, final Parameter[] parameters, final ClassNode[] exceptions, final Statement code) {
if (shouldBeSynthetic) {
return node.addSyntheticMethod(name, modifiers, returnType, parameters, exceptions, code);
} else {
@@ -506,23 +506,22 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
// for binary compatibility only, don't use or override this
- protected void addMethod$$bridge(ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters,
- ClassNode[] exceptions, Statement code) {
+ protected void addMethod$$bridge(final ClassNode node, final boolean shouldBeSynthetic, final String name, final int modifiers, final ClassNode returnType, final Parameter[] parameters, final ClassNode[] exceptions, final Statement code) {
addMethod(node, shouldBeSynthetic, name, modifiers, returnType, parameters, exceptions, code);
}
@Deprecated
- protected void addTimeStamp(ClassNode node) {
+ protected void addTimeStamp(final ClassNode node) {
}
- private static void checkReturnInObjectInitializer(List<Statement> init) {
+ private static void checkReturnInObjectInitializer(final List<Statement> init) {
GroovyCodeVisitor visitor = new CodeVisitorSupport() {
@Override
- public void visitClosureExpression(ClosureExpression expression) {
+ public void visitClosureExpression(final ClosureExpression expression) {
// return is OK in closures in object initializers
}
@Override
- public void visitReturnStatement(ReturnStatement statement) {
+ public void visitReturnStatement(final ReturnStatement statement) {
throw new RuntimeParserException("'return' is not allowed in object initializer", statement);
}
};
@@ -532,14 +531,14 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
@Override
- public void visitConstructor(ConstructorNode node) {
+ public void visitConstructor(final ConstructorNode node) {
Statement stmt = node.getCode();
if (stmt != null) {
stmt.visit(new VerifierCodeVisitor(getClassNode()));
// check for uninitialized-this references
stmt.visit(new CodeVisitorSupport() {
@Override
- public void visitClosureExpression(ClosureExpression ce) {
+ public void visitClosureExpression(final ClosureExpression ce) {
boolean oldInClosure = inClosure;
inClosure = true;
super.visitClosureExpression(ce);
@@ -547,7 +546,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
@Override
- public void visitConstructorCallExpression(ConstructorCallExpression cce) {
+ public void visitConstructorCallExpression(final ConstructorCallExpression cce) {
boolean oldIsSpecialConstructorCall = inSpecialConstructorCall;
inSpecialConstructorCall |= cce.isSpecialCall();
super.visitConstructorCallExpression(cce);
@@ -555,7 +554,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
@Override
- public void visitMethodCallExpression(MethodCallExpression mce) {
+ public void visitMethodCallExpression(final MethodCallExpression mce) {
if (inSpecialConstructorCall && isThisObjectExpression(mce)) {
MethodNode methodTarget = mce.getMethodTarget();
if (methodTarget == null || !(methodTarget.isStatic() || classNode.getOuterClasses().contains(methodTarget.getDeclaringClass()))) {
@@ -573,7 +572,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
@Override
- public void visitVariableExpression(VariableExpression ve) {
+ public void visitVariableExpression(final VariableExpression ve) {
// before this/super ctor call completes, only params and static or outer members are accessible
if (inSpecialConstructorCall && (ve.isThisExpression() || ve.isSuperExpression() || isNonStaticMemberAccess(ve))) {
throw newVariableError(ve.getName(), ve.getLineNumber() > 0 ? ve : node); // TODO: context for default argument
@@ -584,13 +583,13 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
private boolean inClosure, inSpecialConstructorCall;
- private boolean isNonStaticMemberAccess(VariableExpression ve) {
+ private boolean isNonStaticMemberAccess(final VariableExpression ve) {
Variable variable = ve.getAccessedVariable();
return !inClosure && variable != null && !isStatic(variable.getModifiers())
&& !(variable instanceof DynamicVariable) && !(variable instanceof Parameter);
}
- private boolean isThisObjectExpression(MethodCallExpression mce) {
+ private boolean isThisObjectExpression(final MethodCallExpression mce) {
if (mce.isImplicitThis()) {
return true;
} else if (mce.getObjectExpression() instanceof VariableExpression) {
@@ -601,7 +600,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- private GroovyRuntimeException newVariableError(String name, ASTNode node) {
+ private GroovyRuntimeException newVariableError(final String name, final ASTNode node) {
RuntimeParserException rpe = new RuntimeParserException("Cannot reference '" + name +
"' before supertype constructor has been called. Possible causes:\n" +
"You attempted to access an instance field, method, or property.\n" +
@@ -614,8 +613,8 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
@Override
- public void visitMethod(MethodNode node) {
- // GROOVY-3712 - if it's an MOP method, it's an error as they aren't supposed to exist before ACG is invoked
+ public void visitMethod(final MethodNode node) {
+ // GROOVY-3712: if it's an MOP method, it's an error as they aren't supposed to exist before ACG is invoked
if (MopWriter.isMopMethod(node.getName())) {
throw new RuntimeParserException("Found unexpected MOP methods in the class node for " + classNode.getName() + "(" + node.getName() + ")", classNode);
}
@@ -630,7 +629,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- private static void adjustTypesIfStaticMainMethod(MethodNode node) {
+ private static void adjustTypesIfStaticMainMethod(final MethodNode node) {
if (node.getName().equals("main") && node.isStatic()) {
Parameter[] params = node.getParameters();
if (params.length == 1) {
@@ -646,16 +645,16 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- protected void addReturnIfNeeded(MethodNode node) {
+ protected void addReturnIfNeeded(final MethodNode node) {
ReturnAdder adder = new ReturnAdder();
adder.visitMethod(node);
}
@Override
- public void visitField(FieldNode node) {
+ public void visitField(final FieldNode node) {
}
- private boolean methodNeedsReplacement(MethodNode m) {
+ private boolean methodNeedsReplacement(final MethodNode m) {
// no method found, we need to replace
if (m == null) return true;
// method is in current class, nothing to be done
@@ -666,7 +665,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
@Override
- public void visitProperty(PropertyNode node) {
+ public void visitProperty(final PropertyNode node) {
String name = node.getName();
FieldNode field = node.getField();
@@ -698,35 +697,32 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
int getterModifiers = accessorModifiers;
// don't make static accessors final
if (node.isStatic()) {
- getterModifiers = ~ACC_FINAL & getterModifiers;
+ getterModifiers &= ~ACC_FINAL;
}
if (getterBlock != null) {
visitGetter(node, getterBlock, getterModifiers, getterName);
- if (ClassHelper.boolean_TYPE == node.getType() || ClassHelper.Boolean_TYPE == node.getType()) {
- String secondGetterName = "is" + capitalize(name);
- visitGetter(node, getterBlock, getterModifiers, secondGetterName);
+ if (node.getType().equals(ClassHelper.boolean_TYPE) || node.getType().equals(ClassHelper.Boolean_TYPE)) {
+ visitGetter(node, getterBlock, getterModifiers, "is" + capitalize(name));
}
}
if (setterBlock != null) {
Parameter[] setterParameterTypes = {new Parameter(node.getType(), "value")};
- MethodNode setter =
- new MethodNode(setterName, accessorModifiers, ClassHelper.VOID_TYPE, setterParameterTypes, ClassNode.EMPTY_ARRAY, setterBlock);
+ MethodNode setter = new MethodNode(setterName, accessorModifiers, ClassHelper.VOID_TYPE, setterParameterTypes, ClassNode.EMPTY_ARRAY, setterBlock);
setter.setSynthetic(true);
addPropertyMethod(setter);
visitMethod(setter);
}
}
- private void visitGetter(PropertyNode node, Statement getterBlock, int getterModifiers, String getterName) {
- MethodNode getter =
- new MethodNode(getterName, getterModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
+ private void visitGetter(final PropertyNode node, final Statement getterBlock, final int getterModifiers, final String getterName) {
+ MethodNode getter = new MethodNode(getterName, getterModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
getter.setSynthetic(true);
addPropertyMethod(getter);
visitMethod(getter);
}
- protected void addPropertyMethod(MethodNode method) {
+ protected void addPropertyMethod(final MethodNode method) {
classNode.addMethod(method);
markAsGenerated(classNode, method);
// GROOVY-4415 / GROOVY-4645: check that there's no abstract method which corresponds to this one
@@ -763,7 +759,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
/**
* Creates a new method for each combination of default parameter expressions.
*/
- protected void addDefaultParameterMethods(ClassNode type) {
+ protected void addDefaultParameterMethods(final ClassNode type) {
List<MethodNode> methods = new ArrayList<>(type.getMethods());
addDefaultParameters(methods, (arguments, params, method) -> {
BlockStatement code = new BlockStatement();
@@ -790,14 +786,14 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
private boolean inClosure;
@Override
- public void visitClosureExpression(ClosureExpression e) {
+ public void visitClosureExpression(final ClosureExpression e) {
boolean prev = inClosure; inClosure = true;
super.visitClosureExpression(e);
inClosure = prev;
}
@Override
- public void visitVariableExpression(VariableExpression e) {
+ public void visitVariableExpression(final VariableExpression e) {
if (e.getAccessedVariable() instanceof Parameter) {
Parameter p = (Parameter) e.getAccessedVariable();
if (p.hasInitialExpression() && !Arrays.asList(params).contains(p)) {
@@ -821,7 +817,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
visitor.visitArgumentlistExpression(arguments);
// if variable was created to capture an initial value expression, reference it in arguments as well
- for (ListIterator<Expression> it = arguments.getExpressions().listIterator(); it.hasNext();) {
+ for (ListIterator<Expression> it = arguments.getExpressions().listIterator(); it.hasNext(); ) {
Expression argument = it.next();
if (argument instanceof CastExpression) {
argument = ((CastExpression) argument).getExpression();
@@ -851,7 +847,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
// GROOVY-5681: set anon. inner enclosing method reference
visitor = new CodeVisitorSupport() {
@Override
- public void visitConstructorCallExpression(ConstructorCallExpression call) {
+ public void visitConstructorCallExpression(final ConstructorCallExpression call) {
if (call.isUsingAnonymousInnerClass()) {
call.getType().setEnclosingMethod(newMethod);
}
@@ -868,11 +864,11 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
/**
* Creates a new constructor for each combination of default parameter expressions.
*/
- protected void addDefaultParameterConstructors(ClassNode type) {
+ protected void addDefaultParameterConstructors(final ClassNode type) {
List<ConstructorNode> constructors = new ArrayList<>(type.getDeclaredConstructors());
addDefaultParameters(constructors, (arguments, params, method) -> {
// GROOVY-9151: check for references to parameters that have been removed
- for (ListIterator<Expression> it = arguments.getExpressions().listIterator(); it.hasNext();) {
+ for (ListIterator<Expression> it = arguments.getExpressions().listIterator(); it.hasNext(); ) {
Expression argument = it.next();
if (argument instanceof CastExpression) {
argument = ((CastExpression) argument).getExpression();
@@ -891,7 +887,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
GroovyCodeVisitor visitor = new CodeVisitorSupport() {
@Override
- public void visitVariableExpression(VariableExpression e) {
+ public void visitVariableExpression(final VariableExpression e) {
if (e.getAccessedVariable() instanceof Parameter) {
Parameter p = (Parameter) e.getAccessedVariable();
if (p.hasInitialExpression() && !Arrays.asList(params).contains(p)) {
@@ -913,7 +909,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
});
}
- protected void addConstructor(Parameter[] newParams, ConstructorNode ctor, Statement code, ClassNode type) {
+ protected void addConstructor(final Parameter[] newParams, final ConstructorNode ctor, final Statement code, final ClassNode type) {
ConstructorNode newConstructor = type.addConstructor(ctor.getModifiers(), newParams, ctor.getExceptions(), code);
newConstructor.putNodeMetaData(DEFAULT_PARAMETER_GENERATED, Boolean.TRUE);
markAsGenerated(type, newConstructor);
@@ -922,7 +918,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
// set anon. inner enclosing method reference
code.visit(new CodeVisitorSupport() {
@Override
- public void visitConstructorCallExpression(ConstructorCallExpression call) {
+ public void visitConstructorCallExpression(final ConstructorCallExpression call) {
if (call.isUsingAnonymousInnerClass()) {
call.getType().setEnclosingMethod(newConstructor);
}
@@ -934,7 +930,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
/**
* Creates a new helper method for each combination of default parameter expressions.
*/
- protected void addDefaultParameters(List<? extends MethodNode> methods, DefaultArgsAction action) {
+ protected void addDefaultParameters(final List<? extends MethodNode> methods, final DefaultArgsAction action) {
for (MethodNode method : methods) {
if (method.hasDefaultValue()) {
addDefaultParameters(action, method);
@@ -942,7 +938,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- protected void addDefaultParameters(DefaultArgsAction action, MethodNode method) {
+ protected void addDefaultParameters(final DefaultArgsAction action, final MethodNode method) {
Parameter[] parameters = method.getParameters();
long n = Arrays.stream(parameters).filter(Parameter::hasInitialExpression).count();
@@ -1006,7 +1002,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- protected void addInitialization(ClassNode node, ConstructorNode constructorNode) {
+ protected void addInitialization(final ClassNode node, final ConstructorNode constructorNode) {
Statement firstStatement = constructorNode.getFirstStatement();
// if some transformation decided to generate constructor then it probably knows who it does
if (firstStatement instanceof BytecodeSequence)
@@ -1064,7 +1060,6 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
newBlock.setSourcePosition(block);
constructorNode.setCode(newBlock);
-
if (!staticStatements.isEmpty()) {
if (isEnum) {
/*
@@ -1086,7 +1081,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
* When InnerClassVisitor adds <code>this.this$0 = $p$n</code>, it adds it
* as a BlockStatement having that ExpressionStatement.
*/
- private Statement getImplicitThis$0StmtIfInnerClass(List<Statement> otherStatements) {
+ private Statement getImplicitThis$0StmtIfInnerClass(final List<Statement> otherStatements) {
if (!(classNode instanceof InnerClassNode)) return null;
for (Statement stmt : otherStatements) {
if (stmt instanceof BlockStatement) {
@@ -1117,20 +1112,19 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return false;
}
- protected void addFieldInitialization(List list, List staticList, FieldNode fieldNode,
- boolean isEnumClassNode, List initStmtsAfterEnumValuesInit, Set explicitStaticPropsInEnum) {
+ // TODO: add generics to collections
+ protected void addFieldInitialization(final List list, final List staticList, final FieldNode fieldNode, final boolean isEnumClassNode, final List initStmtsAfterEnumValuesInit, final Set explicitStaticPropsInEnum) {
Expression expression = fieldNode.getInitialExpression();
if (expression != null) {
- final FieldExpression fe = new FieldExpression(fieldNode);
+ final FieldExpression fe = fieldX(fieldNode);
if (fieldNode.getType().equals(ClassHelper.REFERENCE_TYPE) && ((fieldNode.getModifiers() & ACC_SYNTHETIC) != 0)) {
fe.setUseReferenceDirectly(true);
}
- ExpressionStatement statement =
- new ExpressionStatement(
- new BinaryExpression(
- fe,
- Token.newSymbol(Types.EQUAL, fieldNode.getLineNumber(), fieldNode.getColumnNumber()),
- expression));
+ Statement statement = stmt(binX(
+ fe,
+ Token.newSymbol(Types.ASSIGN, fieldNode.getLineNumber(), fieldNode.getColumnNumber()),
+ expression
+ ));
if (fieldNode.isStatic()) {
// GROOVY-3311: pre-defined constants added by groovy compiler for numbers/characters should be
// initialized first so that code dependent on it does not see their values as empty
@@ -1165,13 +1159,13 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
/**
* Capitalizes the start of the given bean property name.
*/
- public static String capitalize(String name) {
+ public static String capitalize(final String name) {
return BeanUtils.capitalize(name);
}
- protected Statement createGetterBlock(PropertyNode propertyNode, final FieldNode field) {
+ protected Statement createGetterBlock(final PropertyNode propertyNode, final FieldNode field) {
return new BytecodeSequence(new BytecodeInstruction() {
- public void visit(MethodVisitor mv) {
+ public void visit(final MethodVisitor mv) {
if (field.isStatic()) {
mv.visitFieldInsn(GETSTATIC, BytecodeHelper.getClassInternalName(classNode), field.getName(), BytecodeHelper.getTypeDescription(field.getType()));
} else {
@@ -1183,10 +1177,10 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
});
}
- protected Statement createSetterBlock(PropertyNode propertyNode, final FieldNode field) {
+ protected Statement createSetterBlock(final PropertyNode propertyNode, final FieldNode field) {
return new BytecodeSequence(new BytecodeInstruction() {
@Override
- public void visit(MethodVisitor mv) {
+ public void visit(final MethodVisitor mv) {
if (field.isStatic()) {
BytecodeHelper.load(mv, field.getType(), 0);
mv.visitFieldInsn(PUTSTATIC, BytecodeHelper.getClassInternalName(classNode), field.getName(), BytecodeHelper.getTypeDescription(field.getType()));
@@ -1200,10 +1194,10 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
});
}
- public void visitGenericType(GenericsType genericsType) {
+ public void visitGenericType(final GenericsType genericsType) {
}
- public static Long getTimestampFromFieldName(String fieldName) {
+ public static Long getTimestampFromFieldName(final String fieldName) {
if (fieldName.startsWith(__TIMESTAMP__)) {
try {
return Long.decode(fieldName.substring(__TIMESTAMP__.length()));
@@ -1214,16 +1208,15 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return null;
}
- public static long getTimestamp(Class<?> clazz) {
+ public static long getTimestamp(final Class<?> clazz) {
if (clazz.getClassLoader() instanceof GroovyClassLoader.InnerLoader) {
GroovyClassLoader.InnerLoader innerLoader = (GroovyClassLoader.InnerLoader) clazz.getClassLoader();
return innerLoader.getTimeStamp();
}
- final Field[] fields = clazz.getFields();
- for (int i = 0; i != fields.length; ++i) {
- if (isStatic(fields[i].getModifiers())) {
- Long timestamp = getTimestampFromFieldName(fields[i].getName());
+ for (Field field : clazz.getFields()) {
+ if (isStatic(field.getModifiers())) {
+ Long timestamp = getTimestampFromFieldName(field.getName());
if (timestamp != null) {
return timestamp;
}
@@ -1232,19 +1225,18 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return Long.MAX_VALUE;
}
- protected void addCovariantMethods(ClassNode classNode) {
- Map methodsToAdd = new HashMap();
- Map genericsSpec = new HashMap();
+ protected void addCovariantMethods(final ClassNode classNode) {
+ Map<String, MethodNode> methodsToAdd = new HashMap<>();
+ Map<String, ClassNode> genericsSpec = new HashMap<>();
// unimplemented abstract methods from interfaces
Map<String, MethodNode> abstractMethods = ClassNodeUtils.getDeclaredMethodsFromInterfaces(classNode);
- Map<String, MethodNode> allInterfaceMethods = new HashMap<String, MethodNode>(abstractMethods);
+ Map<String, MethodNode> allInterfaceMethods = new HashMap<>(abstractMethods);
ClassNodeUtils.addDeclaredMethodsFromAllInterfaces(classNode, allInterfaceMethods);
-
- List<MethodNode> declaredMethods = new ArrayList<MethodNode>(classNode.getMethods());
+ List<MethodNode> declaredMethods = new ArrayList<>(classNode.getMethods());
// remove all static, private and package private methods
- for (Iterator methodsIterator = declaredMethods.iterator(); methodsIterator.hasNext(); ) {
- MethodNode m = (MethodNode) methodsIterator.next();
+ for (Iterator<MethodNode> methodsIterator = declaredMethods.iterator(); methodsIterator.hasNext(); ) {
+ MethodNode m = methodsIterator.next();
abstractMethods.remove(m.getTypeDescriptor());
if (m.isStatic() || !(m.isPublic() || m.isProtected())) {
methodsIterator.remove();
@@ -1261,63 +1253,56 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
addCovariantMethods(classNode, declaredMethods, abstractMethods, methodsToAdd, genericsSpec);
- Map<String, MethodNode> declaredMethodsMap = new HashMap<String, MethodNode>();
+ Map<String, MethodNode> declaredMethodsMap = new HashMap<>();
if (!methodsToAdd.isEmpty()) {
for (MethodNode mn : declaredMethods) {
declaredMethodsMap.put(mn.getTypeDescriptor(), mn);
}
}
- for (Object o : methodsToAdd.entrySet()) {
- Map.Entry entry = (Map.Entry) o;
- MethodNode method = (MethodNode) entry.getValue();
+ for (Map.Entry<String, MethodNode> entry : methodsToAdd.entrySet()) {
// we skip bridge methods implemented in current class already
MethodNode mn = declaredMethodsMap.get(entry.getKey());
- if (mn != null && mn.getDeclaringClass().equals(classNode)) continue;
- addPropertyMethod(method);
+ if (mn == null || !mn.getDeclaringClass().equals(classNode)) {
+ addPropertyMethod(entry.getValue());
+ }
}
}
- private void addCovariantMethods(ClassNode classNode, List declaredMethods, Map abstractMethods, Map methodsToAdd, Map oldGenericsSpec) {
+ private void addCovariantMethods(final ClassNode classNode, final List<MethodNode> declaredMethods, final Map<String, MethodNode> abstractMethods, final Map<String, MethodNode> methodsToAdd, final Map<String, ClassNode> oldGenericsSpec) {
ClassNode sn = classNode.getUnresolvedSuperClass(false);
-
if (sn != null) {
- Map genericsSpec = createGenericsSpec(sn, oldGenericsSpec);
+ Map<String, ClassNode> genericsSpec = createGenericsSpec(sn, oldGenericsSpec);
List<MethodNode> classMethods = sn.getMethods();
// original class causing bridge methods for methods in super class
storeMissingCovariantMethods(declaredMethods, methodsToAdd, genericsSpec, classMethods);
// super class causing bridge methods for abstract methods in original class
if (!abstractMethods.isEmpty()) {
- for (Object classMethod : classMethods) {
- MethodNode method = (MethodNode) classMethod;
+ for (MethodNode method : classMethods) {
if (method.isStatic()) continue;
- storeMissingCovariantMethods(abstractMethods.values(), method, methodsToAdd, Collections.EMPTY_MAP, true);
+ storeMissingCovariantMethods(abstractMethods.values(), method, methodsToAdd, Collections.emptyMap(), true);
}
}
addCovariantMethods(sn.redirect(), declaredMethods, abstractMethods, methodsToAdd, genericsSpec);
}
- ClassNode[] interfaces = classNode.getInterfaces();
- for (ClassNode anInterface : interfaces) {
- List interfacesMethods = anInterface.getMethods();
- Map genericsSpec = createGenericsSpec(anInterface, oldGenericsSpec);
+ for (ClassNode anInterface : classNode.getInterfaces()) {
+ List<MethodNode> interfacesMethods = anInterface.getMethods();
+ Map<String, ClassNode> genericsSpec = createGenericsSpec(anInterface, oldGenericsSpec);
storeMissingCovariantMethods(declaredMethods, methodsToAdd, genericsSpec, interfacesMethods);
addCovariantMethods(anInterface, declaredMethods, abstractMethods, methodsToAdd, genericsSpec);
}
-
}
- private void storeMissingCovariantMethods(List declaredMethods, Map methodsToAdd, Map genericsSpec, List<MethodNode> methodNodeList) {
- for (Object declaredMethod : declaredMethods) {
- MethodNode method = (MethodNode) declaredMethod;
+ private void storeMissingCovariantMethods(final List<MethodNode> declaredMethods, final Map<String, MethodNode> methodsToAdd, final Map<String, ClassNode> genericsSpec, final List<MethodNode> methodNodeList) {
+ for (MethodNode method : declaredMethods) {
if (method.isStatic()) continue;
storeMissingCovariantMethods(methodNodeList, method, methodsToAdd, genericsSpec, false);
}
}
- private MethodNode getCovariantImplementation(final MethodNode oldMethod, final MethodNode overridingMethod, Map genericsSpec, boolean ignoreError) {
- // method name
+ private MethodNode getCovariantImplementation(final MethodNode oldMethod, final MethodNode overridingMethod, Map<String, ClassNode> genericsSpec, final boolean ignoreError) {
if (!oldMethod.getName().equals(overridingMethod.getName())) return null;
if ((overridingMethod.getModifiers() & ACC_BRIDGE) != 0) return null;
if ((oldMethod.getModifiers() & ACC_BRIDGE) != 0) return null;
@@ -1327,30 +1312,30 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
genericsSpec = addMethodGenerics(oldMethod, genericsSpec);
// parameters
- boolean normalEqualParameters = equalParametersNormal(overridingMethod, oldMethod);
- boolean genericEqualParameters = equalParametersWithGenerics(overridingMethod, oldMethod, genericsSpec);
- if (!normalEqualParameters && !genericEqualParameters) return null;
+ boolean equalParameters = equalParametersNormal(overridingMethod, oldMethod);
+ if (!equalParameters && !equalParametersWithGenerics(overridingMethod, oldMethod, genericsSpec)) return null;
// return type
- ClassNode mr = overridingMethod.getReturnType();
+ ClassNode nmr = overridingMethod.getReturnType();
ClassNode omr = oldMethod.getReturnType();
- boolean equalReturnType = mr.equals(omr);
+ boolean equalReturnType = nmr.equals(omr);
- ClassNode testmr = correctToGenericsSpec(genericsSpec, omr);
- if (!isAssignable(mr, testmr)) {
+ // TODO: ClassNode nmrCorrected = correctToGenericsSpec(..., nmr)?
+ ClassNode omrCorrected = correctToGenericsSpec(genericsSpec, omr);
+ if (!isAssignable(nmr, omrCorrected)) {
if (ignoreError) return null;
throw new RuntimeParserException(
"The return type of " +
overridingMethod.getTypeDescriptor() +
" in " + overridingMethod.getDeclaringClass().getName() +
- " is incompatible with " + testmr.getName() +
+ " is incompatible with " + omrCorrected.getName() +
" in " + oldMethod.getDeclaringClass().getName(),
sourceOf(overridingMethod));
}
- if (equalReturnType && normalEqualParameters) return null;
+ if (equalReturnType && equalParameters) return null;
- if ((oldMethod.getModifiers() & ACC_FINAL) != 0) {
+ if (oldMethod.isFinal()) {
throw new RuntimeParserException(
"Cannot override final method " +
oldMethod.getTypeDescriptor() +
@@ -1366,15 +1351,15 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
sourceOf(overridingMethod));
}
if (!equalReturnType) {
- boolean oldM = ClassHelper.isPrimitiveType(oldMethod.getReturnType());
- boolean newM = ClassHelper.isPrimitiveType(overridingMethod.getReturnType());
+ boolean oldM = ClassHelper.isPrimitiveType(omr);
+ boolean newM = ClassHelper.isPrimitiveType(nmr);
if (oldM || newM) {
String message;
if (oldM && newM) {
message = " with old and new method having different primitive return types";
} else if (newM) {
message = " with new method having a primitive return type and old method not";
- } else /* oldM */ {
+ } else /*oldM*/ {
message = " with old method having a primitive return type and new method not";
}
throw new RuntimeParserException(
@@ -1386,43 +1371,41 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- // if we reach this point we have at least one parameter or return type, that
- // is different in its specified form. That means we have to create a bridge method!
- MethodNode newMethod = new MethodNode(
+ // if we reach this point there is least one parameter or return type
+ // that is different in its specified form, so create a bridge method
+ return new MethodNode(
oldMethod.getName(),
overridingMethod.getModifiers() | ACC_SYNTHETIC | ACC_BRIDGE,
- cleanType(oldMethod.getReturnType()),
+ cleanType(omr),
cleanParameters(oldMethod.getParameters()),
oldMethod.getExceptions(),
- null
- );
- newMethod.setCode(new BytecodeSequence(new BytecodeInstruction() {
- @Override
- public void visit(MethodVisitor mv) {
- mv.visitVarInsn(ALOAD, 0);
- Parameter[] para = oldMethod.getParameters();
- Parameter[] goal = overridingMethod.getParameters();
- int doubleSlotOffset = 0;
- for (int i = 0; i < para.length; i++) {
- ClassNode type = para[i].getType();
- BytecodeHelper.load(mv, type, i + 1 + doubleSlotOffset);
- if (type.redirect() == ClassHelper.double_TYPE ||
- type.redirect() == ClassHelper.long_TYPE) {
- doubleSlotOffset++;
- }
- if (!type.equals(goal[i].getType())) {
- BytecodeHelper.doCast(mv, goal[i].getType());
- }
- }
- mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(classNode), overridingMethod.getName(), BytecodeHelper.getMethodDescriptor(overridingMethod.getReturnType(), overridingMethod.getParameters()), false);
+ new BytecodeSequence(new BytecodeInstruction() {
+ @Override
+ public void visit(final MethodVisitor mv) {
+ mv.visitVarInsn(ALOAD, 0);
+ Parameter[] para = oldMethod.getParameters();
+ Parameter[] goal = overridingMethod.getParameters();
+ int doubleSlotOffset = 0;
+ for (int i = 0, n = para.length; i < n; i += 1) {
+ ClassNode type = para[i].getType();
+ BytecodeHelper.load(mv, type, i + 1 + doubleSlotOffset);
+ if (type.redirect() == ClassHelper.double_TYPE
+ || type.redirect() == ClassHelper.long_TYPE) {
+ doubleSlotOffset += 1;
+ }
+ if (!type.equals(goal[i].getType())) {
+ BytecodeHelper.doCast(mv, goal[i].getType());
+ }
+ }
+ mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(classNode), overridingMethod.getName(), BytecodeHelper.getMethodDescriptor(nmr, overridingMethod.getParameters()), false);
- BytecodeHelper.doReturn(mv, oldMethod.getReturnType());
- }
- }));
- return newMethod;
+ BytecodeHelper.doReturn(mv, oldMethod.getReturnType());
+ }
+ })
+ );
}
- private boolean isAssignable(ClassNode node, ClassNode testNode) {
+ private static boolean isAssignable(final ClassNode node, final ClassNode testNode) {
if (node.isArray() && testNode.isArray()) {
return isArrayAssignable(node.getComponentType(), testNode.getComponentType());
}
@@ -1432,42 +1415,38 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return node.isDerivedFrom(testNode);
}
- private boolean isArrayAssignable(ClassNode node, ClassNode testNode) {
+ private static boolean isArrayAssignable(final ClassNode node, final ClassNode testNode) {
if (node.isArray() && testNode.isArray()) {
return isArrayAssignable(node.getComponentType(), testNode.getComponentType());
}
return isAssignable(node, testNode);
}
- private static Parameter[] cleanParameters(Parameter[] parameters) {
- Parameter[] params = new Parameter[parameters.length];
- for (int i = 0; i < params.length; i++) {
- params[i] = new Parameter(cleanType(parameters[i].getType()), parameters[i].getName());
- }
- return params;
+ private static Parameter[] cleanParameters(final Parameter[] parameters) {
+ return Arrays.stream(parameters).map(p -> param(cleanType(p.getType()), p.getName())).toArray(Parameter[]::new);
}
- private static ClassNode cleanType(ClassNode type) {
- // todo: should this be directly handled by getPlainNodeReference?
+ private static ClassNode cleanType(final ClassNode type) {
+ // TODO: Should this be directly handled by getPlainNodeReference?
if (type.isArray()) return cleanType(type.getComponentType()).makeArray();
return type.getPlainNodeReference();
}
- private void storeMissingCovariantMethods(Collection methods, MethodNode method, Map methodsToAdd, Map genericsSpec, boolean ignoreError) {
- for (Object next : methods) {
- MethodNode toOverride = (MethodNode) next;
+ private void storeMissingCovariantMethods(final Iterable<MethodNode> methods, final MethodNode method, final Map<String, MethodNode> methodsToAdd, final Map<String, ClassNode> genericsSpec, final boolean ignoreError) {
+ for (MethodNode toOverride : methods) {
MethodNode bridgeMethod = getCovariantImplementation(toOverride, method, genericsSpec, ignoreError);
- if (bridgeMethod == null) continue;
- methodsToAdd.put(bridgeMethod.getTypeDescriptor(), bridgeMethod);
- return;
+ if (bridgeMethod != null) {
+ methodsToAdd.put(bridgeMethod.getTypeDescriptor(), bridgeMethod);
+ return;
+ }
}
}
- private static boolean equalParametersNormal(MethodNode m1, MethodNode m2) {
+ private static boolean equalParametersNormal(final MethodNode m1, final MethodNode m2) {
Parameter[] p1 = m1.getParameters();
Parameter[] p2 = m2.getParameters();
if (p1.length != p2.length) return false;
- for (int i = 0; i < p2.length; i++) {
+ for (int i = 0, n = p2.length; i < n; i += 1) {
ClassNode type = p2[i].getType();
ClassNode parameterType = p1[i].getType();
if (!parameterType.equals(type)) return false;
@@ -1475,11 +1454,11 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return true;
}
- private static boolean equalParametersWithGenerics(MethodNode m1, MethodNode m2, Map genericsSpec) {
+ private static boolean equalParametersWithGenerics(final MethodNode m1, final MethodNode m2, final Map<String, ClassNode> genericsSpec) {
Parameter[] p1 = m1.getParameters();
Parameter[] p2 = m2.getParameters();
if (p1.length != p2.length) return false;
- for (int i = 0; i < p2.length; i++) {
+ for (int i = 0, n = p2.length; i < n; i += 1) {
ClassNode type = p2[i].getType();
ClassNode genericsType = correctToGenericsSpec(genericsSpec, type);
ClassNode parameterType = p1[i].getType();
@@ -1491,25 +1470,23 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
private static boolean moveOptimizedConstantsInitialization(final ClassNode node) {
if (node.isInterface() && !Traits.isTrait(node)) return false;
- final int mods = ACC_STATIC | ACC_SYNTHETIC | ACC_PUBLIC;
String name = SWAP_INIT;
- BlockStatement methodCode = new BlockStatement();
+ int mods = ACC_STATIC | ACC_SYNTHETIC | ACC_PUBLIC;
+ BlockStatement methodCode = block(new SwapInitStatement());
- methodCode.addStatement(new SwapInitStatement());
boolean swapInitRequired = false;
for (FieldNode fn : node.getFields()) {
if (!fn.isStatic() || !fn.isSynthetic() || !fn.getName().startsWith("$const$")) continue;
if (fn.getInitialExpression() == null) continue;
- final FieldExpression fe = new FieldExpression(fn);
+ final FieldExpression fe = fieldX(fn);
if (fn.getType().equals(ClassHelper.REFERENCE_TYPE)) fe.setUseReferenceDirectly(true);
ConstantExpression init = (ConstantExpression) fn.getInitialExpression();
- init = new ConstantExpression(init.getValue(), true);
- ExpressionStatement statement =
- new ExpressionStatement(
- new BinaryExpression(
- fe,
- Token.newSymbol(Types.EQUAL, fn.getLineNumber(), fn.getColumnNumber()),
- init));
+ init = constX(init.getValue(), true);
+ Statement statement = stmt(binX(
+ fe,
+ Token.newSymbol(Types.ASSIGN, fn.getLineNumber(), fn.getColumnNumber()),
+ init
+ ));
fn.setInitialValueExpression(null);
methodCode.addStatement(statement);
swapInitRequired = true;
@@ -1524,7 +1501,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return swapInitRequired;
}
- private static ASTNode sourceOf(MethodNode methodNode) {
+ private static ASTNode sourceOf(final MethodNode methodNode) {
if (methodNode.getLineNumber() < 1) {
ClassNode declaringClass = methodNode.getDeclaringClass();
if (methodNode.isSynthetic()) {
@@ -1553,28 +1530,29 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
* @return the same instance of constant expression if the type is already primitive, or a primitive
* constant if possible.
*/
- public static ConstantExpression transformToPrimitiveConstantIfPossible(ConstantExpression constantExpression) {
+ public static ConstantExpression transformToPrimitiveConstantIfPossible(final ConstantExpression constantExpression) {
Object value = constantExpression.getValue();
if (value == null) return constantExpression;
ConstantExpression result;
ClassNode type = constantExpression.getType();
if (ClassHelper.isPrimitiveType(type)) return constantExpression;
if (value instanceof String && ((String) value).length() == 1) {
- result = new ConstantExpression(((String) value).charAt(0));
+ result = constX(((String) value).charAt(0));
result.setType(ClassHelper.char_TYPE);
} else {
type = ClassHelper.getUnwrapper(type);
- result = new ConstantExpression(value, true);
+ result = constX(value, true);
result.setType(type);
}
return result;
}
- private static class SwapInitStatement extends BytecodeSequence {
+ //--------------------------------------------------------------------------
+ private static class SwapInitStatement extends BytecodeSequence {
private WriterController controller;
- public SwapInitStatement() {
+ SwapInitStatement() {
super(new SwapInitInstruction());
((SwapInitInstruction) getInstructions().get(0)).statement = this;
}
@@ -1582,14 +1560,13 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
@Override
public void visit(final GroovyCodeVisitor visitor) {
if (visitor instanceof AsmClassGenerator) {
- AsmClassGenerator generator = (AsmClassGenerator) visitor;
- controller = generator.getController();
+ controller = ((AsmClassGenerator) visitor).getController();
}
super.visit(visitor);
}
private static class SwapInitInstruction extends BytecodeInstruction {
- SwapInitStatement statement;
+ private SwapInitStatement statement;
@Override
public void visit(final MethodVisitor mv) {
[groovy] 06/19: minor refactor
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit c77a608050090addad7af91802937a6395a4b807
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 22 10:30:01 2020 +0800
minor refactor
(cherry picked from commit 6a02298d75f6597f9dc83ab5b4b4e79ce978b651)
---
.../asm/sc/StaticPropertyAccessHelper.java | 22 +-
.../transformers/BinaryExpressionTransformer.java | 2 +-
.../sc/FieldsAndPropertiesStaticCompileTest.groovy | 299 +++++++++++----------
3 files changed, 164 insertions(+), 159 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java
index 72499b5..ac30d6d 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java
@@ -39,29 +39,29 @@ public abstract class StaticPropertyAccessHelper {
public static Expression transformToSetterCall(
final Expression receiver,
final MethodNode setterMethod,
- final Expression argument,
+ final Expression valueExpression,
final boolean implicitThis,
final boolean safe,
final boolean spreadSafe,
- final boolean requiresReturnValue,
- final Expression propertyExpression) {
- if (requiresReturnValue) {
- TemporaryVariableExpression tmp = new TemporaryVariableExpression(argument);
+ final boolean returnValue,
+ final Expression sourceExpression) {
+ if (returnValue) {
+ TemporaryVariableExpression tmp = new TemporaryVariableExpression(valueExpression);
PoppingMethodCallExpression call = new PoppingMethodCallExpression(receiver, setterMethod, tmp);
call.setSafe(safe);
call.setSpreadSafe(spreadSafe);
call.setImplicitThis(implicitThis);
- call.setSourcePosition(propertyExpression);
+ call.setSourcePosition(sourceExpression);
PoppingListOfExpressionsExpression list = new PoppingListOfExpressionsExpression(tmp, call);
- list.setSourcePosition(propertyExpression);
+ list.setSourcePosition(sourceExpression);
return list;
} else {
- MethodCallExpression call = new MethodCallExpression(receiver, setterMethod.getName(), argument);
+ MethodCallExpression call = new MethodCallExpression(receiver, setterMethod.getName(), valueExpression);
call.setSafe(safe);
call.setSpreadSafe(spreadSafe);
call.setImplicitThis(implicitThis);
call.setMethodTarget(setterMethod);
- call.setSourcePosition(propertyExpression);
+ call.setSourcePosition(sourceExpression);
return call;
}
}
@@ -79,7 +79,7 @@ public abstract class StaticPropertyAccessHelper {
@Override
public Expression transformExpression(final ExpressionTransformer transformer) {
- PoppingMethodCallExpression call = (PoppingMethodCallExpression) this.call.transformExpression(transformer);
+ PoppingMethodCallExpression call = (PoppingMethodCallExpression) transformer.transform(this.call);
return new PoppingListOfExpressionsExpression(call.tmp, call);
}
@@ -104,7 +104,7 @@ public abstract class StaticPropertyAccessHelper {
@Override
public Expression transformExpression(final ExpressionTransformer transformer) {
- PoppingMethodCallExpression call = new PoppingMethodCallExpression(getObjectExpression().transformExpression(transformer), getMethodTarget(), (TemporaryVariableExpression) tmp.transformExpression(transformer));
+ PoppingMethodCallExpression call = new PoppingMethodCallExpression(transformer.transform(getObjectExpression()), getMethodTarget(), (TemporaryVariableExpression) transformer.transform(tmp));
call.copyNodeMetaData(this);
call.setSourcePosition(this);
call.setSafe(isSafe());
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
index 8941398..31df52a 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
@@ -194,7 +194,7 @@ public class BinaryExpressionTransformer {
expr.setSourcePosition(bin);
return expr;
}
- if (operationType == Types.EQUAL && leftExpression instanceof TupleExpression && rightExpression instanceof ListExpression) {
+ if (operationType == Types.ASSIGN && leftExpression instanceof TupleExpression && rightExpression instanceof ListExpression) {
// multiple assignment
ListOfExpressionsExpression cle = new ListOfExpressionsExpression();
boolean isDeclaration = (bin instanceof DeclarationExpression);
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
index a488532..8a0a33d 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
@@ -44,29 +44,29 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
// GROOVY-5561
void testShouldNotThrowAccessForbidden() {
assertScript '''
- class Test {
- def foo() {
- def bar = createBar()
- bar.foo
- }
+ class Test {
+ def foo() {
+ def bar = createBar()
+ bar.foo
+ }
- Bar createBar() { new Bar() }
- }
- class Bar {
- List<String> foo = ['1','2']
- }
- assert new Test().foo() == ['1','2']
+ Bar createBar() { new Bar() }
+ }
+ class Bar {
+ List<String> foo = ['1','2']
+ }
+ assert new Test().foo() == ['1','2']
'''
}
// GROOVY-5579
void testUseSetterAndNotSetProperty() {
assertScript '''
- Date d = new Date()
- d.time = 1
+ Date d = new Date()
+ d.time = 1
- assert d.time == 1
- '''
+ assert d.time == 1
+ '''
assert astTrees.values().any {
it.toString().contains 'INVOKEVIRTUAL java/util/Date.setTime (J)V'
}
@@ -116,38 +116,38 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testUseDirectWriteFieldAccess() {
assertScript '''
- class A {
- boolean setterCalled = false
+ class A {
+ boolean setterCalled
- protected int x
- public void setX(int a) {
- setterCalled = true
- x = a
- }
+ protected int x
+ public void setX(int a) {
+ setterCalled = true
+ x = a
}
- class B extends A {
- void directAccess() {
- this.@x = 2
- }
+ }
+ class B extends A {
+ void directAccess() {
+ this.@x = 2
}
- B b = new B()
- b.directAccess()
- assert b.isSetterCalled() == false
- assert b.x == 2
- '''
+ }
+ B b = new B()
+ b.directAccess()
+ assert b.isSetterCalled() == false
+ assert b.x == 2
+ '''
assert astTrees['B'][1].contains('PUTFIELD A.x')
}
void testUseDirectWriteStaticFieldAccess() {
assertScript '''
class A {
- static boolean setterCalled = false
+ static boolean setterCalled
- static protected int x
- public static void setX(int a) {
- setterCalled = true
- x = a
- }
+ static protected int x
+ public static void setX(int a) {
+ setterCalled = true
+ x = a
+ }
}
class B extends A {
static void directAccess() {
@@ -157,31 +157,31 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
B.directAccess()
assert B.isSetterCalled() == false
assert B.x == 2
- '''
+ '''
assert astTrees['B'][1].contains('PUTSTATIC A.x')
}
void testUseSetterFieldAccess() {
assertScript '''
- class A {
- boolean setterCalled = false
+ class A {
+ boolean setterCalled
- protected int x
- public void setX(int a) {
- setterCalled = true
- x = a
- }
+ protected int x
+ public void setX(int a) {
+ setterCalled = true
+ x = a
}
- class B extends A {
- void setterAccess() {
- this.x = 2
- }
+ }
+ class B extends A {
+ void setterAccess() {
+ this.x = 2
}
- B b = new B()
- b.setterAccess()
- assert b.isSetterCalled() == true
- assert b.x == 2
- '''
+ }
+ B b = new B()
+ b.setterAccess()
+ assert b.isSetterCalled() == true
+ assert b.x == 2
+ '''
assert astTrees['B'][1].contains('INVOKEVIRTUAL B.setX')
}
@@ -251,7 +251,6 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
A a = new A(1)
assert b.sameAs(a)
'''
-
}
void testDirectReadFieldFromSameClass() {
@@ -288,54 +287,55 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testUseDirectReadFieldAccess() {
assertScript '''
- class A {
- boolean getterCalled = false
+ class A {
+ boolean getterCalled
- protected int x
- public int getX() {
- getterCalled = true
- x
- }
+ protected int x
+ public int getX() {
+ getterCalled = true
+ x
}
- class B extends A {
- void m() {
- this.@x
- }
+ }
+ class B extends A {
+ void m() {
+ this.@x
}
- B b = new B()
- b.m()
- assert b.isGetterCalled() == false
- '''
+ }
+ B b = new B()
+ b.m()
+ assert b.isGetterCalled() == false
+ '''
assert astTrees['B'][1].contains('GETFIELD A.x')
}
void testUseGetterFieldAccess() {
assertScript '''
- class A {
- boolean getterCalled = false
-
- protected int x
- public int getX() {
- getterCalled = true
- x
- }
- }
- class B extends A {
- void usingGetter() {
- this.x
- }
- }
- B b = new B()
- b.usingGetter()
- assert b.isGetterCalled() == true
- '''
+ class A {
+ boolean getterCalled
+
+ protected int x
+ public int getX() {
+ getterCalled = true
+ x
+ }
+ }
+ class B extends A {
+ void usingGetter() {
+ this.x
+ }
+ }
+ B b = new B()
+ b.usingGetter()
+ assert b.isGetterCalled() == true
+ '''
assert astTrees['B'][1].contains('INVOKEVIRTUAL B.getX')
}
void testUseAttributeExternal() {
assertScript '''
class A {
- boolean setterCalled = false
+ boolean setterCalled
+
public int x
void setX(int a) {
setterCalled = true
@@ -352,7 +352,8 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testUseAttributeExternalSafe() {
assertScript '''
class A {
- boolean setterCalled = false
+ boolean setterCalled
+
public int x
void setX(int a) {
setterCalled = true
@@ -369,7 +370,8 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testUseAttributeExternalSafeWithNull() {
assertScript '''
class A {
- boolean setterCalled = false
+ boolean setterCalled
+
public int x
void setX(int a) {
setterCalled = true
@@ -384,7 +386,8 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testUseGetterExternal() {
assertScript '''
class A {
- boolean setterCalled = false
+ boolean setterCalled
+
public int x
void setX(int a) {
setterCalled = true
@@ -401,7 +404,8 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testUseAttributeExternalSpread() {
assertScript '''
class A {
- boolean setterCalled = false
+ boolean setterCalled
+
public int x
void setX(int a) {
setterCalled = true
@@ -418,7 +422,8 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testUseAttributeExternalSpreadSafeWithNull() {
assertScript '''
class A {
- boolean setterCalled = false
+ boolean setterCalled
+
public int x
void setX(int a) {
setterCalled = true
@@ -436,7 +441,8 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testUseAttributeExternalSpreadUsingSetter() {
assertScript '''
class A {
- boolean setterCalled = false
+ boolean setterCalled
+
public int x
void setX(int a) {
setterCalled = true
@@ -453,7 +459,8 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
void testUseAttributeExternalSpreadSafeWithNullUsingSetter() {
assertScript '''
class A {
- boolean setterCalled = false
+ boolean setterCalled
+
public int x
void setX(int a) {
setterCalled = true
@@ -471,45 +478,43 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
// GROOVY-5649
void testShouldNotThrowStackOverflowUsingThis() {
new GroovyShell().evaluate '''
- class HaveOption {
-
- private String helpOption;
+ class HaveOption {
+ private String helpOption
- public void setHelpOption(String helpOption) {
- this.helpOption = helpOption
- }
-
- }
- def o = new HaveOption()
- o.setHelpOption 'foo'
- assert o.helpOption
+ public void setHelpOption(String helpOption) {
+ this.helpOption = helpOption
+ }
+ }
+ def o = new HaveOption()
+ o.setHelpOption 'foo'
+ assert o.helpOption
'''
}
void testShouldNotThrowStackOverflow() {
new GroovyShell().evaluate '''
- class HaveOption {
-
- private String helpOption;
-
- public void setHelpOption(String ho) {
- helpOption = ho
- }
+ class HaveOption {
+ private String helpOption
- }
- def o = new HaveOption()
- o.setHelpOption 'foo'
- assert o.helpOption
+ public void setHelpOption(String ho) {
+ helpOption = ho
+ }
+ }
+ def o = new HaveOption()
+ o.setHelpOption 'foo'
+ assert o.helpOption
'''
}
@Override
void testPropertyWithMultipleSetters() {
// we need to override the test because the AST is going to be changed
- assertScript '''import org.codehaus.groovy.ast.expr.BinaryExpression
-import org.codehaus.groovy.ast.expr.BooleanExpression
-import org.codehaus.groovy.ast.stmt.AssertStatement
-import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
+ assertScript '''
+ import org.codehaus.groovy.ast.expr.BinaryExpression
+ import org.codehaus.groovy.ast.expr.BooleanExpression
+ import org.codehaus.groovy.ast.stmt.AssertStatement
+ import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
+
class A {
private field
void setX(Integer a) {field=a}
@@ -537,24 +542,24 @@ import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
assert a.x == "3"
}
testBody()
- '''
+ '''
}
void testCallSetterAsPropertyWithinFinallyBlockShouldNotThrowVerifyError() {
try {
assertScript '''
- class Multi {
- void setOut(int a) {}
- }
+ class Multi {
+ void setOut(int a) {}
+ }
- void foo() {
- def m = new Multi()
- try {
- } finally {
- m.out = 1
- }
- }
- foo()
+ void foo() {
+ def m = new Multi()
+ try {
+ } finally {
+ m.out = 1
+ }
+ }
+ foo()
'''
} finally {
assert astTrees.values().any {
@@ -566,20 +571,20 @@ import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
void testCallMultiSetterAsPropertyWithinFinallyBlockShouldNotThrowVerifyError() {
try {
assertScript '''
- class Multi {
- void setOut(int a) {}
- void setOut(String a) {}
- }
+ class Multi {
+ void setOut(int a) {}
+ void setOut(String a) {}
+ }
- void foo() {
- def m = new Multi()
- try {
- } finally {
- m.out = 1
- m.out = 'foo'
- }
- }
- foo()
+ void foo() {
+ def m = new Multi()
+ try {
+ } finally {
+ m.out = 1
+ m.out = 'foo'
+ }
+ }
+ foo()
'''
} finally {
assert astTrees.values().any {
[groovy] 18/19: GROOVY-9704: load minus one as long integer (closes
#1358)
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 3184da923cb6557759cfe35ba26e55db62adc060
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Aug 31 12:01:43 2020 -0500
GROOVY-9704: load minus one as long integer (closes #1358)
(cherry picked from commit cdee610a78f03eb3acb70664b98f49eba22b6bc9)
---
.../groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java | 2 +-
src/test/groovy/transform/stc/UnaryOperatorSTCTest.groovy | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java
index a46bf94..54d75fe 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java
@@ -62,7 +62,7 @@ public class StaticTypesUnaryExpressionHelper extends UnaryExpressionHelper impl
if (top == int_TYPE || top == long_TYPE || top == short_TYPE || top == byte_TYPE || top == char_TYPE) {
bytecodeX(mv -> {
if (top == long_TYPE) {
- mv.visitLdcInsn(-1);
+ mv.visitLdcInsn(-1L);
mv.visitInsn(LXOR);
} else {
mv.visitInsn(ICONST_M1);
diff --git a/src/test/groovy/transform/stc/UnaryOperatorSTCTest.groovy b/src/test/groovy/transform/stc/UnaryOperatorSTCTest.groovy
index b4854c6..6768f5e 100644
--- a/src/test/groovy/transform/stc/UnaryOperatorSTCTest.groovy
+++ b/src/test/groovy/transform/stc/UnaryOperatorSTCTest.groovy
@@ -61,7 +61,7 @@ class UnaryOperatorSTCTest extends StaticTypeCheckingTestCase {
}
// GROOVY-9704
- void _FIXME_testBitwiseNegate_long() {
+ void testBitwiseNegate_long() {
assertScript '''
long x = 1L
assert ~x == -2L
[groovy] 09/19: minor refactor
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 0d7f98f272c3293e1d1d76975c6a39cb928a5eab
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Aug 25 11:26:04 2020 -0500
minor refactor
(cherry picked from commit e4b4a54470857fa1d1c57b4d0427cce57b2e06b2)
---
.../groovy/transform/ASTTestTransformation.groovy | 66 ++++++++++------------
src/main/java/groovy/transform/ASTTest.java | 8 +--
.../codehaus/groovy/ast/expr/FieldExpression.java | 10 ++--
src/spec/test/DifferencesFromJavaTest.groovy | 63 ++++++++++-----------
src/spec/test/TestingASTTransformsTest.groovy | 5 --
src/test/gls/innerClass/InnerClassTest.groovy | 6 --
src/test/groovy/bugs/Groovy8002.groovy | 1 -
src/test/groovy/bugs/Groovy8169.groovy | 1 -
.../groovy/bugs/ImportNodeLineNumberTest.groovy | 48 +++++++++-------
.../transform/AnnotationCollectorLegacyTest.groovy | 6 +-
.../transform/AnnotationCollectorTest.groovy | 6 +-
.../groovy/transform/AutoFinalTransformTest.groovy | 8 +--
.../groovy/transform/DelegateTransformTest.groovy | 17 +++---
.../transform/TupleConstructorTransformTest.groovy | 2 -
.../traitx/TraitASTTransformationTest.groovy | 6 +-
15 files changed, 114 insertions(+), 139 deletions(-)
diff --git a/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy b/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
index ca675fb..15ca578 100644
--- a/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
+++ b/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
@@ -46,14 +46,15 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
-class ASTTestTransformation extends AbstractASTTransformation implements CompilationUnitAware {
- private CompilationUnit compilationUnit
+class ASTTestTransformation implements ASTTransformation, CompilationUnitAware {
- @SuppressWarnings('Instanceof')
+ CompilationUnit compilationUnit
+
+ @Override
void visit(final ASTNode[] nodes, final SourceUnit source) {
AnnotationNode annotationNode = nodes[0]
def member = annotationNode.getMember('phase')
- def phase = null
+ CompilePhase phase = null
if (member) {
if (member instanceof VariableExpression) {
phase = CompilePhase.valueOf(member.text)
@@ -69,35 +70,32 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
if (!member && !annotationNode.getNodeMetaData(ASTTestTransformation)) {
throw new SyntaxException('Missing test expression', annotationNode.lineNumber, annotationNode.columnNumber)
}
- // convert value into node metadata so that the expression doesn't mix up with other AST xforms like type checking
- annotationNode.putNodeMetaData(ASTTestTransformation, member)
+ // convert value into node metadata so that the expression doesn't mix up with other AST xforms like STC
+ annotationNode.setNodeMetaData(ASTTestTransformation, member)
annotationNode.members.remove('value')
def pcallback = compilationUnit.progressCallback
def callback = new CompilationUnit.ProgressCallback() {
- Binding binding = new Binding([:].withDefault { null })
+ private final Binding binding = new Binding([:].withDefault { null })
@Override
- void call(final ProcessingUnit context, final int phaseRef) {
- if (phase == null || phaseRef == phase.phaseNumber) {
+ void call(final ProcessingUnit context, final int phaseNumber) {
+ if (phase == null || phaseNumber == phase.phaseNumber) {
ClosureExpression testClosure = nodes[0].getNodeMetaData(ASTTestTransformation)
StringBuilder sb = new StringBuilder()
- for (int i = testClosure.lineNumber; i <= testClosure.lastLineNumber; i++) {
+ for (int i = testClosure.lineNumber; i <= testClosure.lastLineNumber; i += 1) {
sb.append(source.source.getLine(i, new Janitor())).append('\n')
}
def testSource = sb[testClosure.columnNumber..<sb.length()]
testSource = testSource[0..<testSource.lastIndexOf('}')]
- CompilerConfiguration config = new CompilerConfiguration()
- def customizer = new ImportCustomizer()
- config.addCompilationCustomizers(customizer)
- binding['sourceUnit'] = source
+
binding['node'] = nodes[1]
- binding['lookup'] = new MethodClosure(LabelFinder, 'lookup').curry(nodes[1])
+ binding['sourceUnit'] = source
binding['compilationUnit'] = compilationUnit
- binding['compilePhase'] = CompilePhase.fromPhaseNumber(phaseRef)
-
- GroovyShell shell = new GroovyShell(binding, config)
+ binding['compilePhase'] = CompilePhase.fromPhaseNumber(phaseNumber)
+ binding['lookup'] = new MethodClosure(LabelFinder, 'lookup').curry(nodes[1])
+ def customizer = new ImportCustomizer()
source.AST.imports.each {
customizer.addImport(it.alias, it.type.name)
}
@@ -110,7 +108,10 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
source.AST.staticStarImports.each {
customizer.addStaticStars(it.value.className)
}
- shell.evaluate(testSource)
+
+ def config = new CompilerConfiguration()
+ config.addCompilationCustomizers(customizer)
+ new GroovyShell(binding, config).evaluate(testSource)
}
}
}
@@ -127,15 +128,11 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
compilationUnit.progressCallback = callback
}
- void setCompilationUnit(final CompilationUnit unit) {
- this.compilationUnit = unit
- }
-
private static class AssertionSourceDelegatingSourceUnit extends SourceUnit {
private final ReaderSource delegate
- AssertionSourceDelegatingSourceUnit(final String name, final ReaderSource source, final CompilerConfiguration flags, final GroovyClassLoader loader, final ErrorCollector er) {
- super(name, '', flags, loader, er)
+ AssertionSourceDelegatingSourceUnit(final String name, final ReaderSource source, final CompilerConfiguration config, final GroovyClassLoader loader, final ErrorCollector er) {
+ super(name, '', config, loader, er)
delegate = source
}
@@ -151,8 +148,7 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
if (column > 40) {
int start = column - 30 - 1
int end = (column + 10 > text.length() ? text.length() : column + 10 - 1)
- sample = ' ' + text[start..<end] + Utilities.eol() + ' ' +
- marker[start..<marker.length()]
+ sample = ' ' + text[start..<end] + Utilities.eol() + ' ' + marker[start..<marker.length()]
} else {
sample = ' ' + text + Utilities.eol() + ' ' + marker
}
@@ -165,16 +161,15 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
}
private static class ProgressCallbackChain implements CompilationUnit.ProgressCallback {
+ private final List<CompilationUnit.ProgressCallback> chain = [] as LinkedList
- private final List<CompilationUnit.ProgressCallback> chain = new LinkedList<CompilationUnit.ProgressCallback>()
-
- ProgressCallbackChain(CompilationUnit.ProgressCallback... callbacks) {
- if (callbacks!=null) {
+ ProgressCallbackChain(final CompilationUnit.ProgressCallback... callbacks) {
+ if (callbacks) {
callbacks.each { addCallback(it) }
}
}
- void addCallback(CompilationUnit.ProgressCallback callback) {
+ void addCallback(final CompilationUnit.ProgressCallback callback) {
chain << callback
}
@@ -186,14 +181,14 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
static class LabelFinder extends ClassCodeVisitorSupport {
- static List<Statement> lookup(MethodNode node, String label) {
+ static List<Statement> lookup(final MethodNode node, final String label) {
LabelFinder finder = new LabelFinder(label, null)
node.code.visit(finder)
finder.targets
}
- static List<Statement> lookup(ClassNode node, String label) {
+ static List<Statement> lookup(final ClassNode node, final String label) {
LabelFinder finder = new LabelFinder(label, null)
node.methods*.code*.visit(finder)
node.declaredConstructors*.code*.visit(finder)
@@ -203,8 +198,7 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
private final String label
private final SourceUnit unit
-
- private final List<Statement> targets = new LinkedList<Statement>()
+ private final List<Statement> targets = [] as LinkedList
LabelFinder(final String label, final SourceUnit unit) {
this.label = label
diff --git a/src/main/java/groovy/transform/ASTTest.java b/src/main/java/groovy/transform/ASTTest.java
index f72759f..1779161 100644
--- a/src/main/java/groovy/transform/ASTTest.java
+++ b/src/main/java/groovy/transform/ASTTest.java
@@ -21,6 +21,7 @@ package groovy.transform;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -41,7 +42,6 @@ import java.lang.annotation.Target;
* assert owner.fields.any { it.name == 'x' }
* })
* {@code @Field int x}
- *
* </pre>
*
* The closure code is executed after the specified phase has completed. If no phase is selected, then the
@@ -50,12 +50,10 @@ import java.lang.annotation.Target;
* it means that <i>node</i> refers to the declaration node (int x).
*
* @since 2.0.0
- *
*/
-@java.lang.annotation.Documented
+@Documented
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD,
-ElementType.LOCAL_VARIABLE, ElementType.PACKAGE, ElementType.PARAMETER})
+@Target({ElementType.PACKAGE, ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@GroovyASTTransformationClass("org.codehaus.groovy.transform.ASTTestTransformation")
public @interface ASTTest {
/**
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java
index 3361715..c221dfc 100644
--- a/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java
+++ b/src/main/java/org/codehaus/groovy/ast/expr/FieldExpression.java
@@ -46,17 +46,17 @@ public class FieldExpression extends Expression {
return this;
}
- public String getFieldName() {
- return field.getName();
- }
-
public FieldNode getField() {
return field;
}
+ public String getFieldName() {
+ return field.getName();
+ }
+
@Override
public String getText() {
- return "this." + field.getName();
+ return "this." + getFieldName();
}
@Override
diff --git a/src/spec/test/DifferencesFromJavaTest.groovy b/src/spec/test/DifferencesFromJavaTest.groovy
index 59f3acc..0b9d83f 100644
--- a/src/spec/test/DifferencesFromJavaTest.groovy
+++ b/src/spec/test/DifferencesFromJavaTest.groovy
@@ -66,38 +66,37 @@ assertEquals(1, result);
}
void testPackagePrivate() {
- assertScript '''import groovy.transform.ASTTest
-import org.codehaus.groovy.control.CompilePhase
-
-import java.lang.reflect.Modifier
-
-@ASTTest(phase = CompilePhase.CLASS_GENERATION, value = {
- def field = node.getField('name')
- assert field.modifiers == Modifier.PRIVATE
-})
-// tag::packageprivate_property[]
-class Person {
- String name
-}
-// end::packageprivate_property[]
-new Person() '''
-
- assertScript '''import groovy.transform.ASTTest
-import groovy.transform.PackageScope
-import org.codehaus.groovy.control.CompilePhase
-
-import java.lang.reflect.Modifier
-
-@ASTTest(phase = CompilePhase.CLASS_GENERATION, value = {
- def field = node.getField('name')
- assert field.modifiers == 0
-})
-// tag::packageprivate_field[]
-class Person {
- @PackageScope String name
-}
-// end::packageprivate_field[]
-new Person() '''
+ assertScript '''
+ import groovy.transform.ASTTest
+ import java.lang.reflect.Modifier
+
+ @ASTTest(phase = CLASS_GENERATION, value = {
+ def field = node.getField('name')
+ assert field.modifiers == Modifier.PRIVATE
+ })
+ // tag::packageprivate_property[]
+ class Person {
+ String name
+ }
+ // end::packageprivate_property[]
+ new Person()
+ '''
+
+ assertScript '''
+ import groovy.transform.ASTTest
+ import groovy.transform.PackageScope
+
+ @ASTTest(phase = CLASS_GENERATION, value = {
+ def field = node.getField('name')
+ assert field.modifiers == 0
+ })
+ // tag::packageprivate_field[]
+ class Person {
+ @PackageScope String name
+ }
+ // end::packageprivate_field[]
+ new Person()
+ '''
}
void testAnonymousAndNestedClasses() {
diff --git a/src/spec/test/TestingASTTransformsTest.groovy b/src/spec/test/TestingASTTransformsTest.groovy
index 7ee4155..5242ce3 100644
--- a/src/spec/test/TestingASTTransformsTest.groovy
+++ b/src/spec/test/TestingASTTransformsTest.groovy
@@ -56,7 +56,6 @@ new MathsTest().testFib()'''
assertScript '''// tag::asttest_basic[]
import groovy.transform.ASTTest
import org.codehaus.groovy.ast.ClassNode
-import static org.codehaus.groovy.control.CompilePhase.*
@ASTTest(phase=CONVERSION, value={ // <1>
assert node instanceof ClassNode // <2>
@@ -76,8 +75,6 @@ def p = new Person()
import groovy.transform.ASTTest
import groovy.transform.PackageScope
-import static org.codehaus.groovy.control.CompilePhase.*
-
@ASTTest(phase=SEMANTIC_ANALYSIS, value= {
def nameNode = node.properties.find { it.name == 'name' }
def ageNode = node.properties.find { it.name == 'age' }
@@ -103,8 +100,6 @@ import org.codehaus.groovy.ast.ClassHelper
import org.codehaus.groovy.ast.expr.DeclarationExpression
import org.codehaus.groovy.ast.stmt.ForStatement
-import static org.codehaus.groovy.control.CompilePhase.*
-
class Something {
@ASTTest(phase=SEMANTIC_ANALYSIS, value= {
def forLoop = lookup('anchor')[0]
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 6f401fe..ebb0b5a 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -1310,7 +1310,6 @@ final class InnerClassTest {
import groovy.transform.ASTTest
import org.codehaus.groovy.ast.expr.*
import static org.codehaus.groovy.classgen.Verifier.*
- import static org.codehaus.groovy.control.CompilePhase.*
class A {
@ASTTest(phase=CLASS_GENERATION, value={
@@ -1339,7 +1338,6 @@ final class InnerClassTest {
import groovy.transform.ASTTest
import org.codehaus.groovy.ast.expr.*
import static org.codehaus.groovy.classgen.Verifier.*
- import static org.codehaus.groovy.control.CompilePhase.*
@ASTTest(phase=CLASS_GENERATION, value={
def init = node.parameters[0].getNodeMetaData(INITIAL_EXPRESSION)
@@ -1366,7 +1364,6 @@ final class InnerClassTest {
import org.codehaus.groovy.ast.expr.*
import org.codehaus.groovy.ast.stmt.*
import static org.codehaus.groovy.classgen.Verifier.*
- import static org.codehaus.groovy.control.CompilePhase.*
@ASTTest(phase=CLASS_GENERATION, value={
def init = node.parameters[0].getNodeMetaData(INITIAL_EXPRESSION)
@@ -1579,9 +1576,7 @@ final class InnerClassTest {
@Test // GROOVY-7312
void testInnerClassOfInterfaceIsStatic2() {
assertScript '''
- import java.lang.reflect.Modifier
import groovy.transform.ASTTest
- import org.codehaus.groovy.control.CompilePhase
import org.objectweb.asm.Opcodes
@ASTTest(phase = CLASS_GENERATION, value = {
@@ -1709,7 +1704,6 @@ final class InnerClassTest {
import java.util.concurrent.Callable
import org.codehaus.groovy.ast.expr.*
import static org.codehaus.groovy.classgen.Verifier.*
- import static org.codehaus.groovy.control.CompilePhase.*
class A {
@ASTTest(phase=CLASS_GENERATION, value={
diff --git a/src/test/groovy/bugs/Groovy8002.groovy b/src/test/groovy/bugs/Groovy8002.groovy
index d2a5ee5..d3093cd 100644
--- a/src/test/groovy/bugs/Groovy8002.groovy
+++ b/src/test/groovy/bugs/Groovy8002.groovy
@@ -30,7 +30,6 @@ final class Groovy8002 {
void testSourcePositionOfMethodInChainAssignmentCS() {
assertScript '''
import groovy.transform.*
- import static org.codehaus.groovy.control.CompilePhase.*
class B {
private String z
diff --git a/src/test/groovy/bugs/Groovy8169.groovy b/src/test/groovy/bugs/Groovy8169.groovy
index dd3d9d1..6b82899 100644
--- a/src/test/groovy/bugs/Groovy8169.groovy
+++ b/src/test/groovy/bugs/Groovy8169.groovy
@@ -32,7 +32,6 @@ final class Groovy8169 {
import groovy.transform.*
import org.codehaus.groovy.ast.stmt.*
import static org.codehaus.groovy.ast.ClassHelper.*
- import static org.codehaus.groovy.control.CompilePhase.*
@ASTTest(phase=CLASS_GENERATION, value={
def loop = node.code.statements.find { it instanceof ForStatement }
diff --git a/src/test/groovy/bugs/ImportNodeLineNumberTest.groovy b/src/test/groovy/bugs/ImportNodeLineNumberTest.groovy
index f4d967a..bca576d 100644
--- a/src/test/groovy/bugs/ImportNodeLineNumberTest.groovy
+++ b/src/test/groovy/bugs/ImportNodeLineNumberTest.groovy
@@ -18,29 +18,35 @@
*/
package groovy.bugs
-import groovy.test.GroovyTestCase
+import org.junit.Test
-class ImportNodeLineNumberTest extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
+
+final class ImportNodeLineNumberTest {
+ @Test
void testLineNumberOfImports() {
- assertScript '''import groovy.transform.ASTTest
- import static org.codehaus.groovy.control.CompilePhase.SEMANTIC_ANALYSIS
- import groovy.transform.*
- import static java.lang.Math.*
-
- @ASTTest(phase=SEMANTIC_ANALYSIS, value={
- def module = node.declaringClass.module
- def astTestImport = module.getImport('ASTTest')
- assert astTestImport.lineNumber == 1
- def staticImport = module.staticImports['SEMANTIC_ANALYSIS']
- assert staticImport.lineNumber == 2
- def starImport = module.starImports[0]
- assert starImport.lineNumber == 3
- def staticStar = module.staticStarImports['java.lang.Math']
- assert staticStar.lineNumber == 4
- })
- void foo() {}
-
- foo()
+ assertScript '''\
+ import groovy.lang.Grab
+ import groovy.transform.*
+ import static java.lang.Math.*
+ import static java.lang.Math.PI as pi
+
+ @ASTTest({
+ def moduleNode = sourceUnit.AST
+
+ def importNode = moduleNode.getImport('Grab')
+ assert importNode.lineNumber == 1
+
+ importNode = moduleNode.starImports[0]
+ assert importNode.lineNumber == 2
+
+ importNode = moduleNode.staticStarImports['java.lang.Math']
+ assert importNode.lineNumber == 3
+
+ importNode = moduleNode.staticImports['pi']
+ assert importNode.lineNumber == 4
+ })
+ def var
'''
}
}
diff --git a/src/test/groovy/transform/AnnotationCollectorLegacyTest.groovy b/src/test/groovy/transform/AnnotationCollectorLegacyTest.groovy
index b57f73d..0268602 100644
--- a/src/test/groovy/transform/AnnotationCollectorLegacyTest.groovy
+++ b/src/test/groovy/transform/AnnotationCollectorLegacyTest.groovy
@@ -109,7 +109,7 @@ class AnnotationCollectorLegacyTest extends GroovyTestCase {
class Foo {
Integer a, b
}
- assert Foo.class.annotations.size() == 3
+ assert Foo.class.annotations.size() == 3
assert new Foo(a: 1, b: 2).toString() == "Foo(2)"
assert NotPreCompiledAlias.value().length == 0
assert NotPreCompiledAlias.value() instanceof Object[][]
@@ -141,7 +141,7 @@ class AnnotationCollectorLegacyTest extends GroovyTestCase {
'''
assertScript '''
import groovy.transform.*
-
+
@OtherPreCompiledAliasL(applyToAllClasses=false, value={ counter++> 10})
class X {
def counter = 0
@@ -168,7 +168,7 @@ class AnnotationCollectorLegacyTest extends GroovyTestCase {
@interface Alias {}
@Alias(excludes=["a"])
- @ASTTest(phase=org.codehaus.groovy.control.CompilePhase.INSTRUCTION_SELECTION, value={
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
def annotations = node.annotations
assert annotations.size() == 4 //ASTTest + 3
annotations.each {
diff --git a/src/test/groovy/transform/AnnotationCollectorTest.groovy b/src/test/groovy/transform/AnnotationCollectorTest.groovy
index b8825dd..6f519a5 100644
--- a/src/test/groovy/transform/AnnotationCollectorTest.groovy
+++ b/src/test/groovy/transform/AnnotationCollectorTest.groovy
@@ -114,7 +114,7 @@ class AnnotationCollectorTest extends GroovyTestCase {
class Foo {
Integer a, b
}
- assert Foo.class.annotations.size() == 3
+ assert Foo.class.annotations.size() == 3
assert new Foo(a: 1, b: 2).toString() == "Foo(2)"
def data = NotPreCompiledAlias.getAnnotation(AnnotationCollector).serializeClass().value()
assert data.length == 0
@@ -148,7 +148,7 @@ class AnnotationCollectorTest extends GroovyTestCase {
'''
assertScript '''
import groovy.transform.*
-
+
@OtherPreCompiledAlias(applyToAllClasses=false, value={ counter++> 10})
class X {
def counter = 0
@@ -175,7 +175,7 @@ class AnnotationCollectorTest extends GroovyTestCase {
@interface Alias {}
@Alias(excludes=["a"])
- @ASTTest(phase=org.codehaus.groovy.control.CompilePhase.INSTRUCTION_SELECTION, value={
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
def annotations = node.annotations
assert annotations.size() == 4 //ASTTest + 3
annotations.each {
diff --git a/src/test/org/codehaus/groovy/transform/AutoFinalTransformTest.groovy b/src/test/org/codehaus/groovy/transform/AutoFinalTransformTest.groovy
index 329af82..496ea85 100644
--- a/src/test/org/codehaus/groovy/transform/AutoFinalTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/AutoFinalTransformTest.groovy
@@ -28,9 +28,7 @@ class AutoFinalTransformTest extends CompilableTestSupport {
void testAutoFinalOnClass() {
// use ASTTest here since final modifier isn't put into bytecode so not available via reflection
assertScript '''
- import groovy.transform.AutoFinal
- import groovy.transform.ASTTest
- import static org.codehaus.groovy.control.CompilePhase.SEMANTIC_ANALYSIS
+ import groovy.transform.*
import static java.lang.reflect.Modifier.isFinal
@ASTTest(phase=SEMANTIC_ANALYSIS, value = {
@@ -65,9 +63,7 @@ class AutoFinalTransformTest extends CompilableTestSupport {
void testAutoFinalOnClassButDisabledOnMethod() {
// use ASTTest here since final modifier isn't put into bytecode so not available via reflection
assertScript '''
- import groovy.transform.AutoFinal
- import groovy.transform.ASTTest
- import static org.codehaus.groovy.control.CompilePhase.SEMANTIC_ANALYSIS
+ import groovy.transform.*
import static java.lang.reflect.Modifier.isFinal
@ASTTest(phase=SEMANTIC_ANALYSIS, value = {
diff --git a/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy b/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy
index 903ff4b..1f3e8ab 100644
--- a/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy
@@ -157,9 +157,9 @@ class DelegateTransformTest extends CompilableTestSupport {
void testUsingDateCompiles() {
assertScript """
- class Foo {
- @Delegate Date d = new Date();
- }
+ class Foo {
+ @Delegate Date d = new Date();
+ }
Foo
"""
}
@@ -510,7 +510,7 @@ class DelegateTransformTest extends CompilableTestSupport {
@Delegate(includes=['author', 'getTitleAndAuthor'])
Book book
}
-
+
Book book = new Book(title: 'Ulysses', author: 'James Joyce')
OwnedBook ownedBook = new OwnedBook(owner: 'John Smith', book: book)
@@ -532,7 +532,7 @@ class DelegateTransformTest extends CompilableTestSupport {
}
'''
}
-
+
// GROOVY-6329
void testIncludeAndExcludeByType() {
assertScript """
@@ -593,7 +593,6 @@ class DelegateTransformTest extends CompilableTestSupport {
void testLineNumberInStackTrace() {
try {
assertScript '''import groovy.transform.ASTTest
- import org.codehaus.groovy.control.CompilePhase
@ASTTest(phase=CompilePhase.CANONICALIZATION, value={
def fieldNode = node.getDeclaredField('thingie')
@@ -791,8 +790,8 @@ assert foo.dm.x == '123'
Bar bar
}
- class Bar {
- String pls
+ class Bar {
+ String pls
}
assert new Foo(pls: 'ok').pls == 'ok'
'''
@@ -836,7 +835,7 @@ assert foo.dm.x == '123'
String name
@Delegate(excludes = "name")
Map<String, String> data
-
+
WMap(String name, Map<String, String> data) {
this.name = name
this.data = data
diff --git a/src/test/org/codehaus/groovy/transform/TupleConstructorTransformTest.groovy b/src/test/org/codehaus/groovy/transform/TupleConstructorTransformTest.groovy
index addab14..671bbcd 100644
--- a/src/test/org/codehaus/groovy/transform/TupleConstructorTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/TupleConstructorTransformTest.groovy
@@ -222,7 +222,6 @@ class TupleConstructorTransformTest extends GroovyShellTestCase {
import groovy.transform.*
import static groovy.transform.options.Visibility.*
import static java.lang.reflect.Modifier.isPrivate
- import static org.codehaus.groovy.control.CompilePhase.*
@VisibilityOptions(PRIVATE)
@Immutable
@@ -253,7 +252,6 @@ class TupleConstructorTransformTest extends GroovyShellTestCase {
import groovy.transform.*
import java.lang.reflect.Modifier
import static groovy.transform.options.Visibility.*
- import static org.codehaus.groovy.control.CompilePhase.*
@VisibilityOptions(value = PROTECTED, id = 'first_only')
@VisibilityOptions(constructor = PRIVATE, id = 'age_only')
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index 9c1c7c9..934eaf4 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -284,14 +284,13 @@ final class TraitASTTransformationTest {
void testPrivateFieldInTraitShouldBeRemapped() {
assertScript '''
import groovy.transform.ASTTest
- import org.codehaus.groovy.control.CompilePhase
trait Foo {
private int i = 0
int sum(int x) { x+i }
void setIndex(int index) { this.i = index }
}
- @ASTTest(phase=CompilePhase.INSTRUCTION_SELECTION, value={
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
assert node.fields.any { it.name == 'Foo__i' }
})
class Bob implements Foo {
@@ -2444,7 +2443,7 @@ final class TraitASTTransformationTest {
void testFieldInTraitModifiers() {
assertScript '''
import groovy.transform.ASTTest
- import static org.codehaus.groovy.control.CompilePhase.INSTRUCTION_SELECTION
+
trait A {
public int foo
}
@@ -2460,7 +2459,6 @@ final class TraitASTTransformationTest {
import groovy.transform.ASTTest
import java.lang.reflect.Modifier
- import static org.codehaus.groovy.control.CompilePhase.INSTRUCTION_SELECTION
trait A {
private int foo
}
[groovy] 04/19: minor refactor
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 6a4f4c416ea1be7c058f08d29c8f2c891b4a1db6
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Aug 20 15:05:35 2020 -0500
minor refactor
(cherry picked from commit 092c7f78f8fd644136b6f1e35819639b3ecc5f73)
---
...icTypesBinaryExpressionMultiTypeDispatcher.java | 43 ++++++++++------------
.../classgen/asm/sc/bugs/Groovy7361Bug.groovy | 35 +++++++++---------
2 files changed, 36 insertions(+), 42 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
index b2a6b3c..26685e5 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
@@ -37,7 +37,6 @@ import org.codehaus.groovy.ast.stmt.EmptyStatement;
import org.codehaus.groovy.ast.stmt.ForStatement;
import org.codehaus.groovy.ast.tools.WideningCategories;
import org.codehaus.groovy.classgen.asm.BinaryExpressionMultiTypeDispatcher;
-import org.codehaus.groovy.classgen.asm.BinaryExpressionWriter;
import org.codehaus.groovy.classgen.asm.BytecodeHelper;
import org.codehaus.groovy.classgen.asm.CompileStack;
import org.codehaus.groovy.classgen.asm.OperandStack;
@@ -45,10 +44,7 @@ import org.codehaus.groovy.classgen.asm.VariableSlotLoader;
import org.codehaus.groovy.classgen.asm.WriterController;
import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.TokenUtil;
-import org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys;
import org.codehaus.groovy.transform.sc.StaticCompilationVisitor;
-import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
-import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -77,9 +73,12 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.PRIVATE_FIELDS_MUTATORS;
import static org.codehaus.groovy.transform.sc.StaticCompilationVisitor.ARRAYLIST_ADD_METHOD;
import static org.codehaus.groovy.transform.sc.StaticCompilationVisitor.ARRAYLIST_CLASSNODE;
import static org.codehaus.groovy.transform.sc.StaticCompilationVisitor.ARRAYLIST_CONSTRUCTOR;
+import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isAssignment;
+import static org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.inferLoopElementType;
import static org.codehaus.groovy.transform.stc.StaticTypesMarker.DIRECT_METHOD_CALL_TARGET;
import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_FUNCTIONAL_INTERFACE_TYPE;
import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE;
@@ -195,7 +194,7 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
// GROOVY-5620: spread-safe operator on LHS is not supported
if (leftExpression instanceof PropertyExpression
&& ((PropertyExpression) leftExpression).isSpreadSafe()
- && StaticTypeCheckingSupport.isAssignment(expression.getOperation().getType())) {
+ && isAssignment(expression.getOperation().getType())) {
// rewrite it so that it can be statically compiled
transformSpreadOnLHS(expression);
return;
@@ -225,8 +224,7 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
operandStack.remove(1); // receiver consumed by if()
Label nonull = compileStack.createLocalLabel("nonull_" + counter);
mv.visitLabel(nonull);
- ClassNode componentType = StaticTypeCheckingVisitor.inferLoopElementType(
- controller.getTypeChooser().resolveType(receiver, controller.getClassNode()));
+ ClassNode componentType = inferLoopElementType(controller.getTypeChooser().resolveType(receiver, controller.getClassNode()));
Parameter iterator = new Parameter(componentType, "for$it$" + counter);
VariableExpression iteratorAsVar = varX(iterator);
PropertyExpression pexp = spreadExpression instanceof AttributeExpression
@@ -357,7 +355,7 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
if (field != null && field.isPrivate() && !receiverType.equals(classNode)
&& (StaticInvocationWriter.isPrivateBridgeMethodsCallAllowed(receiverType, classNode)
|| StaticInvocationWriter.isPrivateBridgeMethodsCallAllowed(classNode,receiverType))) {
- Map<String, MethodNode> mutators = receiverType.redirect().getNodeMetaData(StaticCompilationMetadataKeys.PRIVATE_FIELDS_MUTATORS);
+ Map<String, MethodNode> mutators = receiverType.redirect().getNodeMetaData(PRIVATE_FIELDS_MUTATORS);
if (mutators != null) {
MethodNode methodNode = mutators.get(fieldName);
if (methodNode != null) {
@@ -375,30 +373,27 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
}
@Override
- protected void assignToArray(final Expression parent, final Expression receiver, final Expression index, final Expression rhsValueLoader, final boolean safe) {
- ClassNode arrayType = controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
- int operationType = getOperandType(arrayType.getComponentType());
- BinaryExpressionWriter bew = binExpWriter[operationType];
+ protected void assignToArray(final Expression enclosing, final Expression receiver, final Expression subscript, final Expression rhsValueLoader, final boolean safe) {
+ ClassNode receiverType = controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
- if (bew.arraySet(true) && arrayType.isArray() && !safe) {
- super.assignToArray(parent, receiver, index, rhsValueLoader, safe);
+ if (receiverType.isArray() && !safe && binExpWriter[getOperandType(receiverType.getComponentType())].arraySet(true)) {
+ super.assignToArray(enclosing, receiver, subscript, rhsValueLoader, safe);
} else {
/*
* This code path is needed because ACG creates array access expressions
*/
- StaticTypeCheckingVisitor visitor = new StaticCompilationVisitor(controller.getSourceUnit(), controller.getClassNode());
+
// GROOVY-6061
- if (rhsValueLoader instanceof VariableSlotLoader && parent instanceof BinaryExpression) {
- rhsValueLoader.putNodeMetaData(INFERRED_TYPE, controller.getTypeChooser().resolveType(parent, controller.getClassNode()));
+ if (rhsValueLoader instanceof VariableSlotLoader && enclosing instanceof BinaryExpression) {
+ rhsValueLoader.putNodeMetaData(INFERRED_TYPE, controller.getTypeChooser().resolveType(enclosing, controller.getClassNode()));
}
- // let's replace this assignment to a subscript operator with a method call
- // e.g. x[5] = 10
- // -> (x, [], 5), =, 10
- // -> methodCall(x, "putAt", [5, 10])
- MethodCallExpression call = callX(receiver, "putAt", args(index, rhsValueLoader));
+
+ // replace assignment to a subscript operator with a method call
+ // e.g. x[5] = 10 -> methodCall(x, "putAt", [5, 10])
+ MethodCallExpression call = callX(receiver, "putAt", args(subscript, rhsValueLoader));
call.setSafe(safe);
- call.setSourcePosition(parent);
- visitor.visitMethodCallExpression(call);
+ call.setSourcePosition(enclosing);
+ call.visit(new StaticCompilationVisitor(controller.getSourceUnit(), controller.getClassNode()));
OperandStack operandStack = controller.getOperandStack();
int height = operandStack.getStackLength();
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7361Bug.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7361Bug.groovy
index 4eca251..e7f26a4 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7361Bug.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7361Bug.groovy
@@ -16,47 +16,46 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-
package org.codehaus.groovy.classgen.asm.sc.bugs
import groovy.transform.stc.StaticTypeCheckingTestCase
import org.codehaus.groovy.classgen.asm.sc.StaticCompilationTestSupport
-class Groovy7361Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
+final class Groovy7361Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
+
void testShouldNotThrowVerifyError() {
assertScript '''
- class TaskManager {
- private final Map<Long, String> map = [1L:'a',2L:'b']
- void doh() {
- def list = [1L]
- list.each {
- synchronized (map) {
- map.remove(it)
- }
+ class A {
+ private final Map<Long, String> map = [1L:'x', 2L:'y']
+ def m() {
+ def list = [1L]
+ list.each {
+ synchronized (map) {
+ map.remove(it)
}
}
+ map
}
- new TaskManager().doh()
- '''
+ }
+ assert new A().m() == [2L:'y']
+ '''
}
void testShouldNotThrowClassCastException() {
assertScript '''
class A {
private final Map map = [:]
- Map foo() {
+ def m() {
new Runnable() {
@Override
- void run(){
- { -> map['a']='b'}.call()
+ void run() {
+ { -> map['x'] = 'y' }.call()
}
}.run()
map
}
}
- def a = new A()
- assert a.foo() == [a:'b']
+ assert new A().m() == [x:'y']
'''
}
}
[groovy] 19/19: reduce impact of makeAccessible(AccessibleObject)
(closes #1357)
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit f7b86016463aa0bce39eade97c200da70e646be0
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 29 12:38:34 2020 -0500
reduce impact of makeAccessible(AccessibleObject) (closes #1357)
(cherry picked from commit 9fb9e506eb2af8e96a593e08d64cfae5b5acf007)
---
.../java/org/codehaus/groovy/reflection/ReflectionUtils.java | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java b/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
index 780e7a7..411b79d 100644
--- a/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
+++ b/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
@@ -196,8 +196,14 @@ public class ReflectionUtils {
// to be run in PrivilegedAction!
public static Optional<AccessibleObject> makeAccessible(final AccessibleObject ao) {
- AccessibleObject[] result = makeAccessible(new AccessibleObject[] {ao});
- return Optional.ofNullable(result.length == 0 ? null : result[0]);
+ try {
+ if (ao.isAccessible() || trySetAccessible(ao)) {
+ return Optional.of(ao);
+ }
+ } catch (Throwable ignore) {
+ // swallow for strict security managers, module systems, android, etc.
+ }
+ return Optional.empty();
}
// to be run in PrivilegedAction!
[groovy] 10/19: GROOVY-9700: SC: transform variable assignment to
direct setter call
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 80400b1b153eb52ba40e1a32b37c72529cb43eed
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Aug 26 07:44:51 2020 -0500
GROOVY-9700: SC: transform variable assignment to direct setter call
closes #1351
(cherry picked from commit f48603a8ce477b7b3a4c7186bd17da7acea47aac)
---
.../transformers/BinaryExpressionTransformer.java | 59 +++++++++++++++++-----
.../sc/FieldsAndPropertiesStaticCompileTest.groovy | 30 +++++++++++
2 files changed, 76 insertions(+), 13 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
index 31df52a..86261aa 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
@@ -102,11 +102,31 @@ public class BinaryExpressionTransformer {
MethodNode directMCT = leftExpression.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
if (directMCT != null) {
Expression left = staticCompilationTransformer.transform(leftExpression);
+ Expression right = staticCompilationTransformer.transform(rightExpression);
if (left instanceof PropertyExpression) {
- Expression right = staticCompilationTransformer.transform(rightExpression);
- return transformPropertyAssignmentToSetterCall((PropertyExpression) left, right, directMCT);
+ // transform "a.x = val" into "def tmp = val; a.setX(tmp); tmp"
+ PropertyExpression pe = (PropertyExpression) left;
+ return transformAssignmentToSetterCall(
+ pe.getObjectExpression(), // "a"
+ directMCT, // "setX"
+ right, // "val"
+ false,
+ pe.isSafe(),
+ pe.getProperty(), // "x"
+ bin // "a.x = val"
+ );
+ } else if (left instanceof VariableExpression) {
+ // transform "x = val" into "def tmp = val; this.setX(tmp); tmp"
+ return transformAssignmentToSetterCall(
+ varX("this"),
+ directMCT, // "setX"
+ right, // "val"
+ true,
+ false,
+ left, // "x"
+ bin // "x = val"
+ );
}
- // TODO: Handle left instanceof VariableExpression and has DIRECT_METHOD_CALL_TARGET?
}
} else if (operationType == Types.COMPARE_EQUAL || operationType == Types.COMPARE_NOT_EQUAL) {
// let's check if one of the operands is the null constant
@@ -357,17 +377,30 @@ public class BinaryExpressionTransformer {
throw new IllegalArgumentException("Unsupported conversion");
}
- private static Expression transformPropertyAssignmentToSetterCall(final PropertyExpression leftExpression, final Expression rightExpression, final MethodNode directMCT) {
- // transform "a.x = b" into "def tmp = b; a.setX(tmp); tmp"
+ /**
+ * Adapter for {@link StaticPropertyAccessHelper#transformToSetterCall}.
+ */
+ private static Expression transformAssignmentToSetterCall(
+ final Expression receiver,
+ final MethodNode setterMethod,
+ final Expression valueExpression,
+ final boolean implicitThis,
+ final boolean safeNavigation,
+ final Expression nameExpression,
+ final Expression binaryExpression) {
+ // expression that will transfer assignment and name positions
+ Expression pos = new PropertyExpression(null, nameExpression);
+ pos.setSourcePosition(binaryExpression);
+
return StaticPropertyAccessHelper.transformToSetterCall(
- leftExpression.getObjectExpression(),
- directMCT,
- rightExpression,
- false,
- leftExpression.isSafe(),
- false,
- true, // to be replaced with a proper test whether a return value should be used or not
- leftExpression
+ receiver,
+ setterMethod,
+ valueExpression,
+ implicitThis,
+ safeNavigation,
+ false, // spreadSafe
+ true, // TODO: replace with a proper test whether a return value is required or not
+ pos
);
}
}
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
index 8a0a33d..3150e2b 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
@@ -610,6 +610,36 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
'''
}
+ // GROOVY-9700
+ void testVariableAssignmentUsesDirectSetterCall() {
+ assertScript '''
+ import org.codehaus.groovy.transform.sc.ListOfExpressionsExpression
+
+ class Foo {
+ void setX(Date value) {}
+ void setX(Long value) {}
+ }
+ class Bar extends Foo {
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ def assignment = node.code.statements[0].expression
+ assert assignment instanceof ListOfExpressionsExpression
+ assignment = node.code.statements[1].expression
+ assert assignment instanceof ListOfExpressionsExpression
+ })
+ void test() {
+ x = 42L
+ x = new Date()
+ }
+ }
+ new Bar().test()
+ '''
+
+ def bar = astTrees['Bar'][1]
+ assert bar.contains('INVOKEVIRTUAL Bar.setX (Ljava/lang/Long;)V')
+ assert bar.contains('INVOKEVIRTUAL Bar.setX (Ljava/util/Date;)V')
+ assert !bar.contains('INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.setGroovyObjectProperty ')
+ }
+
void testPrivateFieldMutationInClosureUsesBridgeMethod() {
try {
assertScript '''
[groovy] 12/19: promote early returns, remove extra calls,
and other minor edits
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit d257cbf0cc5e84d488d31297bb379cf3444c1b8d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Aug 27 12:06:40 2020 -0500
promote early returns, remove extra calls, and other minor edits
(cherry picked from commit 08cd04304e6e01fb935ba54a662e613910883af4)
---
.../transform/stc/StaticTypeCheckingVisitor.java | 102 ++++++++++-----------
1 file changed, 48 insertions(+), 54 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 d237f31..4e9ae6e 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2927,9 +2927,11 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
private void doInferClosureParameterTypes(final ClassNode receiver, final Expression arguments, final ClosureExpression expression, final MethodNode selectedMethod, final Expression hintClass, final Expression resolverClass, final Expression options) {
- List<ClassNode[]> closureSignatures = getSignaturesFromHint(expression, selectedMethod, hintClass, options);
- List<ClassNode[]> candidates = new LinkedList<ClassNode[]>();
Parameter[] closureParams = expression.getParameters();
+ if (closureParams == null) return; // no-arg closure
+
+ List<ClassNode[]> closureSignatures = getSignaturesFromHint(expression, selectedMethod, hintClass, options);
+ List<ClassNode[]> candidates = new LinkedList<>();
for (ClassNode[] signature : closureSignatures) {
// in order to compute the inferred types of the closure parameters, we're using the following trick:
// 1. create a dummy MethodNode for which the return type is a class node for which the generic types are the types returned by the hint
@@ -2938,7 +2940,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
// In practice, it could be done differently but it has the main advantage of reusing
// existing code, hence reducing the amount of code to debug in case of failure.
ClassNode[] inferred = resolveGenericsFromTypeHint(receiver, arguments, selectedMethod, signature);
- if (closureParams == null) return; // no-arg closure
if (signature.length == closureParams.length // same number of arguments
|| (signature.length == 1 && closureParams.length == 0) // implicit it
|| (closureParams.length > signature.length && inferred[inferred.length - 1].isArray())) { // vargs
@@ -3407,9 +3408,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (mn.size() == 1) {
MethodNode directMethodCallCandidate = mn.get(0);
- if (call.getNodeMetaData(DYNAMIC_RESOLUTION) == null &&
- !directMethodCallCandidate.isStatic() && objectExpression instanceof ClassExpression &&
- !"java.lang.Class".equals(directMethodCallCandidate.getDeclaringClass().getName())) {
+ if (call.getNodeMetaData(DYNAMIC_RESOLUTION) == null
+ && !directMethodCallCandidate.isStatic() && objectExpression instanceof ClassExpression
+ && !"java.lang.Class".equals(directMethodCallCandidate.getDeclaringClass().getName())) {
ClassNode owner = directMethodCallCandidate.getDeclaringClass();
addStaticTypeError("Non static method " + owner.getName() + "#" + directMethodCallCandidate.getName() + " cannot be called from static context", call);
}
@@ -4142,8 +4143,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
private static boolean isEmptyCollection(final Expression expr) {
- return (expr instanceof ListExpression && ((ListExpression) expr).getExpressions().size() == 0)
- || (expr instanceof MapExpression && ((MapExpression) expr).getMapEntryExpressions().size() == 0);
+ return (expr instanceof ListExpression && ((ListExpression) expr).getExpressions().isEmpty())
+ || (expr instanceof MapExpression && ((MapExpression) expr).getMapEntryExpressions().isEmpty());
}
private static boolean hasInferredReturnType(final Expression expression) {
@@ -5074,32 +5075,27 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
*/
protected ClassNode inferReturnTypeGenerics(final ClassNode receiver, final MethodNode method, final Expression arguments, final GenericsType[] explicitTypeHints) {
ClassNode returnType = method.getReturnType();
- if (method instanceof ExtensionMethodNode
- && (isUsingGenericsOrIsArrayUsingGenerics(returnType))) {
+ if (getGenericsWithoutArray(returnType) == null) {
+ return returnType;
+ }
+ if (method instanceof ExtensionMethodNode) {
// check if the placeholder corresponds to the placeholder of the first parameter
ExtensionMethodNode emn = (ExtensionMethodNode) method;
- MethodNode dgmMethod = emn.getExtensionMethodNode();
- ClassNode dc = emn.getDeclaringClass();
- ArgumentListExpression argList = new ArgumentListExpression();
- VariableExpression vexp = varX("$foo", receiver);
- vexp.setNodeMetaData(ExtensionMethodDeclaringClass.class, dc);
- argList.addExpression(vexp);
+ MethodNode dgm = emn.getExtensionMethodNode();
+ ArgumentListExpression args = new ArgumentListExpression();
+ VariableExpression vexp = varX("$self", receiver);
+ args.addExpression(vexp);
+ vexp.setNodeMetaData(ExtensionMethodDeclaringClass.class, emn.getDeclaringClass());
if (arguments instanceof ArgumentListExpression) {
- List<Expression> expressions = ((ArgumentListExpression) arguments).getExpressions();
- for (Expression arg : expressions) {
- argList.addExpression(arg);
+ for (Expression argument : (ArgumentListExpression) arguments) {
+ args.addExpression(argument);
}
} else {
- argList.addExpression(arguments);
+ args.addExpression(arguments);
}
- return inferReturnTypeGenerics(receiver, dgmMethod, argList);
+ return inferReturnTypeGenerics(receiver, dgm, args);
}
- if (!isUsingGenericsOrIsArrayUsingGenerics(returnType)) return returnType;
- if (getGenericsWithoutArray(returnType) == null) return returnType;
Map<GenericsTypeName, GenericsType> resolvedPlaceholders = resolvePlaceHoldersFromDeclaration(receiver, getDeclaringClass(method, arguments), method, method.isStatic());
- if (!receiver.isGenericsPlaceHolder()) {
- GenericsUtils.extractPlaceholders(receiver, resolvedPlaceholders);
- }
resolvePlaceholdersFromExplicitTypeHints(method, explicitTypeHints, resolvedPlaceholders);
if (resolvedPlaceholders.isEmpty()) {
return boundUnboundedWildcards(returnType);
@@ -5108,37 +5104,35 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
applyGenericsConnections(placeholdersFromContext, resolvedPlaceholders);
// then resolve receivers from method arguments
+ List<Expression> expressions = InvocationWriter.makeArgumentList(arguments).getExpressions();
Parameter[] parameters = method.getParameters();
boolean isVargs = isVargs(parameters);
- ArgumentListExpression argList = InvocationWriter.makeArgumentList(arguments);
- List<Expression> expressions = argList.getExpressions();
int paramLength = parameters.length;
if (expressions.size() >= paramLength) {
- for (int i = 0; i < paramLength; i++) {
- boolean lastArg = i == paramLength - 1;
- ClassNode type = parameters[i].getType();
- ClassNode actualType = getType(expressions.get(i));
- while (!type.isUsingGenerics() && type.isArray() && actualType.isArray()) {
- type = type.getComponentType();
- actualType = actualType.getComponentType();
+ for (int i = 0; i < paramLength; i += 1) {
+ boolean lastArg = (i == paramLength - 1);
+ ClassNode paramType = parameters[i].getType();
+ ClassNode argumentType = getType(expressions.get(i));
+ while (paramType.isArray() && argumentType.isArray()) {
+ paramType = paramType.getComponentType();
+ argumentType = argumentType.getComponentType();
}
- if (isUsingGenericsOrIsArrayUsingGenerics(type)) {
- if (implementsInterfaceOrIsSubclassOf(actualType, CLOSURE_TYPE) &&
- isSAMType(type)) {
+ if (isUsingGenericsOrIsArrayUsingGenerics(paramType)) {
+ if (implementsInterfaceOrIsSubclassOf(argumentType, CLOSURE_TYPE) && isSAMType(paramType)) {
// implicit closure coercion in action!
- Map<GenericsTypeName, GenericsType> pholders = applyGenericsContextToParameterClass(resolvedPlaceholders, type);
- actualType = convertClosureTypeToSAMType(expressions.get(i), actualType, type, pholders);
+ Map<GenericsTypeName, GenericsType> pholders = applyGenericsContextToParameterClass(resolvedPlaceholders, paramType);
+ argumentType = convertClosureTypeToSAMType(expressions.get(i), argumentType, paramType, pholders);
}
- if (isVargs && lastArg && actualType.isArray()) {
- actualType = actualType.getComponentType();
+ if (isVargs && lastArg && argumentType.isArray()) {
+ argumentType = argumentType.getComponentType();
}
- if (isVargs && lastArg && type.isArray()) {
- type = type.getComponentType();
+ if (isVargs && lastArg && paramType.isArray()) {
+ paramType = paramType.getComponentType();
}
- actualType = wrapTypeIfNecessary(actualType);
+ argumentType = wrapTypeIfNecessary(argumentType);
Map<GenericsTypeName, GenericsType> connections = new HashMap<>();
- extractGenericsConnections(connections, actualType, type);
+ extractGenericsConnections(connections, argumentType, paramType);
extractGenericsConnectionsForSuperClassAndInterfaces(resolvedPlaceholders, connections);
applyGenericsConnections(connections, resolvedPlaceholders);
}
@@ -5152,7 +5146,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (explicitTypeHints != null) {
GenericsType[] methodGenericTypes = method.getGenericsTypes();
if (methodGenericTypes != null && methodGenericTypes.length == explicitTypeHints.length) {
- for (int i = 0; i < explicitTypeHints.length; i++) {
+ for (int i = 0, n = methodGenericTypes.length; i < n; i += 1) {
GenericsType methodGenericType = methodGenericTypes[i];
GenericsType explicitTypeHint = explicitTypeHints[i];
resolvedPlaceholders.put(new GenericsTypeName(methodGenericType.getName()), explicitTypeHint);
@@ -5325,17 +5319,17 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (isPrimitiveType(receiver) && !isPrimitiveType(declaringClass)) {
receiver = getWrapper(receiver);
}
- List<ClassNode> queue;
+ ClassNode[] todo;
if (receiver instanceof UnionTypeClassNode) {
- queue = Arrays.asList(((UnionTypeClassNode) receiver).getDelegates());
+ todo = ((UnionTypeClassNode) receiver).getDelegates();
} else {
- queue = Collections.singletonList(receiver);
+ todo = new ClassNode[] {receiver};
}
- for (ClassNode item : queue) {
- ClassNode current = item;
+ for (ClassNode type : todo) {
+ ClassNode current = type;
while (current != null) {
boolean continueLoop = true;
- //extract the place holders
+ // extract the place holders
Map<GenericsTypeName, GenericsType> currentPlaceHolders = new HashMap<>();
if (isGenericsPlaceHolderOrArrayOf(declaringClass) || declaringClass.equals(current)) {
extractGenericsConnections(currentPlaceHolders, current, declaringClass);
@@ -5362,7 +5356,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (!continueLoop) break;
current = getNextSuperClass(current, declaringClass);
- if (current == null && CLASS_Type.equals(declaringClass)) {
+ if (current == null && declaringClass.equals(CLASS_Type)) {
// this can happen if the receiver is Class<Foo>, then
// the actual receiver is Foo and declaringClass is Class
current = declaringClass;
[groovy] 01/19: GROOVY-9672: replace "this" argument with "Type"
for static super call
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit d093ed33b3967dc2a090c7dc5a6f422f40c3a565
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Aug 17 17:33:39 2020 -0500
GROOVY-9672: replace "this" argument with "Type" for static super call
closes #1344
(cherry picked from commit 05e02e09b5699256b7d920fa13824ccbb072f892)
---
.../transform/trait/SuperCallTraitTransformer.java | 32 +++--
.../traitx/TraitASTTransformationTest.groovy | 141 +++++++++++++++++++++
2 files changed, 165 insertions(+), 8 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
index e8f1c35..8e9193d 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
@@ -33,13 +33,15 @@ import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.PropertyExpression;
import org.codehaus.groovy.ast.expr.TupleExpression;
-import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.tools.ClosureUtils;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.syntax.Types;
+import java.util.List;
import java.util.function.Function;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_STATIC;
@@ -100,12 +102,13 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
String setterName = MetaProperty.getSetterName(leftExpression.getPropertyAsString());
for (MethodNode method : helperType.getMethods(setterName)) {
Parameter[] parameters = method.getParameters();
- if (parameters.length == 2 && parameters[0].getType().equals(traitType)) {
+ if (parameters.length == 2 && isSelfType(parameters[0], traitType)) {
MethodCallExpression setterCall = new MethodCallExpression(
new ClassExpression(helperType),
setterName,
new ArgumentListExpression(
- new VariableExpression("this"),
+ parameters[0].getType().equals(ClassHelper.CLASS_Type)
+ ? thisPropX(false, "class") : varX("this"),
bin.getRightExpression()
)
);
@@ -143,7 +146,8 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
new ClassExpression(helperType),
methodNode.getName(),
new ArgumentListExpression(
- new VariableExpression("this")
+ methodNode.getParameters()[0].getType().equals(ClassHelper.CLASS_Type)
+ ? thisPropX(false, "class") : varX("this")
)
);
methodCall.getObjectExpression().setSourcePosition(((PropertyExpression) exp.getObjectExpression()).getObjectExpression());
@@ -157,7 +161,7 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
String getterName = MetaProperty.getGetterName(exp.getPropertyAsString(), null);
for (MethodNode method : helperType.getMethods(getterName)) {
if (method.isStatic() && method.getParameters().length == 1
- && method.getParameters()[0].getType().equals(traitType)
+ && isSelfType(method.getParameters()[0], traitType)
&& !method.getReturnType().equals(ClassHelper.VOID_TYPE)) {
return xform.apply(method);
}
@@ -166,7 +170,7 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
String isserName = "is" + getterName.substring(3);
for (MethodNode method : helperType.getMethods(isserName)) {
if (method.isStatic() && method.getParameters().length == 1
- && method.getParameters()[0].getType().equals(traitType)
+ && isSelfType(method.getParameters()[0], traitType)
&& method.getReturnType().equals(ClassHelper.boolean_TYPE)) {
return xform.apply(method);
}
@@ -183,8 +187,12 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
ClassNode helperType = getHelper(traitType);
// TraitType.super.foo() -> TraitType$Trait$Helper.foo(this)
- ArgumentListExpression newArgs = new ArgumentListExpression();
- newArgs.addExpression(new VariableExpression("this"));
+ List<MethodNode> targets = helperType.getMethods(exp.getMethodAsString());
+ boolean isStatic = !targets.isEmpty() && targets.stream().map(MethodNode::getParameters)
+ .allMatch(params -> params.length > 0 && params[0].getType().equals(ClassHelper.CLASS_Type));
+
+ ArgumentListExpression newArgs = new ArgumentListExpression(
+ isStatic ? thisPropX(false, "class") : varX("this"));
Expression arguments = exp.getArguments();
if (arguments instanceof TupleExpression) {
for (Expression expression : (TupleExpression) arguments) {
@@ -240,4 +248,12 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
}
return null;
}
+
+ private static boolean isSelfType(final Parameter parameter, final ClassNode traitType) {
+ ClassNode paramType = parameter.getType();
+ if (paramType.equals(traitType)) return true;
+ return paramType.equals(ClassHelper.CLASS_Type)
+ && paramType.getGenericsTypes() != null
+ && paramType.getGenericsTypes()[0].getType().equals(traitType);
+ }
}
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index 45a91b1..e785703 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -1066,6 +1066,72 @@ final class TraitASTTransformationTest {
'''
}
+ @Test // GROOVY-9672
+ void testTraitSuperPropertyGetStatic() {
+ assertScript '''
+ trait T {
+ static x = 'value'
+ }
+ class C implements T {
+ def test() {
+ T.super.x
+ }
+ }
+ assert new C().test() == 'value'
+ '''
+
+ assertScript '''
+ trait T {
+ static boolean x = true
+ }
+ class C implements T {
+ def test() {
+ T.super.x
+ }
+ }
+ assert new C().test() == true
+ '''
+
+ assertScript '''
+ trait T {
+ static getX() { 'value' }
+ }
+ class C implements T {
+ def test() {
+ T.super.x
+ }
+ }
+ assert new C().test() == 'value'
+ '''
+
+ assertScript '''
+ trait T {
+ static boolean isX() { true }
+ }
+ class C implements T {
+ def test() {
+ T.super.x
+ }
+ }
+ assert new C().test() == true
+ '''
+
+ assertScript '''
+ trait A {
+ static getX() { 'A' }
+ }
+ trait B {
+ static getX() { 'B' }
+ }
+ class C implements A, B {
+ def test() {
+ A.super.x + B.super.x
+ }
+ }
+ assert new C().test() == 'AB'
+ '''
+ }
+
@Test
void testTraitSuperPropertySet() {
assertScript '''
@@ -1123,6 +1189,63 @@ final class TraitASTTransformationTest {
'''
}
+ @Test // GROOVY-9672
+ void testTraitSuperPropertySetStatic() {
+ assertScript '''
+ trait T {
+ static x
+ }
+ class C implements T {
+ def test() {
+ T.super.x = 'value'
+ return x
+ }
+ }
+ assert new C().test() == 'value'
+ '''
+
+ def err = shouldFail '''
+ trait T {
+ static final x = 'const'
+ }
+ class C implements T {
+ def test() {
+ T.super.x = 'value'
+ return x
+ }
+ }
+ assert new C().test() == 'value'
+ '''
+ assert err =~ /No such property: super for class: T/
+
+ assertScript '''
+ trait T {
+ static setX(value) { 'retval' }
+ }
+ class C implements T {
+ def test() {
+ T.super.x = 'value'
+ }
+ }
+ assert new C().test() == 'retval'
+ '''
+
+ assertScript '''
+ trait A {
+ static setX(value) { 'A' }
+ }
+ trait B {
+ static setX(value) { 'B' }
+ }
+ class C implements A, B {
+ def test() {
+ (A.super.x = 'a') + (B.super.x = 'b')
+ }
+ }
+ assert new C().test() == 'AB'
+ '''
+ }
+
@Test // GROOVY-9673
void testTraitSuperPropertySetWithOverloads() {
assertScript '''
@@ -1160,6 +1283,24 @@ final class TraitASTTransformationTest {
'''
}
+ @Test // GROOVY-9672
+ void testTraitSuperCallStatic() {
+ assertScript '''
+ trait A {
+ static m() { 'A' }
+ }
+ trait B {
+ static m() { 'B' }
+ }
+ class C implements A, B {
+ def test() {
+ m() + A.super.m() + B.super.m()
+ }
+ }
+ assert new C().test() == 'BAB'
+ '''
+ }
+
@Test
void testTraitSuperCallWhenExtendingAnotherTrait() {
assertScript '''
[groovy] 08/19: GROOVY-9699: SC: reposition
checkOrMarkPrivateAccess for field reference
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 6a10018edce16094cba5cef1177bbe73b7421b0a
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Aug 24 17:12:40 2020 -0500
GROOVY-9699: SC: reposition checkOrMarkPrivateAccess for field reference
and drop extra visitation for "putAt" method call transformation
* reuse getType for field in visitVariableExpression and simplify its flow
closes #1349
(cherry picked from commit 97ba01a4d4237a8fc7863818d59fb793dbf7236c)
---
...icTypesBinaryExpressionMultiTypeDispatcher.java | 2 -
.../transform/stc/StaticTypeCheckingVisitor.java | 89 ++++++++--------------
.../classgen/asm/sc/bugs/Groovy7361Bug.groovy | 29 +++++++
3 files changed, 59 insertions(+), 61 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
index 26685e5..9c835fd 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
@@ -44,7 +44,6 @@ import org.codehaus.groovy.classgen.asm.VariableSlotLoader;
import org.codehaus.groovy.classgen.asm.WriterController;
import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.TokenUtil;
-import org.codehaus.groovy.transform.sc.StaticCompilationVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -393,7 +392,6 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
MethodCallExpression call = callX(receiver, "putAt", args(subscript, rhsValueLoader));
call.setSafe(safe);
call.setSourcePosition(enclosing);
- call.visit(new StaticCompilationVisitor(controller.getSourceUnit(), controller.getClassNode()));
OperandStack operandStack = controller.getOperandStack();
int height = operandStack.getStackLength();
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 6b69ee6..d237f31 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -189,8 +189,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.isOrImplements;
import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.findActualTypeByGenericsPlaceholderName;
-import static org.codehaus.groovy.ast.tools.GenericsUtils.makeDeclaringAndActualGenericsTypeMapOfExactType;
import static org.codehaus.groovy.ast.tools.GenericsUtils.toGenericTypesString;
import static org.codehaus.groovy.ast.tools.WideningCategories.isBigDecCategory;
import static org.codehaus.groovy.ast.tools.WideningCategories.isBigIntCategory;
@@ -552,7 +550,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
final Variable accessedVariable = vexp.getAccessedVariable();
final TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure();
- VariableExpression localVariableExpression = null;
+ if (accessedVariable == null) {
+ return;
+ }
+
if (accessedVariable instanceof DynamicVariable) {
// a dynamic variable is either a closure property, a class member referenced from a closure, or an undeclared variable
@@ -594,20 +595,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (enclosingClosure != null) {
tryVariableExpressionAsProperty(vexp, name);
} else {
+ checkOrMarkPrivateAccess(vexp, (FieldNode) accessedVariable, typeCheckingContext.isTargetOfEnclosingAssignment(vexp));
+
// GROOVY-9454
ClassNode inferredType = getInferredTypeFromTempInfo(vexp, null);
if (inferredType != null && !inferredType.equals(OBJECT_TYPE)) {
vexp.putNodeMetaData(INFERRED_RETURN_TYPE, inferredType);
} else {
- // GROOVY-7691
- FieldNode fieldNode = (FieldNode) accessedVariable;
- ClassNode fieldType = findActualTypeByGenericsPlaceholderName(
- fieldNode.getOriginType().getUnresolvedName(),
- makeDeclaringAndActualGenericsTypeMapOfExactType(fieldNode.getDeclaringClass(), typeCheckingContext.getEnclosingClassNode())
- );
- if (fieldType != null) {
- storeType(vexp, fieldType);
- }
+ storeType(vexp, getType(vexp));
}
}
} else if (accessedVariable instanceof PropertyNode) {
@@ -621,25 +616,21 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
SetterInfo setterInfo = removeSetterInfo(leftExpression);
if (setterInfo != null) {
Expression rightExpression = enclosingBinaryExpression.getRightExpression();
- if (!ensureValidSetter(vexp, leftExpression, rightExpression, setterInfo)) {
- return;
- }
+ ensureValidSetter(vexp, leftExpression, rightExpression, setterInfo);
}
}
}
- } else if (accessedVariable instanceof Parameter) {
- if (enclosingClosure == null) {
- localVariableExpression = new ParameterVariableExpression((Parameter) accessedVariable);
- }
- } else if (accessedVariable instanceof VariableExpression) {
- if (enclosingClosure == null) {
- localVariableExpression = (VariableExpression) accessedVariable;
+ } else if (enclosingClosure == null) {
+ VariableExpression localVariable;
+ if (accessedVariable instanceof Parameter) {
+ Parameter parameter = (Parameter) accessedVariable;
+ localVariable = new ParameterVariableExpression(parameter);
+ } else {
+ localVariable = (VariableExpression) accessedVariable;
}
- }
- if (localVariableExpression != null) {
- ClassNode inferredType = localVariableExpression.getNodeMetaData(INFERRED_TYPE);
- inferredType = getInferredTypeFromTempInfo(localVariableExpression, inferredType);
+ ClassNode inferredType = localVariable.getNodeMetaData(INFERRED_TYPE);
+ inferredType = getInferredTypeFromTempInfo(localVariable, inferredType);
if (inferredType != null && !inferredType.equals(OBJECT_TYPE)) {
vexp.putNodeMetaData(INFERRED_RETURN_TYPE, inferredType);
}
@@ -1265,12 +1256,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
ClassNode inferredRightExpressionType = inferredRightExpressionTypeOrig;
if (!typeCheckMultipleAssignmentAndContinue(leftExpression, rightExpression)) return;
- if (leftExpression instanceof VariableExpression
- && ((VariableExpression) leftExpression).getAccessedVariable() instanceof FieldNode) {
- checkOrMarkPrivateAccess(leftExpression, (FieldNode) ((VariableExpression) leftExpression).getAccessedVariable(), true);
- }
-
- //TODO: need errors for write-only too!
+ // TODO: need errors for write-only too!
if (addedReadOnlyPropertyError(leftExpression)) return;
ClassNode leftRedirect = leftExpressionType.redirect();
@@ -4811,9 +4797,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (vexp.isSuperExpression()) return makeSuper();
Variable variable = vexp.getAccessedVariable();
if (variable instanceof FieldNode) {
- FieldNode fieldNode = (FieldNode) variable;
- checkOrMarkPrivateAccess(vexp, fieldNode, typeCheckingContext.isTargetOfEnclosingAssignment(vexp));
- return getType(fieldNode);
+ ClassNode fieldType = variable.getOriginType();
+ if (isUsingGenericsOrIsArrayUsingGenerics(fieldType)) {
+ boolean isStatic = (variable.getModifiers() & Opcodes.ACC_STATIC) != 0;
+ ClassNode thisType = typeCheckingContext.getEnclosingClassNode(), declType = ((FieldNode) variable).getDeclaringClass();
+ Map<GenericsTypeName, GenericsType> placeholders = resolvePlaceHoldersFromDeclaration(thisType, declType, null, isStatic);
+
+ fieldType = resolveGenericsWithContext(placeholders, fieldType);
+ }
+ return fieldType;
}
if (variable != vexp && variable instanceof VariableExpression) {
return getType((Expression) variable);
@@ -4856,6 +4848,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
ClassNode ret = getInferredReturnType(exp);
return ret != null ? ret : ((MethodNode) exp).getReturnType();
}
+ if (exp instanceof FieldNode || exp instanceof PropertyNode) {
+ return ((Variable) exp).getOriginType();
+ }
if (exp instanceof RangeExpression) {
ClassNode plain = RANGE_TYPE.getPlainNodeReference();
RangeExpression re = (RangeExpression) exp;
@@ -4884,14 +4879,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (exp instanceof Parameter) {
return ((Parameter) exp).getOriginType();
}
- if (exp instanceof FieldNode) {
- FieldNode fn = (FieldNode) exp;
- return getGenericsResolvedTypeOfFieldOrProperty(fn, fn.getOriginType());
- }
- if (exp instanceof PropertyNode) {
- PropertyNode pn = (PropertyNode) exp;
- return getGenericsResolvedTypeOfFieldOrProperty(pn, pn.getOriginType());
- }
if (exp instanceof ClosureExpression) {
ClassNode irt = getInferredReturnType(exp);
if (irt != null) {
@@ -4931,22 +4918,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
return null;
}
- /**
- * resolves a Field or Property node generics by using the current class and
- * the declaring class to extract the right meaning of the generics symbols
- *
- * @param an a FieldNode or PropertyNode
- * @param type the origin type
- * @return the new ClassNode with corrected generics
- */
- private ClassNode getGenericsResolvedTypeOfFieldOrProperty(final AnnotatedNode an, final ClassNode type) {
- if (!type.isUsingGenerics()) return type;
- Map<GenericsTypeName, GenericsType> connections = new HashMap<>();
- // TODO: inner classes mean a different this-type. This is ignored here!
- extractGenericsConnections(connections, typeCheckingContext.getEnclosingClassNode(), an.getDeclaringClass());
- return applyGenericsContext(connections, type);
- }
-
private static ClassNode makeSelf(final ClassNode trait) {
ClassNode selfType = trait;
Set<ClassNode> selfTypes = Traits.collectSelfTypes(selfType, new LinkedHashSet<>());
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7361Bug.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7361Bug.groovy
index e7f26a4..9878851 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7361Bug.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7361Bug.groovy
@@ -58,4 +58,33 @@ final class Groovy7361Bug extends StaticTypeCheckingTestCase implements StaticCo
assert new A().m() == [x:'y']
'''
}
+
+ // GROOVY-9699
+ void testShouldNotEmitErrorForSubscriptPrivateAccess() {
+ assertScript '''
+ class A {
+ private static final java.util.regex.Pattern PATTERN = ~/.*/
+ void checkList() {
+ def list = []
+ def closure = { ->
+ list << PATTERN.pattern()
+ }
+ closure()
+ }
+ void checkMap() {
+ def map = [:]
+ def closure = { ->
+ map[PATTERN.pattern()] = 1
+ }
+ closure()
+ }
+ }
+ class B extends A {
+ }
+ new A().checkList()
+ new B().checkList()
+ new A().checkMap()
+ new B().checkMap()
+ '''
+ }
}
[groovy] 02/19: GROOVY-9691: don't make SMCE within closure outside
of special ctor call
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 1837fff301c02a295cb3dbadc17e327b30d78ed5
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Aug 17 17:34:12 2020 -0500
GROOVY-9691: don't make SMCE within closure outside of special ctor call
closes #1346
(cherry picked from commit fc50dca6a967ef52e0f653c2505bf6f24864c3fd)
---
.../groovy/control/StaticImportVisitor.java | 28 +++++++++-------
.../{Groovy8816Bug.groovy => Groovy8816.groovy} | 25 +++++++-------
.../{Groovy8816Bug.groovy => Groovy9691.groovy} | 39 +++++++++++++++-------
3 files changed, 56 insertions(+), 36 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java b/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
index 57b1540..100e861 100644
--- a/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/StaticImportVisitor.java
@@ -289,22 +289,26 @@ public class StaticImportVisitor extends ClassCodeExpressionTransformer {
return false;
};
- if (isInnerClass(currentClass)) {
- if (mce.isImplicitThis() && !inClosure && inSpecialConstructorCall && !foundInstanceMethod) {
- if (currentClass.getOuterClass().hasPossibleMethod(methodName, args)) {
- object = new PropertyExpression(new ClassExpression(currentClass.getOuterClass()), new ConstantExpression("this"));
- } else if (hasPossibleStaticMember.test(currentClass.getOuterClass())) {
- Expression result = new StaticMethodCallExpression(currentClass.getOuterClass(), methodName, args);
+ if (mce.isImplicitThis()) {
+ if (isInnerClass(currentClass)) {
+ if (inSpecialConstructorCall && !foundInstanceMethod) {
+ // check for reference to outer class method in this(...) or super(...)
+ if (currentClass.getOuterClass().hasPossibleMethod(methodName, args)) {
+ object = new PropertyExpression(new ClassExpression(currentClass.getOuterClass()), new ConstantExpression("this"));
+ } else if (hasPossibleStaticMember.test(currentClass.getOuterClass())) {
+ Expression result = new StaticMethodCallExpression(currentClass.getOuterClass(), methodName, args);
+ result.setSourcePosition(mce);
+ return result;
+ }
+ }
+ } else if (inSpecialConstructorCall || (!inClosure && !foundInstanceMethod && !methodName.equals("call"))) {
+ // check for reference to static method in this(...) or super(...) or when call not resolved
+ if (hasPossibleStaticMember.test(currentClass)) {
+ Expression result = new StaticMethodCallExpression(currentClass, methodName, args);
result.setSourcePosition(mce);
return result;
}
}
- } else if (inSpecialConstructorCall || (!foundInstanceMethod && !methodName.equals("call"))) {
- if (hasPossibleStaticMember.test(currentClass)) {
- Expression result = new StaticMethodCallExpression(currentClass, methodName, args);
- result.setSourcePosition(mce);
- return result;
- }
}
}
diff --git a/src/test/groovy/bugs/Groovy8816Bug.groovy b/src/test/groovy/bugs/Groovy8816.groovy
similarity index 67%
copy from src/test/groovy/bugs/Groovy8816Bug.groovy
copy to src/test/groovy/bugs/Groovy8816.groovy
index 2d6854d..0bd56e4 100644
--- a/src/test/groovy/bugs/Groovy8816Bug.groovy
+++ b/src/test/groovy/bugs/Groovy8816.groovy
@@ -18,21 +18,22 @@
*/
package groovy.bugs
-import groovy.test.GroovyTestCase
+import org.junit.Test
-class Groovy8816Bug extends GroovyTestCase {
- void testCallNoArgClosureWithArg() {
- def msg = shouldFail MissingMethodException, '''
- import groovy.transform.CompileStatic
+import static groovy.test.GroovyAssert.shouldFail
- @CompileStatic
- void main() {
- [0].each { -> }
- }
+final class Groovy8816 {
- main()
+ @Test
+ void testCallNoArgClosureWithArg() {
+ def err = shouldFail MissingMethodException, '''
+ @groovy.transform.CompileStatic
+ void test() {
+ [0].each { -> }
+ }
+ test()
'''
- assert msg.contains('No signature of method:')
- assert msg.contains('doCall() is applicable for argument types: (Integer) values: [0]')
+
+ assert err =~ /No signature of method: .*\.doCall\(\) is applicable for argument types: \(Integer\) values: \[0\]/
}
}
diff --git a/src/test/groovy/bugs/Groovy8816Bug.groovy b/src/test/groovy/bugs/Groovy9691.groovy
similarity index 50%
rename from src/test/groovy/bugs/Groovy8816Bug.groovy
rename to src/test/groovy/bugs/Groovy9691.groovy
index 2d6854d..6e179f2 100644
--- a/src/test/groovy/bugs/Groovy8816Bug.groovy
+++ b/src/test/groovy/bugs/Groovy9691.groovy
@@ -18,21 +18,36 @@
*/
package groovy.bugs
-import groovy.test.GroovyTestCase
+import org.junit.Test
-class Groovy8816Bug extends GroovyTestCase {
- void testCallNoArgClosureWithArg() {
- def msg = shouldFail MissingMethodException, '''
- import groovy.transform.CompileStatic
+import static groovy.test.GroovyAssert.assertScript
- @CompileStatic
- void main() {
- [0].each { -> }
- }
+final class Groovy9691 {
- main()
+ @Test
+ void testMainCallInClosure() {
+ assertScript '''
+ import org.codehaus.groovy.ast.expr.*
+
+ void sourceSets(Closure block) {
+ // no-op
+ }
+
+ sourceSets {
+ @groovy.transform.ASTTest({
+ def call = node.rightExpression
+ assert call instanceof MethodCall
+ assert !(call instanceof StaticMethodCallExpression)
+ })
+ x = main {
+ java { srcDirs = [] }
+ groovy { srcDirs = ['src/main'] }
+ }
+ test {
+ java { srcDirs = [] }
+ groovy { srcDirs = ['src/test'] }
+ }
+ }
'''
- assert msg.contains('No signature of method:')
- assert msg.contains('doCall() is applicable for argument types: (Integer) values: [0]')
}
}
[groovy] 14/19: reuse CachedField#getProperty
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 0357ffaa35efb27c8a091aa33fd15ffcf89c4c1d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 29 17:57:47 2020 -0500
reuse CachedField#getProperty
(cherry picked from commit 57c8a116098c750e6e00b727112f66f2b8c10df5)
---
.../callsite/GetEffectivePogoFieldSite.java | 58 ++++++++--------------
.../callsite/GetEffectivePojoFieldSite.java | 36 ++++++--------
2 files changed, 36 insertions(+), 58 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/runtime/callsite/GetEffectivePogoFieldSite.java b/src/main/java/org/codehaus/groovy/runtime/callsite/GetEffectivePogoFieldSite.java
index efa5fb5..b345cbe 100644
--- a/src/main/java/org/codehaus/groovy/runtime/callsite/GetEffectivePogoFieldSite.java
+++ b/src/main/java/org/codehaus/groovy/runtime/callsite/GetEffectivePogoFieldSite.java
@@ -19,60 +19,46 @@
package org.codehaus.groovy.runtime.callsite;
import groovy.lang.GroovyObject;
-import groovy.lang.GroovyRuntimeException;
import groovy.lang.MetaClass;
import org.codehaus.groovy.reflection.CachedField;
import org.codehaus.groovy.runtime.GroovyCategorySupport;
-import java.lang.reflect.Field;
-
public class GetEffectivePogoFieldSite extends AbstractCallSite {
private final MetaClass metaClass;
- private final Field effective;
+ private final CachedField effective;
- public GetEffectivePogoFieldSite(CallSite site, MetaClass metaClass, CachedField effective) {
+ public GetEffectivePogoFieldSite(final CallSite site, final MetaClass metaClass, final CachedField effective) {
super(site);
this.metaClass = metaClass;
- this.effective = effective.getCachedField();
+ this.effective = effective;
+ }
+
+ @Override
+ public final CallSite acceptGetProperty(final Object receiver) {
+ return isEffective(receiver) ? this : createGetPropertySite(receiver);
}
- public final Object callGetProperty (Object receiver) throws Throwable {
- if (GroovyCategorySupport.hasCategoryInCurrentThread() || !(receiver instanceof GroovyObject) || ((GroovyObject) receiver).getMetaClass() != metaClass) {
- return createGetPropertySite(receiver).getProperty(receiver);
- } else {
- return getProperty(receiver);
- }
+ @Override
+ public final CallSite acceptGroovyObjectGetProperty(final Object receiver) {
+ return isEffective(receiver) ? this : createGroovyObjectGetPropertySite(receiver);
}
- public final CallSite acceptGetProperty(Object receiver) {
- if (GroovyCategorySupport.hasCategoryInCurrentThread() || !(receiver instanceof GroovyObject) || ((GroovyObject)receiver).getMetaClass() != metaClass) {
- return createGetPropertySite(receiver);
- } else {
- return this;
- }
+ @Override
+ public final Object callGetProperty(final Object receiver) throws Throwable {
+ return isEffective(receiver) ? getProperty(receiver) : createGetPropertySite(receiver).getProperty(receiver);
}
- public final Object callGroovyObjectGetProperty (Object receiver) throws Throwable {
- if (GroovyCategorySupport.hasCategoryInCurrentThread() || ((GroovyObject) receiver).getMetaClass() != metaClass) {
- return createGroovyObjectGetPropertySite(receiver).getProperty(receiver);
- } else {
- return getProperty(receiver);
- }
+ @Override
+ public final Object callGroovyObjectGetProperty (final Object receiver) throws Throwable {
+ return isEffective(receiver) ? getProperty(receiver) : createGroovyObjectGetPropertySite(receiver).getProperty(receiver);
}
- public final CallSite acceptGroovyObjectGetProperty(Object receiver) {
- if (GroovyCategorySupport.hasCategoryInCurrentThread() || !(receiver instanceof GroovyObject) || ((GroovyObject)receiver).getMetaClass() != metaClass) {
- return createGroovyObjectGetPropertySite(receiver);
- } else {
- return this;
- }
+ @Override
+ public final Object getProperty(final Object receiver) {
+ return effective.getProperty(receiver);
}
- public final Object getProperty(Object receiver) {
- try {
- return effective.get(receiver);
- } catch (IllegalAccessException e) {
- throw new GroovyRuntimeException("Cannot get the property '" + name + "'.", e);
- }
+ private boolean isEffective(final Object receiver) {
+ return !GroovyCategorySupport.hasCategoryInCurrentThread() && receiver instanceof GroovyObject && ((GroovyObject) receiver).getMetaClass() == metaClass;
}
}
diff --git a/src/main/java/org/codehaus/groovy/runtime/callsite/GetEffectivePojoFieldSite.java b/src/main/java/org/codehaus/groovy/runtime/callsite/GetEffectivePojoFieldSite.java
index f1c4d71..2e8a698 100644
--- a/src/main/java/org/codehaus/groovy/runtime/callsite/GetEffectivePojoFieldSite.java
+++ b/src/main/java/org/codehaus/groovy/runtime/callsite/GetEffectivePojoFieldSite.java
@@ -18,43 +18,35 @@
*/
package org.codehaus.groovy.runtime.callsite;
-import groovy.lang.GroovyRuntimeException;
import groovy.lang.MetaClassImpl;
import org.codehaus.groovy.reflection.CachedField;
import org.codehaus.groovy.runtime.GroovyCategorySupport;
-import java.lang.reflect.Field;
-
class GetEffectivePojoFieldSite extends AbstractCallSite {
private final MetaClassImpl metaClass;
- private final Field effective;
- private final int version;
+ private final CachedField effective;
+ private final int metaClassVersion;
- public GetEffectivePojoFieldSite(CallSite site, MetaClassImpl metaClass, CachedField effective) {
+ public GetEffectivePojoFieldSite(final CallSite site, final MetaClassImpl metaClass, final CachedField effective) {
super(site);
this.metaClass = metaClass;
- this.effective = effective.getCachedField();
- version = metaClass.getVersion();
+ this.effective = effective;
+ this.metaClassVersion = metaClass.getVersion();
}
-// public final Object callGetProperty (Object receiver) throws Throwable {
-// return acceptGetProperty(receiver).getProperty(receiver);
-// }
+ @Override
+ public final CallSite acceptGetProperty(final Object receiver) {
+ if (GroovyCategorySupport.hasCategoryInCurrentThread()
+ || metaClass.getTheClass() != receiver.getClass()
+ || metaClass.getVersion() != metaClassVersion) {
- public final CallSite acceptGetProperty(Object receiver) {
- if (GroovyCategorySupport.hasCategoryInCurrentThread() || receiver.getClass() != metaClass.getTheClass()
- || version != metaClass.getVersion()) { // metaClass is invalid
return createGetPropertySite(receiver);
- } else {
- return this;
}
+ return this;
}
- public final Object getProperty(Object receiver) {
- try {
- return effective.get(receiver);
- } catch (IllegalAccessException e) {
- throw new GroovyRuntimeException("Cannot get the property '" + name + "'.", e);
- }
+ @Override
+ public final Object getProperty(final Object receiver) {
+ return effective.getProperty(receiver);
}
}
[groovy] 13/19: minor refactor
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 33e1277b81ce8cdcaf2e87e792fc72435ea96b8e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 29 12:35:30 2020 -0500
minor refactor
(cherry picked from commit 3ae9083dbbee0d6a3bcbd5683668ac77501a9a49)
---
.../codehaus/groovy/reflection/CachedField.java | 64 ++++++++--------
.../groovy/reflection/ReflectionUtils.java | 86 ++++++++++-----------
src/test/groovy/IllegalAccessScenariosTest.groovy | 41 ----------
src/test/groovy/IllegalAccessTests.groovy | 88 ++++++++++++++++++++++
.../sc/FieldsAndPropertiesStaticCompileTest.groovy | 8 +-
5 files changed, 170 insertions(+), 117 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/reflection/CachedField.java b/src/main/java/org/codehaus/groovy/reflection/CachedField.java
index c2b5dd4..6c666aa 100644
--- a/src/main/java/org/codehaus/groovy/reflection/CachedField.java
+++ b/src/main/java/org/codehaus/groovy/reflection/CachedField.java
@@ -28,34 +28,44 @@ import java.lang.reflect.Modifier;
import static org.codehaus.groovy.reflection.ReflectionUtils.makeAccessibleInPrivilegedAction;
public class CachedField extends MetaProperty {
- private final Field cachedField;
+ private final Field field;
- public CachedField(Field field) {
- super (field.getName(), field.getType());
- this.cachedField = field;
+ public CachedField(final Field field) {
+ super(field.getName(), field.getType());
+ this.field = field;
}
- public boolean isStatic() {
- return Modifier.isStatic(getModifiers());
+ public Field getCachedField() {
+ makeAccessibleIfNecessary();
+ return field;
+ }
+
+ public Class getDeclaringClass() {
+ return field.getDeclaringClass();
+ }
+
+ @Override
+ public int getModifiers() {
+ return field.getModifiers();
}
public boolean isFinal() {
return Modifier.isFinal(getModifiers());
}
- public int getModifiers() {
- return cachedField.getModifiers();
+ public boolean isStatic() {
+ return Modifier.isStatic(getModifiers());
}
/**
* @return the property of the given object
* @throws RuntimeException if the property could not be evaluated
*/
+ @Override
public Object getProperty(final Object object) {
makeAccessibleIfNecessary();
- AccessPermissionChecker.checkAccessPermission(cachedField);
try {
- return cachedField.get(object);
+ return field.get(object);
} catch (IllegalAccessException e) {
throw new GroovyRuntimeException("Cannot get the property '" + name + "'.", e);
}
@@ -68,36 +78,26 @@ public class CachedField extends MetaProperty {
* @param newValue the new value of the property
* @throws RuntimeException if the property could not be set
*/
- public void setProperty(final Object object, Object newValue) {
- makeAccessibleIfNecessary();
- AccessPermissionChecker.checkAccessPermission(cachedField);
- final Object goalValue = DefaultTypeTransformation.castToType(newValue, cachedField.getType());
-
+ @Override
+ public void setProperty(final Object object, final Object newValue) {
if (isFinal()) {
throw new GroovyRuntimeException("Cannot set the property '" + name + "' because the backing field is final.");
}
+ makeAccessibleIfNecessary();
+ Object goalValue = DefaultTypeTransformation.castToType(newValue, field.getType());
try {
- cachedField.set(object, goalValue);
- } catch (IllegalAccessException ex) {
- throw new GroovyRuntimeException("Cannot set the property '" + name + "'.", ex);
+ field.set(object, goalValue);
+ } catch (IllegalAccessException e) {
+ throw new GroovyRuntimeException("Cannot set the property '" + name + "'.", e);
}
}
- public Class getDeclaringClass() {
- return cachedField.getDeclaringClass();
- }
-
- public Field getCachedField() {
- makeAccessibleIfNecessary();
- AccessPermissionChecker.checkAccessPermission(cachedField);
- return cachedField;
- }
-
- private boolean makeAccessibleDone = false;
+ private transient boolean madeAccessible;
private void makeAccessibleIfNecessary() {
- if (!makeAccessibleDone) {
- makeAccessibleInPrivilegedAction(cachedField);
- makeAccessibleDone = true;
+ if (!madeAccessible) {
+ makeAccessibleInPrivilegedAction(field);
+ madeAccessible = true;
}
+ AccessPermissionChecker.checkAccessPermission(field);
}
}
diff --git a/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java b/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
index b9027d1..780e7a7 100644
--- a/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
+++ b/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
@@ -42,32 +42,37 @@ import java.util.function.Function;
* current class to multiple levels of depth. Calls used to handle the
* groovy MOP are excluded from the level counting.
*/
+@SuppressWarnings("rawtypes")
public class ReflectionUtils {
- // these are packages in the call stack that are only part of the groovy MOP
- private static final Set<String> IGNORED_PACKAGES = new HashSet<String>();
private static final VMPlugin VM_PLUGIN = VMPluginFactory.getPlugin();
+ /** The packages in the call stack that are only part of the Groovy MOP. */
+ private static final Set<String> IGNORED_PACKAGES;
static {
- //IGNORED_PACKAGES.add("java.lang.reflect");
- IGNORED_PACKAGES.add("groovy.lang");
- IGNORED_PACKAGES.add("org.codehaus.groovy.reflection");
- IGNORED_PACKAGES.add("org.codehaus.groovy.runtime.callsite");
- IGNORED_PACKAGES.add("org.codehaus.groovy.runtime.metaclass");
- IGNORED_PACKAGES.add("org.codehaus.groovy.runtime");
- IGNORED_PACKAGES.add("sun.reflect");
- IGNORED_PACKAGES.add("java.security");
- IGNORED_PACKAGES.add("java.lang.invoke");
- IGNORED_PACKAGES.add("org.codehaus.groovy.vmplugin.v5");
- IGNORED_PACKAGES.add("org.codehaus.groovy.vmplugin.v6");
- IGNORED_PACKAGES.add("org.codehaus.groovy.vmplugin.v7");
- IGNORED_PACKAGES.add("org.codehaus.groovy.vmplugin.v8");
- IGNORED_PACKAGES.add("org.codehaus.groovy.vmplugin.v9");
+ Set<String> set = new HashSet<>();
+
+ set.add("groovy.lang");
+ set.add("sun.reflect");
+ set.add("java.security");
+ set.add("java.lang.invoke");
+ //set.add("java.lang.reflect");
+ set.add("org.codehaus.groovy.reflection");
+ set.add("org.codehaus.groovy.runtime");
+ set.add("org.codehaus.groovy.runtime.callsite");
+ set.add("org.codehaus.groovy.runtime.metaclass");
+ set.add("org.codehaus.groovy.vmplugin.v5");
+ set.add("org.codehaus.groovy.vmplugin.v6");
+ set.add("org.codehaus.groovy.vmplugin.v7");
+ set.add("org.codehaus.groovy.vmplugin.v8");
+ set.add("org.codehaus.groovy.vmplugin.v9");
+
+ IGNORED_PACKAGES = Collections.unmodifiableSet(set);
}
private static final ClassContextHelper HELPER = new ClassContextHelper();
/**
- * Determine whether or not the getCallingClass methods will return
+ * Determines whether or not the getCallingClass methods will return
* any sensible results. On JVMs that are not Sun derived i.e.
* (gcj, Harmony) this will likely return false. When not available
* all getCallingClass methods will return null.
@@ -80,7 +85,7 @@ public class ReflectionUtils {
}
/**
- * Get the immediate calling class, ignoring MOP frames.
+ * Gets the immediate calling class, ignoring MOP frames.
*
* @return The Class of the caller
*/
@@ -89,7 +94,7 @@ public class ReflectionUtils {
}
/**
- * Get the called that is matchLevel stack frames before the call,
+ * Gets the called that is matchLevel stack frames before the call,
* ignoring MOP frames.
*
* @param matchLevel how may call stacks down to look.
@@ -97,12 +102,12 @@ public class ReflectionUtils {
* @return The Class of the matched caller, or null if there aren't
* enough stackframes to satisfy matchLevel
*/
- public static Class getCallingClass(int matchLevel) {
+ public static Class getCallingClass(final int matchLevel) {
return getCallingClass(matchLevel, Collections.emptySet());
}
/**
- * Get the called that is matchLevel stack frames before the call,
+ * Gets the called that is matchLevel stack frames before the call,
* ignoring MOP frames and desired exclude packages.
*
* @param matchLevel how may call stacks down to look.
@@ -112,32 +117,31 @@ public class ReflectionUtils {
* @return The Class of the matched caller, or null if there aren't
* enough stackframes to satisfy matchLevel
*/
- public static Class getCallingClass(int matchLevel, Collection<String> extraIgnoredPackages) {
+ public static Class getCallingClass(final int matchLevel, final Collection<String> extraIgnoredPackages) {
Class[] classContext = HELPER.getClassContext();
-
- int depth = 0;
+ int depth = 0, level = matchLevel;
try {
Class c;
do {
do {
c = classContext[depth++];
} while (classShouldBeIgnored(c, extraIgnoredPackages));
- } while (c != null && matchLevel-- > 0 && depth<classContext.length);
+ } while (c != null && level-- > 0 && depth < classContext.length);
return c;
- } catch (Throwable t) {
+ } catch (Throwable ignore) {
return null;
}
}
- public static List<Method> getDeclaredMethods(Class<?> type, String name, Class<?>... parameterTypes) {
+ public static List<Method> getDeclaredMethods(final Class<?> type, final String name, final Class<?>... parameterTypes) {
return doGetMethods(type, name, parameterTypes, Class::getDeclaredMethods);
}
- public static List<Method> getMethods(Class<?> type, String name, Class<?>... parameterTypes) {
+ public static List<Method> getMethods(final Class<?> type, final String name, final Class<?>... parameterTypes) {
return doGetMethods(type, name, parameterTypes, Class::getMethods);
}
- private static List<Method> doGetMethods(Class<?> type, String name, Class<?>[] parameterTypes, Function<? super Class<?>, ? extends Method[]> f) {
+ private static List<Method> doGetMethods(final Class<?> type, final String name, final Class<?>[] parameterTypes, final Function<? super Class<?>, ? extends Method[]> f) {
List<Method> methodList = new LinkedList<>();
out:
@@ -151,7 +155,7 @@ public class ReflectionUtils {
continue;
}
- for (int i = 0, n = methodParameterTypes.length; i < n; i++) {
+ for (int i = 0, n = methodParameterTypes.length; i < n; i += 1) {
Class<?> parameterType = TypeUtil.autoboxType(parameterTypes[i]);
if (null == parameterType) {
continue out;
@@ -169,21 +173,20 @@ public class ReflectionUtils {
return methodList;
}
- public static boolean checkCanSetAccessible(AccessibleObject accessibleObject, Class<?> caller) {
+ public static boolean checkCanSetAccessible(final AccessibleObject accessibleObject, final Class<?> caller) {
return VM_PLUGIN.checkCanSetAccessible(accessibleObject, caller);
}
- public static boolean checkAccessible(Class<?> callerClass, Class<?> declaringClass, int memberModifiers, boolean allowIllegalAccess) {
+ public static boolean checkAccessible(final Class<?> callerClass, final Class<?> declaringClass, final int memberModifiers, final boolean allowIllegalAccess) {
return VM_PLUGIN.checkAccessible(callerClass, declaringClass, memberModifiers, allowIllegalAccess);
}
- public static boolean trySetAccessible(AccessibleObject ao) {
+ public static boolean trySetAccessible(final AccessibleObject ao) {
try {
return VM_PLUGIN.trySetAccessible(ao);
- } catch (Throwable t) {
+ } catch (Throwable ignore) {
// swallow for strict security managers, module systems, android or others
}
-
return false;
}
@@ -193,9 +196,8 @@ public class ReflectionUtils {
// to be run in PrivilegedAction!
public static Optional<AccessibleObject> makeAccessible(final AccessibleObject ao) {
- AccessibleObject[] result = makeAccessible(new AccessibleObject[] { ao });
-
- return Optional.ofNullable(0 == result.length ? null : result[0]);
+ AccessibleObject[] result = makeAccessible(new AccessibleObject[] {ao});
+ return Optional.ofNullable(result.length == 0 ? null : result[0]);
}
// to be run in PrivilegedAction!
@@ -203,10 +205,10 @@ public class ReflectionUtils {
try {
AccessibleObject.setAccessible(aoa, true);
return aoa;
- } catch (Throwable outer) {
+ } catch (Throwable ignore) {
// swallow for strict security managers, module systems, android or others,
// but try one-by-one to get the allowed ones at least
- final List<AccessibleObject> ret = new ArrayList<>(aoa.length);
+ List<AccessibleObject> ret = new ArrayList<>(aoa.length);
for (final AccessibleObject ao : aoa) {
boolean accessible = trySetAccessible(ao);
if (accessible) {
@@ -217,8 +219,8 @@ public class ReflectionUtils {
}
}
- private static boolean classShouldBeIgnored(Class c, Collection<String> extraIgnoredPackages) {
- return ((c != null)
+ private static boolean classShouldBeIgnored(final Class c, final Collection<String> extraIgnoredPackages) {
+ return (c != null
&& (c.isSynthetic()
|| (c.getPackage() != null
&& (IGNORED_PACKAGES.contains(c.getPackage().getName())
diff --git a/src/test/groovy/IllegalAccessScenariosTest.groovy b/src/test/groovy/IllegalAccessScenariosTest.groovy
deleted file mode 100644
index cc1db54..0000000
--- a/src/test/groovy/IllegalAccessScenariosTest.groovy
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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
-
-import groovy.test.GroovyTestCase
-
-import static groovy.test.GroovyAssert.isAtLeastJdk
-import static org.apache.groovy.util.SystemUtil.getBooleanSafe
-
-/**
- * Tests for permissive member access. Typically such access is only allowed in Java via means such
- * as reflection.
- *
- * In JDK versions < 9, Groovy supports permissive access and no warnings are given by the JDK.
- * In JDK versions >= 9, Groovy supports permissive access but the JDK gives illegal access warnings.
- * At some point, the JDK may further restrict permissive access and Groovy's support for this feature may be limited.
- */
-class IllegalAccessScenariosTest extends GroovyTestCase {
- void testPrivateFieldAccess() {
- if (isAtLeastJdk('9.0') && !getBooleanSafe('groovy.force.illegal.access')) return
- def items = [1, 2, 3]
- // size is a private field in ArrayList
- assert items.size == 3
- }
-}
diff --git a/src/test/groovy/IllegalAccessTests.groovy b/src/test/groovy/IllegalAccessTests.groovy
new file mode 100644
index 0000000..f0d1192
--- /dev/null
+++ b/src/test/groovy/IllegalAccessTests.groovy
@@ -0,0 +1,88 @@
+/*
+ * 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
+
+import org.junit.Before
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.isAtLeastJdk
+import static org.junit.Assume.assumeTrue
+
+/**
+ * Tests for permissive member access. Typically such access is only allowed in
+ * Java via means such as reflection.
+ *
+ * In JDK versions < 9, Groovy supports permissive access and no warnings are given by the JDK.
+ * In JDK versions >= 9, Groovy supports permissive access but the JDK gives illegal access warnings.
+ * At some point, the JDK may further restrict permissive access and Groovy's support for this feature may be limited.
+ */
+final class IllegalAccessTests {
+
+ @Before
+ void setUp() {
+ assumeTrue(isAtLeastJdk('9.0') && !Boolean.getBoolean('groovy.force.illegal.access'))
+ }
+
+ @Test
+ void testReadPrivateField() {
+ assertScript '''
+ def items = [1, 2, 3]
+ assert items.size == 3 // "size" is private
+ '''
+ }
+
+ @Test
+ void testReadPackageProtectedField() {
+ // TODO: move A to another package
+ assertScript '''
+ class A {
+ @groovy.transform.PackageScope int i
+ }
+ class B extends A {
+ def eye() { super.i }
+ }
+ assert new B().eye() == 0
+ '''
+ }
+
+ @Test // GROOVY-9596
+ void testReadProtectedFieldFromSuperClass() {
+ // in is a protected field in FilterReader
+ assertScript '''
+ class MyFilterReader extends FilterReader {
+ MyFilterReader(Reader reader) {
+ super(new BufferedReader(reader))
+ }
+ String nextLine() {
+ ((BufferedReader) this.in).readLine()?.trim() // "in" is protected
+ }
+ }
+
+ def input =
+ " works \\t\\n" +
+ "hello there \\n" +
+ "hi\\n" +
+ "\\n"
+ def reader = new CharArrayReader(input.toCharArray())
+ reader = new MyFilterReader(reader)
+ assert reader.nextLine() == 'works'
+ '''
+ }
+}
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
index 3150e2b..81c5c83 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
@@ -305,7 +305,8 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
b.m()
assert b.isGetterCalled() == false
'''
- assert astTrees['B'][1].contains('GETFIELD A.x')
+ def b = astTrees['B'][1]
+ assert b.contains('GETFIELD A.x')
}
void testUseGetterFieldAccess() {
@@ -328,7 +329,10 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
b.usingGetter()
assert b.isGetterCalled() == true
'''
- assert astTrees['B'][1].contains('INVOKEVIRTUAL B.getX')
+ def b = astTrees['B'][1]
+ assert !b.contains('GETFIELD A.x')
+ assert !b.contains('GETFIELD B.x')
+ assert b.contains('INVOKEVIRTUAL B.getX')
}
void testUseAttributeExternal() {
[groovy] 15/19: GROOVY-9570: collect context generics starting at
innermost class/method
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 68ded928dde9f4aac016e456441d2f4e6f934d93
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 29 20:09:29 2020 -0500
GROOVY-9570: collect context generics starting at innermost class/method
closes #1353
(cherry picked from commit ba63acef326cd206bd709cd6e9026bb656d54ad4)
---
.../transform/stc/StaticTypeCheckingSupport.java | 12 ++++++++++-
.../transform/stc/StaticTypeCheckingVisitor.java | 4 ++--
.../stc/ClosureParamTypeInferenceSTCTest.groovy | 24 ++++++++++++++++++++++
3 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 2a1dc79..b569fc9 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1991,7 +1991,17 @@ public abstract class StaticTypeCheckingSupport {
return false;
}
- static Map<GenericsTypeName, GenericsType> extractGenericsParameterMapOfThis(final MethodNode mn) {
+ static Map<GenericsTypeName, GenericsType> extractGenericsParameterMapOfThis(final TypeCheckingContext context) {
+ ClassNode cn = context.getEnclosingClassNode();
+ MethodNode mn = context.getEnclosingMethod();
+ // GROOVY-9570: find the innermost class or method
+ if (cn != null && cn.getEnclosingMethod() == mn) {
+ return getGenericsParameterMapOfThis(cn);
+ }
+ return extractGenericsParameterMapOfThis(mn);
+ }
+
+ private static Map<GenericsTypeName, GenericsType> extractGenericsParameterMapOfThis(final MethodNode mn) {
if (mn == null) return null;
Map<GenericsTypeName, GenericsType> map;
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 4e9ae6e..f977ce1 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -5100,7 +5100,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (resolvedPlaceholders.isEmpty()) {
return boundUnboundedWildcards(returnType);
}
- Map<GenericsTypeName, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
+ Map<GenericsTypeName, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext);
applyGenericsConnections(placeholdersFromContext, resolvedPlaceholders);
// then resolve receivers from method arguments
@@ -5271,7 +5271,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
private ClassNode resolveGenericsWithContext(final Map<GenericsTypeName, GenericsType> resolvedPlaceholders, final ClassNode currentType) {
- Map<GenericsTypeName, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
+ Map<GenericsTypeName, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext);
return resolveClassNodeGenerics(resolvedPlaceholders, placeholdersFromContext, currentType);
}
diff --git a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
index 618f46f..d991a6f 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -1376,6 +1376,30 @@ method()
'''
}
+ void testGroovy9570() {
+ assertScript '''
+ interface Item {}
+
+ class C<I extends Item> {
+ Queue<I> queue
+
+ def c = { ->
+ queue.each { I item ->
+ println item
+ }
+ }
+
+ def m() {
+ queue.each { I item ->
+ println item
+ }
+ }
+ }
+
+ new C()
+ '''
+ }
+
void testGroovy9597a() {
assertScript '''
import groovy.transform.stc.*
[groovy] 07/19: minor refactor
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 1591c0231e603c0c5dcf8964e0831352f92b6038
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 22 04:34:28 2020 -0500
minor refactor
(cherry picked from commit e3a59d099a89ff6de35092c4639c6c0a7d0eb660)
---
.../groovy/transform/tailrec/VariableExpressionReplacer.groovy | 2 +-
.../codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java | 4 ++--
.../codehaus/groovy/transform/sc/TemporaryVariableExpression.java | 6 +++---
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy
index ea2d601..b56f0bd 100644
--- a/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy
+++ b/src/main/groovy/org/codehaus/groovy/transform/tailrec/VariableExpressionReplacer.groovy
@@ -139,7 +139,7 @@ class VariableExpressionReplacer extends CodeVisitorSupport {
replaceExpression(node, propName, propClass, expr, newExpr)
}
} else {
- Expression newExpr = expr.transformExpression(transformer)
+ Expression newExpr = transformer.transform(expr)
replaceExpression(node, propName, propClass, expr, newExpr)
}
}
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java
index ac30d6d..7a4182e 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java
@@ -79,7 +79,7 @@ public abstract class StaticPropertyAccessHelper {
@Override
public Expression transformExpression(final ExpressionTransformer transformer) {
- PoppingMethodCallExpression call = (PoppingMethodCallExpression) transformer.transform(this.call);
+ PoppingMethodCallExpression call = (PoppingMethodCallExpression) this.call.transformExpression(transformer);
return new PoppingListOfExpressionsExpression(call.tmp, call);
}
@@ -104,7 +104,7 @@ public abstract class StaticPropertyAccessHelper {
@Override
public Expression transformExpression(final ExpressionTransformer transformer) {
- PoppingMethodCallExpression call = new PoppingMethodCallExpression(transformer.transform(getObjectExpression()), getMethodTarget(), (TemporaryVariableExpression) transformer.transform(tmp));
+ PoppingMethodCallExpression call = new PoppingMethodCallExpression(transformer.transform(getObjectExpression()), getMethodTarget(), (TemporaryVariableExpression) tmp.transformExpression(transformer));
call.copyNodeMetaData(this);
call.setSourcePosition(this);
call.setSafe(isSafe());
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/TemporaryVariableExpression.java b/src/main/java/org/codehaus/groovy/transform/sc/TemporaryVariableExpression.java
index b93a2a9..ef41205 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/TemporaryVariableExpression.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/TemporaryVariableExpression.java
@@ -45,7 +45,7 @@ public class TemporaryVariableExpression extends Expression {
@Override
public Expression transformExpression(final ExpressionTransformer transformer) {
- TemporaryVariableExpression result = new TemporaryVariableExpression(expression.transformExpression(transformer));
+ TemporaryVariableExpression result = new TemporaryVariableExpression(transformer.transform(expression));
result.copyNodeMetaData(this);
return result;
}
@@ -53,7 +53,7 @@ public class TemporaryVariableExpression extends Expression {
@Override
public void visit(final GroovyCodeVisitor visitor) {
if (visitor instanceof AsmClassGenerator) {
- if (variable==null) {
+ if (variable == null) {
AsmClassGenerator acg = (AsmClassGenerator) visitor;
WriterController controller = acg.getController();
variable = new ExpressionAsVariableSlot(controller, expression);
@@ -64,7 +64,7 @@ public class TemporaryVariableExpression extends Expression {
}
}
- public void remove(WriterController controller) {
+ public void remove(final WriterController controller) {
controller.getCompileStack().removeVar(variable.getIndex());
variable = null;
}