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/08/09 02:35:34 UTC
[groovy] 07/07: minor refactor
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 55429fbfb37e409083fe776416c4af81aa689a8d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 8 10:50:37 2020 -0500
minor refactor
(cherry picked from commit 6eea0beb1386fe9e6bac39eda8fc27772ef48f1f)
---
.../transform/trait/SuperCallTraitTransformer.java | 6 +-
.../transform/trait/TraitASTTransformation.java | 228 ++++++++++-----------
.../traitx/TraitASTTransformationTest.groovy | 116 ++++++-----
3 files changed, 171 insertions(+), 179 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 edd1e12..e8f1c35 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
@@ -95,7 +95,7 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
ClassNode traitType = getTraitSuperTarget(leftExpression.getObjectExpression());
if (traitType != null) {
ClassNode helperType = getHelper(traitType);
- // TraitType.super.foo = ... -> TraitType$Helper.setFoo(this, ...)
+ // TraitType.super.foo = ... -> TraitType$Trait$Helper.setFoo(this, ...)
String setterName = MetaProperty.getSetterName(leftExpression.getPropertyAsString());
for (MethodNode method : helperType.getMethods(setterName)) {
@@ -136,7 +136,7 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
ClassNode traitType = getTraitSuperTarget(exp.getObjectExpression());
if (traitType != null) {
ClassNode helperType = getHelper(traitType);
- // TraitType.super.foo -> TraitType$Helper.getFoo(this)
+ // TraitType.super.foo -> TraitType$Trait$Helper.getFoo(this)
Function<MethodNode, MethodCallExpression> xform = (methodNode) -> {
MethodCallExpression methodCall = new MethodCallExpression(
@@ -181,7 +181,7 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
ClassNode traitType = getTraitSuperTarget(exp.getObjectExpression());
if (traitType != null) {
ClassNode helperType = getHelper(traitType);
- // TraitType.super.foo() -> TraitType$Helper.foo(this)
+ // TraitType.super.foo() -> TraitType$Trait$Helper.foo(this)
ArgumentListExpression newArgs = new ArgumentListExpression();
newArgs.addExpression(new VariableExpression("this"));
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
index 2daeae2..da8cf12 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
@@ -32,13 +32,8 @@ import org.codehaus.groovy.ast.InnerClassNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.PropertyNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.BinaryExpression;
-import org.codehaus.groovy.ast.expr.CastExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.FieldExpression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
@@ -53,13 +48,10 @@ import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.syntax.SyntaxException;
-import org.codehaus.groovy.syntax.Token;
-import org.codehaus.groovy.syntax.Types;
import org.codehaus.groovy.transform.ASTTransformationCollectorCodeVisitor;
import org.codehaus.groovy.transform.AbstractASTTransformation;
import org.codehaus.groovy.transform.GroovyASTTransformation;
-import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@@ -70,7 +62,19 @@ import java.util.Set;
import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated;
import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
+import static org.apache.groovy.util.BeanUtils.capitalize;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
import static org.codehaus.groovy.transform.trait.SuperCallTraitTransformer.UNRESOLVED_HELPER_CLASS;
/**
@@ -85,21 +89,26 @@ import static org.codehaus.groovy.transform.trait.SuperCallTraitTransformer.UNRE
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
public class TraitASTTransformation extends AbstractASTTransformation implements CompilationUnitAware {
- public static final String DO_DYNAMIC = TraitReceiverTransformer.class+".doDynamic";
- public static final String POST_TYPECHECKING_REPLACEMENT = TraitReceiverTransformer.class+".replacement";
+ public static final String DO_DYNAMIC = TraitReceiverTransformer.class + ".doDynamic";
+ public static final String POST_TYPECHECKING_REPLACEMENT = TraitReceiverTransformer.class + ".replacement";
private static final ClassNode INVOKERHELPER_CLASSNODE = ClassHelper.make(InvokerHelper.class);
-
private static final ClassNode OVERRIDE_CLASSNODE = ClassHelper.make(Override.class);
- private SourceUnit unit;
+ private SourceUnit sourceUnit;
private CompilationUnit compilationUnit;
- public void visit(ASTNode[] nodes, SourceUnit source) {
+ @Override
+ public void setCompilationUnit(final CompilationUnit unit) {
+ this.compilationUnit = unit;
+ }
+
+ @Override
+ public void visit(final ASTNode[] nodes, final SourceUnit source) {
AnnotatedNode parent = (AnnotatedNode) nodes[1];
AnnotationNode anno = (AnnotationNode) nodes[0];
if (!Traits.TRAIT_CLASSNODE.equals(anno.getClassNode())) return;
- unit = source;
+ sourceUnit = source;
init(nodes, source);
if (parent instanceof ClassNode) {
ClassNode cNode = (ClassNode) parent;
@@ -117,7 +126,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
if (helperClassNode == null) {
return;
}
- for (ClassNode cNode : unit.getAST().getClasses()) {
+ for (ClassNode cNode : sourceUnit.getAST().getClasses()) {
ClassNode unresolvedHelperNode = cNode.getNodeMetaData(UNRESOLVED_HELPER_CLASS);
if (unresolvedHelperNode != null
&& unresolvedHelperNode.getName().equals(helperClassNode.getName())) {
@@ -151,14 +160,13 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
private void resolveScope(final ClassNode cNode) {
// we need to resolve again!
- VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(unit);
+ VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(sourceUnit);
scopeVisitor.visitClass(cNode);
}
private void checkNoConstructor(final ClassNode cNode) {
if (!cNode.getDeclaredConstructors().isEmpty()) {
- addError("Error processing trait '" + cNode.getName() + "'. " +
- " Constructors are not allowed.", cNode);
+ addError("Error processing trait '" + cNode.getName() + "'. " + " Constructors are not allowed.", cNode);
}
}
@@ -182,8 +190,8 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
generatePropertyMethods(cNode);
// prepare fields
- List<FieldNode> fields = new ArrayList<FieldNode>();
- Set<String> fieldNames = new HashSet<String>();
+ List<FieldNode> fields = new ArrayList<>();
+ Set<String> fieldNames = new HashSet<>();
boolean hasStatic = false;
for (FieldNode field : cNode.getFields()) {
if (!"metaClass".equals(field.getName()) && (!field.isSynthetic() || field.getName().indexOf('$') < 0)) {
@@ -200,28 +208,28 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
fieldHelper = new InnerClassNode(
cNode,
Traits.fieldHelperClassName(cNode),
- ACC_STATIC | ACC_PUBLIC | ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC,
+ ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_SYNTHETIC,
ClassHelper.OBJECT_TYPE
);
if (hasStatic) {
staticFieldHelper = new InnerClassNode(
cNode,
Traits.staticFieldHelperClassName(cNode),
- ACC_STATIC | ACC_PUBLIC | ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC,
+ ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_SYNTHETIC,
ClassHelper.OBJECT_TYPE
);
}
}
// add methods
- List<MethodNode> methods = new ArrayList<MethodNode>(cNode.getMethods());
- List<MethodNode> nonPublicAPIMethods = new LinkedList<MethodNode>();
+ List<MethodNode> methods = new ArrayList<>(cNode.getMethods());
+ List<MethodNode> nonPublicAPIMethods = new LinkedList<>();
List<Statement> staticInitStatements = null;
for (final MethodNode methodNode : methods) {
boolean declared = methodNode.getDeclaringClass() == cNode;
if (declared) {
if (!methodNode.isSynthetic() && (methodNode.isProtected() || (!methodNode.isPrivate() && !methodNode.isPublic()))) {
- unit.addError(new SyntaxException("Cannot have protected/package-private method in a trait (" + cNode.getName() + "#" + methodNode.getTypeDescriptor() + ")",
+ sourceUnit.addError(new SyntaxException("Cannot have protected/package-private method in a trait (" + cNode.getName() + "#" + methodNode.getTypeDescriptor() + ")",
methodNode.getLineNumber(), methodNode.getColumnNumber()));
return null;
}
@@ -262,7 +270,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
BlockStatement toBlock = getBlockStatement(initializer, toCode);
for (Statement next : initStatements) {
Parameter selfParam = createSelfParameter(cNode, false);
- toBlock.addStatement(processBody(new VariableExpression(selfParam), next, cNode, helper, fieldHelper, fieldNames));
+ toBlock.addStatement(processBody(varX(selfParam), next, cNode, helper, fieldHelper, fieldNames));
}
initStatements.clear();
@@ -273,7 +281,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
copyClassAnnotations(cNode, helper);
markAsGenerated(cNode, helper);
- fields = new ArrayList<FieldNode>(cNode.getFields()); // reuse the full list of fields
+ fields = new ArrayList<>(cNode.getFields()); // reuse the full list of fields
for (FieldNode field : fields) {
cNode.removeField(field.getName());
}
@@ -281,11 +289,11 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
// visit AST xforms
registerASTTransformations(helper);
- unit.getAST().addClass(helper);
+ sourceUnit.getAST().addClass(helper);
if (fieldHelper != null) {
- unit.getAST().addClass(fieldHelper);
+ sourceUnit.getAST().addClass(fieldHelper);
if (staticFieldHelper != null) {
- unit.getAST().addClass(staticFieldHelper);
+ sourceUnit.getAST().addClass(staticFieldHelper);
}
}
@@ -300,22 +308,21 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
return helper;
}
- private BlockStatement getBlockStatement(MethodNode targetMethod, Statement code) {
- BlockStatement toBlock;
+ private BlockStatement getBlockStatement(final MethodNode targetMethod, final Statement code) {
+ BlockStatement blockStmt;
if (code instanceof BlockStatement) {
- toBlock = (BlockStatement) code;
+ blockStmt = (BlockStatement) code;
} else {
- toBlock = new BlockStatement();
- toBlock.addStatement(code);
- targetMethod.setCode(toBlock);
+ blockStmt = block(code);
+ targetMethod.setCode(blockStmt);
}
- return toBlock;
+ return blockStmt;
}
private static MethodNode createInitMethod(final boolean isStatic, final ClassNode cNode, final ClassNode helper) {
MethodNode initializer = new MethodNode(
- isStatic?Traits.STATIC_INIT_METHOD:Traits.INIT_METHOD,
- ACC_STATIC | ACC_PUBLIC | ACC_SYNTHETIC,
+ isStatic ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD,
+ ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC,
ClassHelper.VOID_TYPE,
new Parameter[]{createSelfParameter(cNode, isStatic)},
ClassNode.EMPTY_ARRAY,
@@ -333,7 +340,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
private void registerASTTransformations(final ClassNode helper) {
{
- GroovyClassVisitor visitor = new ASTTransformationCollectorCodeVisitor(unit, compilationUnit.getTransformLoader());
+ GroovyClassVisitor visitor = new ASTTransformationCollectorCodeVisitor(sourceUnit, compilationUnit.getTransformLoader());
visitor.visitClass(helper);
}
// Perform an additional phase which has to be done *after* type checking
@@ -346,7 +353,8 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
}
/**
- * Copies annotation from the trait to the helper, excluding the trait annotation itself
+ * Copies annotation from the trait to the helper, excluding the trait annotation itself.
+ *
* @param cNode the trait class node
* @param helper the helper class node
*/
@@ -360,11 +368,10 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
}
private void checkInnerClasses(final ClassNode cNode) {
- Iterator<InnerClassNode> it = cNode.getInnerClasses();
- while (it.hasNext()) {
+ for (Iterator<InnerClassNode> it = cNode.getInnerClasses(); it.hasNext(); ) {
InnerClassNode origin = it.next();
if ((origin.getModifiers() & ACC_STATIC) == 0) {
- unit.addError(new SyntaxException("Cannot have non-static inner class inside a trait ("+origin.getName()+")", origin.getLineNumber(), origin.getColumnNumber()));
+ sourceUnit.addError(new SyntaxException("Cannot have non-static inner class inside a trait ("+origin.getName()+")", origin.getLineNumber(), origin.getColumnNumber()));
}
}
}
@@ -376,87 +383,65 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
}
/**
- * Mostly copied from the {@link Verifier} class but does *not* generate bytecode
- *
- * @param cNode
- * @param node
+ * Mostly copied from the {@link Verifier} class but does *not* generate bytecode.
*/
- private static void processProperty(final ClassNode cNode, PropertyNode node) {
+ private static void processProperty(final ClassNode cNode, final PropertyNode node) {
String name = node.getName();
FieldNode field = node.getField();
- int propNodeModifiers = node.getModifiers();
-
- String getterName = "get" + Verifier.capitalize(name);
- String setterName = "set" + Verifier.capitalize(name);
+ int propNodeModifiers = node.getModifiers() & 0x1F; // GROOVY-3726
- // GROOVY-3726: clear volatile, transient modifiers so that they don't get applied to methods
- if ((propNodeModifiers & Modifier.VOLATILE) != 0) {
- propNodeModifiers = propNodeModifiers - Modifier.VOLATILE;
- }
- if ((propNodeModifiers & Modifier.TRANSIENT) != 0) {
- propNodeModifiers = propNodeModifiers - Modifier.TRANSIENT;
- }
+ String getterName = GeneralUtils.getGetterName(node);
+ String setterName = GeneralUtils.getSetterName(name);
Statement getterBlock = node.getGetterBlock();
if (getterBlock == null) {
MethodNode getter = cNode.getGetterMethod(getterName);
- if (getter == null && ClassHelper.boolean_TYPE == node.getType()) {
- String secondGetterName = "is" + Verifier.capitalize(name);
- getter = cNode.getGetterMethod(secondGetterName);
+ if (getter == null && node.getType().equals(ClassHelper.boolean_TYPE)) {
+ getter = cNode.getGetterMethod("is" + capitalize(name));
}
if (!node.isPrivate() && methodNeedsReplacement(cNode, getter)) {
- getterBlock = new ExpressionStatement(new FieldExpression(field));
+ getterBlock = stmt(fieldX(field));
}
}
Statement setterBlock = node.getSetterBlock();
if (setterBlock == null) {
// 2nd arg false below: though not usual, allow setter with non-void return type
MethodNode setter = cNode.getSetterMethod(setterName, false);
- if (!node.isPrivate() &&
- (propNodeModifiers & ACC_FINAL) == 0 &&
- methodNeedsReplacement(cNode, setter)) {
- setterBlock = new ExpressionStatement(
- new BinaryExpression(
- new FieldExpression(field),
- Token.newSymbol(Types.EQUAL, 0, 0),
- new VariableExpression("value")
- )
- );
+ if (!node.isPrivate() && (propNodeModifiers & ACC_FINAL) == 0
+ && methodNeedsReplacement(cNode, setter)) {
+ setterBlock = assignS(fieldX(field), varX(name));
}
}
if (getterBlock != null) {
- MethodNode getter =
- new MethodNode(getterName, propNodeModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
+ MethodNode getter = new MethodNode(getterName, propNodeModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
getter.setSynthetic(true);
cNode.addMethod(getter);
- if (ClassHelper.boolean_TYPE == node.getType() || ClassHelper.Boolean_TYPE == node.getType()) {
- String secondGetterName = "is" + Verifier.capitalize(name);
- MethodNode secondGetter =
- new MethodNode(secondGetterName, propNodeModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
+ if (node.getType().equals(ClassHelper.boolean_TYPE) || node.getType().equals(ClassHelper.Boolean_TYPE)) {
+ MethodNode secondGetter = new MethodNode("is" + capitalize(name), propNodeModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
secondGetter.setSynthetic(true);
cNode.addMethod(secondGetter);
}
}
if (setterBlock != null) {
- Parameter[] setterParameterTypes = {new Parameter(node.getType(), "value")};
VariableExpression var = (VariableExpression) ((BinaryExpression) ((ExpressionStatement) setterBlock).getExpression()).getRightExpression();
- var.setAccessedVariable(setterParameterTypes[0]);
- MethodNode setter =
- new MethodNode(setterName, propNodeModifiers, ClassHelper.VOID_TYPE, setterParameterTypes, ClassNode.EMPTY_ARRAY, setterBlock);
+ Parameter setterParameter = new Parameter(node.getType(), name);
+ var.setAccessedVariable(setterParameter);
+
+ MethodNode setter = new MethodNode(setterName, propNodeModifiers, ClassHelper.VOID_TYPE, params(setterParameter), ClassNode.EMPTY_ARRAY, setterBlock);
setter.setSynthetic(true);
cNode.addMethod(setter);
}
}
- private static boolean methodNeedsReplacement(ClassNode classNode, MethodNode m) {
+ private static boolean methodNeedsReplacement(final ClassNode cNode, final MethodNode mNode) {
// no method found, we need to replace
- if (m == null) return true;
+ if (mNode == null) return true;
// method is in current class, nothing to be done
- if (m.getDeclaringClass() == classNode) return false;
+ if (mNode.getDeclaringClass() == cNode) return false;
// do not overwrite final
- if ((m.getModifiers() & ACC_FINAL) != 0) return false;
+ if ((mNode.getModifiers() & ACC_FINAL) != 0) return false;
return true;
}
@@ -464,23 +449,23 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
final ClassNode fieldHelper, final ClassNode helper, final ClassNode staticFieldHelper, final ClassNode trait,
final Set<String> knownFields) {
if (field.isProtected()) {
- unit.addError(new SyntaxException("Cannot have protected field in a trait (" + trait.getName() + "#" + field.getName() + ")",
+ sourceUnit.addError(new SyntaxException("Cannot have protected field in a trait (" + trait.getName() + "#" + field.getName() + ")",
field.getLineNumber(), field.getColumnNumber()));
return;
}
Expression initialExpression = field.getInitialExpression();
- MethodNode selectedMethod = field.isStatic()?staticInitializer:initializer;
+ MethodNode selectedMethod = field.isStatic() ? staticInitializer : initializer;
ClassNode target = field.isStatic() && staticFieldHelper != null ? staticFieldHelper : fieldHelper;
if (initialExpression != null) {
- VariableExpression thisObject = new VariableExpression(selectedMethod.getParameters()[0]);
+ VariableExpression thisObject = varX(selectedMethod.getParameters()[0]);
ExpressionStatement initCode = new ExpressionStatement(initialExpression);
processBody(thisObject, initCode, trait, helper, fieldHelper, knownFields);
if (field.isFinal()) {
String baseName = field.isStatic() ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD;
MethodNode fieldInitializer = new MethodNode(
baseName + Traits.remappedFieldName(trait, field.getName()),
- ACC_STATIC | ACC_PUBLIC | ACC_SYNTHETIC,
+ ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC,
field.getOriginType(),
new Parameter[]{createSelfParameter(trait, field.isStatic())},
ClassNode.EMPTY_ARRAY,
@@ -494,25 +479,25 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
if (staticFieldHelper != null) {
target = staticFieldHelper;
}
- mce = new MethodCallExpression(
- new ClassExpression(INVOKERHELPER_CLASSNODE),
+ mce = callX(
+ classX(INVOKERHELPER_CLASSNODE),
"invokeStaticMethod",
- new ArgumentListExpression(
+ args(
thisObject,
- new ConstantExpression(Traits.helperSetterName(field)),
+ constX(Traits.helperSetterName(field)),
initCode.getExpression()
)
);
} else {
- mce = new MethodCallExpression(
- new CastExpression(createReceiverType(field.isStatic(), fieldHelper), thisObject),
+ mce = callX(
+ castX(createReceiverType(field.isStatic(), fieldHelper), thisObject),
Traits.helperSetterName(field),
- new CastExpression(field.getOriginType(),initCode.getExpression())
+ castX(field.getOriginType(), initCode.getExpression())
);
}
mce.setImplicitThis(false);
mce.setSourcePosition(initialExpression);
- code.addStatement(new ExpressionStatement(mce));
+ code.addStatement(stmt(mce));
}
}
// define setter/getter helper methods (setter added even for final fields for legacy compatibility)
@@ -539,38 +524,38 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
String dummyFieldName = String.format("$0x%04x", mods) + Traits.remappedFieldName(field.getOwner(), field.getName());
FieldNode dummyField = new FieldNode(
dummyFieldName,
- ACC_STATIC | ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
+ ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC,
field.getOriginType(),
fieldHelper,
null
);
// copy annotations from field to dummy field
- List<AnnotationNode> copied = new LinkedList<AnnotationNode>();
- List<AnnotationNode> notCopied = new LinkedList<AnnotationNode>();
+ List<AnnotationNode> copied = new LinkedList<>();
+ List<AnnotationNode> notCopied = new LinkedList<>();
GeneralUtils.copyAnnotatedNodeAnnotations(field, copied, notCopied);
dummyField.addAnnotations(copied);
fieldHelper.addField(dummyField);
// retain legacy field (will be given lower precedence than above)
dummyFieldName = (field.isStatic() ? Traits.STATIC_FIELD_PREFIX : Traits.FIELD_PREFIX) +
- (field.isPublic()? Traits.PUBLIC_FIELD_PREFIX : Traits.PRIVATE_FIELD_PREFIX)+
+ (field.isPublic() ? Traits.PUBLIC_FIELD_PREFIX : Traits.PRIVATE_FIELD_PREFIX) +
Traits.remappedFieldName(field.getOwner(), field.getName());
dummyField = new FieldNode(
dummyFieldName,
- ACC_STATIC | ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
+ ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC,
field.getOriginType(),
fieldHelper,
null
);
// copy annotations from field to legacy dummy field
- copied = new LinkedList<AnnotationNode>();
- notCopied = new LinkedList<AnnotationNode>();
+ copied = new LinkedList<>();
+ notCopied = new LinkedList<>();
GeneralUtils.copyAnnotatedNodeAnnotations(field, copied, notCopied);
dummyField.addAnnotations(copied);
fieldHelper.addField(dummyField);
}
- private MethodNode processMethod(ClassNode traitClass, ClassNode traitHelperClass, MethodNode methodNode, ClassNode fieldHelper, Collection<String> knownFields) {
+ private MethodNode processMethod(final ClassNode traitClass, final ClassNode traitHelperClass, final MethodNode methodNode, final ClassNode fieldHelper, final Collection<String> knownFields) {
Parameter[] initialParams = methodNode.getParameters();
Parameter[] newParams = new Parameter[initialParams.length + 1];
newParams[0] = createSelfParameter(traitClass, methodNode.isStatic());
@@ -582,7 +567,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
methodNode.getReturnType(),
newParams,
methodNode.getExceptions(),
- processBody(new VariableExpression(newParams[0]), methodNode.getCode(), traitClass, traitHelperClass, fieldHelper, knownFields)
+ processBody(varX(newParams[0]), methodNode.getCode(), traitClass, traitHelperClass, fieldHelper, knownFields)
);
mNode.setSourcePosition(methodNode);
mNode.addAnnotations(filterAnnotations(methodNode.getAnnotations()));
@@ -600,8 +585,8 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
return mNode;
}
- private static List<AnnotationNode> filterAnnotations(List<AnnotationNode> annotations) {
- List<AnnotationNode> result = new ArrayList<AnnotationNode>(annotations.size());
+ private static List<AnnotationNode> filterAnnotations(final List<AnnotationNode> annotations) {
+ List<AnnotationNode> result = new ArrayList<>(annotations.size());
for (AnnotationNode annotation : annotations) {
if (!OVERRIDE_CLASSNODE.equals(annotation.getClassNode())) {
result.add(annotation);
@@ -614,7 +599,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
private static Parameter createSelfParameter(final ClassNode traitClass, boolean isStatic) {
final ClassNode rawType = traitClass.getPlainNodeReference();
ClassNode type = createReceiverType(isStatic, rawType);
- return new Parameter(type, isStatic?Traits.STATIC_THIS_OBJECT:Traits.THIS_OBJECT);
+ return new Parameter(type, isStatic ? Traits.STATIC_THIS_OBJECT : Traits.THIS_OBJECT);
}
private static ClassNode createReceiverType(final boolean isStatic, final ClassNode rawType) {
@@ -632,20 +617,18 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
return type;
}
- private Statement processBody(VariableExpression thisObject, Statement code, ClassNode trait, ClassNode traitHelper, ClassNode fieldHelper, Collection<String> knownFields) {
+ private Statement processBody(final VariableExpression thisObject, final Statement code, final ClassNode trait, final ClassNode traitHelper, final ClassNode fieldHelper, final Collection<String> knownFields) {
if (code == null) return null;
- NAryOperationRewriter operationRewriter = new NAryOperationRewriter(unit, knownFields);
+ NAryOperationRewriter operationRewriter = new NAryOperationRewriter(sourceUnit, knownFields);
code.visit(operationRewriter);
- SuperCallTraitTransformer superTrn = new SuperCallTraitTransformer(unit);
+ SuperCallTraitTransformer superTrn = new SuperCallTraitTransformer(sourceUnit);
code.visit(superTrn);
- TraitReceiverTransformer trn = new TraitReceiverTransformer(thisObject, unit, trait, traitHelper, fieldHelper, knownFields);
+ TraitReceiverTransformer trn = new TraitReceiverTransformer(thisObject, sourceUnit, trait, traitHelper, fieldHelper, knownFields);
code.visit(trn);
return code;
}
- public void setCompilationUnit(final CompilationUnit unit) {
- this.compilationUnit = unit;
- }
+ //--------------------------------------------------------------------------
private static class DefaultArgsMethodsAdder extends Verifier {
@@ -659,7 +642,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
private static class PostTypeCheckingExpressionReplacer extends ClassCodeExpressionTransformer {
private final SourceUnit sourceUnit;
- private PostTypeCheckingExpressionReplacer(final SourceUnit sourceUnit) {
+ PostTypeCheckingExpressionReplacer(final SourceUnit sourceUnit) {
this.sourceUnit = sourceUnit;
}
@@ -671,13 +654,12 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
@Override
public Expression transform(final Expression exp) {
if (exp != null) {
- Expression replacement = exp.getNodeMetaData(TraitASTTransformation.POST_TYPECHECKING_REPLACEMENT);
- if (replacement!=null) {
+ Expression replacement = exp.getNodeMetaData(POST_TYPECHECKING_REPLACEMENT);
+ if (replacement != null) {
return replacement;
}
}
return super.transform(exp);
}
}
-
}
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index dfd956a..45a91b1 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -1019,48 +1019,48 @@ final class TraitASTTransformationTest {
void testTraitSuperPropertyGet() {
assertScript '''
trait T {
- def x = 'value'
+ def x = 'value'
}
class C implements T {
- def test() {
- T.super.x
- }
+ def test() {
+ T.super.x
+ }
}
assert new C().test() == 'value'
'''
assertScript '''
trait T {
- boolean x = true
+ boolean x = true
}
class C implements T {
- def test() {
- T.super.x
- }
+ def test() {
+ T.super.x
+ }
}
assert new C().test() == true
'''
assertScript '''
trait T {
- def getX() { 'value' }
+ def getX() { 'value' }
}
class C implements T {
- def test() {
- T.super.x
- }
+ def test() {
+ T.super.x
+ }
}
assert new C().test() == 'value'
'''
assertScript '''
trait T {
- boolean isX() { true }
+ boolean isX() { true }
}
class C implements T {
- def test() {
- T.super.x
- }
+ def test() {
+ T.super.x
+ }
}
assert new C().test() == true
'''
@@ -1070,40 +1070,54 @@ final class TraitASTTransformationTest {
void testTraitSuperPropertySet() {
assertScript '''
trait T {
- def x
+ def x
}
class C implements T {
- def test() {
- T.super.x = 'value'
- return x
- }
+ def test() {
+ T.super.x = 'value'
+ return x
+ }
+ }
+ assert new C().test() == 'value'
+ '''
+
+ def err = shouldFail '''
+ trait T {
+ 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/
// TODO: add support for compound assignment
shouldFail MissingPropertyException, '''
trait T {
- def x = 'value'
+ def x = 'value'
}
class C implements T {
- def test() {
- T.super.x -= ~/e\b/
- T.super.x += 'able'
- return x
- }
+ def test() {
+ T.super.x -= ~/e\b/
+ T.super.x += 'able'
+ return x
+ }
}
assert new C().test() == 'valuable'
'''
assertScript '''
trait T {
- def setX(value) { 'retval' }
+ def setX(value) { 'retval' }
}
class C implements T {
- def test() {
- T.super.x = 'value'
- }
+ def test() {
+ T.super.x = 'value'
+ }
}
assert new C().test() == 'retval'
'''
@@ -1113,39 +1127,35 @@ final class TraitASTTransformationTest {
void testTraitSuperPropertySetWithOverloads() {
assertScript '''
trait T {
- def setX(Number n) {
- 'Number'
- }
- def setX(String s) {
- 'String'
- }
+ def setX(Number n) {
+ 'Number'
+ }
+ def setX(String s) {
+ 'String'
+ }
}
-
class C implements T {
- def test() {
- T.super.x = 42
- }
+ def test() {
+ T.super.x = 42
+ }
}
-
assert new C().test() == 'Number'
'''
assertScript '''
trait T {
- def setX(Number n) {
- 'Number'
- }
- def setX(String s) {
- 'String'
- }
+ def setX(Number n) {
+ 'Number'
+ }
+ def setX(String s) {
+ 'String'
+ }
}
-
class C implements T {
- def test() {
- T.super.x = 'x'
- }
+ def test() {
+ T.super.x = 'x'
+ }
}
-
assert new C().test() == 'String'
'''
}