use of org.codehaus.groovy.ast.expr.FieldExpression in project grails-core by grails.
the class TestMixinTransformation method weaveMixinIntoClass.
protected void weaveMixinIntoClass(final ClassNode classNode, final ClassNode mixinClassNode, final Junit3TestFixtureMethodHandler junit3MethodHandler, ClassNode applicationClassNode) {
if (mixinClassNode.getName().equals(IntegrationTestMixin.class.getName())) {
new IntegrationTestMixinTransformation().weaveIntegrationTestMixin(classNode, applicationClassNode);
return;
}
final String fieldName = '$' + GrailsNameUtils.getPropertyName(mixinClassNode.getName());
boolean implementsTestRuntimeAwareMixin = GrailsASTUtils.findInterface(mixinClassNode, ClassHelper.make(TestRuntimeAwareMixin.class)) != null;
FieldNode mixinFieldNode;
if (!implementsTestRuntimeAwareMixin) {
mixinFieldNode = addLegacyMixinFieldIfNonExistent(classNode, mixinClassNode, fieldName);
} else {
mixinFieldNode = addTestRuntimeAwareMixinFieldIfNonExistent(classNode, mixinClassNode, fieldName);
}
// already woven
if (mixinFieldNode == null)
return;
FieldExpression fieldReference = new FieldExpression(mixinFieldNode);
ClassNode currentMixinClassNode = mixinClassNode;
while (!currentMixinClassNode.getName().equals(GrailsASTUtils.OBJECT_CLASS)) {
final List<MethodNode> mixinMethods = currentMixinClassNode.getMethods();
for (MethodNode mixinMethod : mixinMethods) {
if (!isCandidateMethod(mixinMethod) || hasDeclaredMethod(classNode, mixinMethod)) {
continue;
}
MethodNode methodNode;
if (mixinMethod.isStatic()) {
methodNode = GrailsASTUtils.addDelegateStaticMethod(classNode, mixinMethod);
} else {
methodNode = GrailsASTUtils.addDelegateInstanceMethod(classNode, fieldReference, mixinMethod, false);
}
if (methodNode != null) {
methodNode.addAnnotation(MIXIN_METHOD_ANNOTATION);
GrailsASTUtils.addCompileStaticAnnotation(methodNode);
}
if (junit3MethodHandler != null) {
junit3MethodHandler.handle(mixinMethod, methodNode);
}
}
currentMixinClassNode = currentMixinClassNode.getSuperClass();
if (junit3MethodHandler != null) {
junit3MethodHandler.mixinSuperClassChanged();
}
}
}
use of org.codehaus.groovy.ast.expr.FieldExpression in project groovy-core by groovy.
the class ClosureWriter method createClosureClass.
protected ClassNode createClosureClass(ClosureExpression expression, int mods) {
ClassNode classNode = controller.getClassNode();
ClassNode outerClass = controller.getOutermostClass();
MethodNode methodNode = controller.getMethodNode();
String name = classNode.getName() + "$" + // add a more informative name
controller.getContext().getNextClosureInnerName(outerClass, classNode, methodNode);
boolean staticMethodOrInStaticClass = controller.isStaticMethod() || classNode.isStaticClass();
Parameter[] parameters = expression.getParameters();
if (parameters == null) {
parameters = Parameter.EMPTY_ARRAY;
} else if (parameters.length == 0) {
// let's create a default 'it' parameter
Parameter it = new Parameter(ClassHelper.OBJECT_TYPE, "it", ConstantExpression.NULL);
parameters = new Parameter[] { it };
Variable ref = expression.getVariableScope().getDeclaredVariable("it");
if (ref != null)
it.setClosureSharedVariable(ref.isClosureSharedVariable());
}
Parameter[] localVariableParams = getClosureSharedVariables(expression);
removeInitialValues(localVariableParams);
InnerClassNode answer = new InnerClassNode(classNode, name, mods, ClassHelper.CLOSURE_TYPE.getPlainNodeReference());
answer.setEnclosingMethod(controller.getMethodNode());
answer.setSynthetic(true);
answer.setUsingGenerics(outerClass.isUsingGenerics());
answer.setSourcePosition(expression);
if (staticMethodOrInStaticClass) {
answer.setStaticClass(true);
}
if (controller.isInScriptBody()) {
answer.setScriptBody(true);
}
MethodNode method = answer.addMethod("doCall", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, expression.getCode());
method.setSourcePosition(expression);
VariableScope varScope = expression.getVariableScope();
if (varScope == null) {
throw new RuntimeException("Must have a VariableScope by now! for expression: " + expression + " class: " + name);
} else {
method.setVariableScope(varScope.copy());
}
if (parameters.length > 1 || (parameters.length == 1 && parameters[0].getType() != null && parameters[0].getType() != ClassHelper.OBJECT_TYPE && !ClassHelper.OBJECT_TYPE.equals(parameters[0].getType().getComponentType()))) {
// let's add a typesafe call method
MethodNode call = answer.addMethod("call", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, new ReturnStatement(new MethodCallExpression(VariableExpression.THIS_EXPRESSION, "doCall", new ArgumentListExpression(parameters))));
call.setSourcePosition(expression);
}
// let's make the constructor
BlockStatement block = new BlockStatement();
// this block does not get a source position, because we don't
// want this synthetic constructor to show up in corbertura reports
VariableExpression outer = new VariableExpression("_outerInstance");
outer.setSourcePosition(expression);
block.getVariableScope().putReferencedLocalVariable(outer);
VariableExpression thisObject = new VariableExpression("_thisObject");
thisObject.setSourcePosition(expression);
block.getVariableScope().putReferencedLocalVariable(thisObject);
TupleExpression conArgs = new TupleExpression(outer, thisObject);
block.addStatement(new ExpressionStatement(new ConstructorCallExpression(ClassNode.SUPER, conArgs)));
// let's assign all the parameter fields from the outer context
for (Parameter param : localVariableParams) {
String paramName = param.getName();
ClassNode type = param.getType();
if (true) {
VariableExpression initialValue = new VariableExpression(paramName);
initialValue.setAccessedVariable(param);
initialValue.setUseReferenceDirectly(true);
ClassNode realType = type;
type = ClassHelper.makeReference();
param.setType(ClassHelper.makeReference());
FieldNode paramField = answer.addField(paramName, ACC_PRIVATE | ACC_SYNTHETIC, type, initialValue);
paramField.setOriginType(ClassHelper.getWrapper(param.getOriginType()));
paramField.setHolder(true);
String methodName = Verifier.capitalize(paramName);
// let's add a getter & setter
Expression fieldExp = new FieldExpression(paramField);
answer.addMethod("get" + methodName, ACC_PUBLIC, realType.getPlainNodeReference(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new ReturnStatement(fieldExp));
}
}
Parameter[] params = new Parameter[2 + localVariableParams.length];
params[0] = new Parameter(ClassHelper.OBJECT_TYPE, "_outerInstance");
params[1] = new Parameter(ClassHelper.OBJECT_TYPE, "_thisObject");
System.arraycopy(localVariableParams, 0, params, 2, localVariableParams.length);
ASTNode sn = answer.addConstructor(ACC_PUBLIC, params, ClassNode.EMPTY_ARRAY, block);
sn.setSourcePosition(expression);
correctAccessedVariable(answer, expression);
return answer;
}
use of org.codehaus.groovy.ast.expr.FieldExpression in project groovy-core by groovy.
the class ClosureWriter method loadReference.
public static void loadReference(String name, WriterController controller) {
CompileStack compileStack = controller.getCompileStack();
MethodVisitor mv = controller.getMethodVisitor();
ClassNode classNode = controller.getClassNode();
AsmClassGenerator acg = controller.getAcg();
// an already declared variable.
if (!compileStack.containsVariable(name) && compileStack.getScope().isReferencedClassVariable(name)) {
acg.visitFieldExpression(new FieldExpression(classNode.getDeclaredField(name)));
} else {
BytecodeVariable v = compileStack.getVariable(name, !classNodeUsesReferences(controller.getClassNode()));
if (v == null) {
// variable is not on stack because we are
// inside a nested Closure and this variable
// was not used before
// then load it from the Closure field
FieldNode field = classNode.getDeclaredField(name);
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, controller.getInternalClassName(), name, BytecodeHelper.getTypeDescription(field.getType()));
} else {
mv.visitVarInsn(ALOAD, v.getIndex());
}
controller.getOperandStack().push(ClassHelper.REFERENCE_TYPE);
}
}
use of org.codehaus.groovy.ast.expr.FieldExpression in project groovy-core by groovy.
the class Verifier method moveOptimizedConstantsInitialization.
private boolean moveOptimizedConstantsInitialization(final ClassNode node) {
if (node.isInterface() && !Traits.isTrait(node))
return false;
final int mods = Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_PUBLIC;
String name = SWAP_INIT;
BlockStatement methodCode = new BlockStatement();
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);
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));
fn.setInitialValueExpression(null);
methodCode.addStatement(statement);
swapInitRequired = true;
}
if (swapInitRequired) {
node.addSyntheticMethod(name, mods, ClassHelper.VOID_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, methodCode);
}
return swapInitRequired;
}
use of org.codehaus.groovy.ast.expr.FieldExpression in project groovy-core by groovy.
the class BinaryExpressionHelper method execMethodAndStoreForSubscriptOperator.
private void execMethodAndStoreForSubscriptOperator(int op, String method, Expression expression, VariableSlotLoader usesSubscript, Expression orig) {
final OperandStack operandStack = controller.getOperandStack();
writePostOrPrefixMethod(op, method, expression, orig);
// we need special code for arrays to store the result (like for a[1]++)
if (usesSubscript != null) {
CompileStack compileStack = controller.getCompileStack();
BinaryExpression be = (BinaryExpression) expression;
ClassNode methodResultType = operandStack.getTopOperand();
final int resultIdx = compileStack.defineTemporaryVariable("postfix_" + method, methodResultType, true);
BytecodeExpression methodResultLoader = new VariableSlotLoader(methodResultType, resultIdx, operandStack);
// execute the assignment, this will leave the right side
// (here the method call result) on the stack
assignToArray(be, be.getLeftExpression(), usesSubscript, methodResultLoader);
compileStack.removeVar(resultIdx);
} else // here we handle a.b++ and a++
if (expression instanceof VariableExpression || expression instanceof FieldExpression || expression instanceof PropertyExpression) {
operandStack.dup();
controller.getCompileStack().pushLHS(true);
expression.visit(controller.getAcg());
controller.getCompileStack().popLHS();
}
// other cases don't need storing, so nothing to be done for them
}
Aggregations