use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy by apache.
the class StaticImportVisitor method transformMethodCallExpression.
protected Expression transformMethodCallExpression(MethodCallExpression mce) {
Expression args = transform(mce.getArguments());
Expression method = transform(mce.getMethod());
Expression object = transform(mce.getObjectExpression());
boolean isExplicitThisOrSuper = false;
boolean isExplicitSuper = false;
if (object instanceof VariableExpression) {
VariableExpression ve = (VariableExpression) object;
isExplicitThisOrSuper = !mce.isImplicitThis() && (ve.isThisExpression() || ve.isSuperExpression());
isExplicitSuper = ve.isSuperExpression();
}
if (mce.isImplicitThis() || isExplicitThisOrSuper) {
if (mce.isImplicitThis()) {
Expression ret = findStaticMethodImportFromModule(method, args);
if (ret != null) {
setSourcePosition(ret, mce);
return ret;
}
if (method instanceof ConstantExpression && !inLeftExpression) {
// could be a closure field
String methodName = (String) ((ConstantExpression) method).getValue();
ret = findStaticFieldOrPropAccessorImportFromModule(methodName);
if (ret != null) {
ret = new MethodCallExpression(ret, "call", args);
setSourcePosition(ret, mce);
return ret;
}
}
} else if (currentMethod != null && currentMethod.isStatic() && isExplicitSuper) {
MethodCallExpression ret = new MethodCallExpression(new ClassExpression(currentClass.getSuperClass()), method, args);
setSourcePosition(ret, mce);
return ret;
}
if (method instanceof ConstantExpression) {
ConstantExpression ce = (ConstantExpression) method;
Object value = ce.getValue();
if (value instanceof String) {
boolean foundInstanceMethod = false;
String methodName = (String) value;
boolean inInnerClass = isInnerClass(currentClass);
if (currentMethod != null && !currentMethod.isStatic()) {
if (currentClass.hasPossibleMethod(methodName, args)) {
foundInstanceMethod = true;
}
}
boolean lookForPossibleStaticMethod = !methodName.equals("call");
lookForPossibleStaticMethod &= !foundInstanceMethod;
lookForPossibleStaticMethod |= inSpecialConstructorCall;
lookForPossibleStaticMethod &= !inInnerClass;
if (!inClosure && lookForPossibleStaticMethod && (hasPossibleStaticMethod(currentClass, methodName, args, true)) || hasPossibleStaticProperty(currentClass, methodName)) {
StaticMethodCallExpression smce = new StaticMethodCallExpression(currentClass, methodName, args);
setSourcePosition(smce, mce);
return smce;
}
if (!inClosure && inInnerClass && inSpecialConstructorCall && mce.isImplicitThis() && !foundInstanceMethod) {
if (currentClass.getOuterClass().hasPossibleMethod(methodName, args)) {
object = new PropertyExpression(new ClassExpression(currentClass.getOuterClass()), new ConstantExpression("this"));
} else if (hasPossibleStaticMethod(currentClass.getOuterClass(), methodName, args, true) || hasPossibleStaticProperty(currentClass.getOuterClass(), methodName)) {
StaticMethodCallExpression smce = new StaticMethodCallExpression(currentClass.getOuterClass(), methodName, args);
setSourcePosition(smce, mce);
return smce;
}
}
}
}
}
MethodCallExpression result = new MethodCallExpression(object, method, args);
result.setSafe(mce.isSafe());
result.setImplicitThis(mce.isImplicitThis());
result.setSpreadSafe(mce.isSpreadSafe());
result.setMethodTarget(mce.getMethodTarget());
// GROOVY-6757
result.setGenericsTypes(mce.getGenericsTypes());
setSourcePosition(result, mce);
return result;
}
use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy by apache.
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
}
use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy by apache.
the class InnerClassCompletionVisitor method addThisReference.
private void addThisReference(ConstructorNode node) {
if (!shouldHandleImplicitThisForInnerClass(classNode))
return;
Statement code = node.getCode();
// add "this$0" field init
//add this parameter to node
Parameter[] params = node.getParameters();
Parameter[] newParams = new Parameter[params.length + 1];
System.arraycopy(params, 0, newParams, 1, params.length);
String name = getUniqueName(params, node);
Parameter thisPara = new Parameter(classNode.getOuterClass().getPlainNodeReference(), name);
newParams[0] = thisPara;
node.setParameters(newParams);
BlockStatement block = null;
if (code == null) {
block = new BlockStatement();
} else if (!(code instanceof BlockStatement)) {
block = new BlockStatement();
block.addStatement(code);
} else {
block = (BlockStatement) code;
}
BlockStatement newCode = new BlockStatement();
addFieldInit(thisPara, thisField, newCode);
ConstructorCallExpression cce = getFirstIfSpecialConstructorCall(block);
if (cce == null) {
cce = new ConstructorCallExpression(ClassNode.SUPER, new TupleExpression());
block.getStatements().add(0, new ExpressionStatement(cce));
}
if (shouldImplicitlyPassThisPara(cce)) {
// add thisPara to this(...)
TupleExpression args = (TupleExpression) cce.getArguments();
List<Expression> expressions = args.getExpressions();
VariableExpression ve = new VariableExpression(thisPara.getName());
ve.setAccessedVariable(thisPara);
expressions.add(0, ve);
}
if (cce.isSuperCall()) {
// we have a call to super here, so we need to add
// our code after that
block.getStatements().add(1, newCode);
}
node.setCode(block);
}
use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy by apache.
the class InnerClassVisitor method visitConstructorCallExpression.
@Override
public void visitConstructorCallExpression(ConstructorCallExpression call) {
super.visitConstructorCallExpression(call);
if (!call.isUsingAnonymousInnerClass()) {
passThisReference(call);
return;
}
InnerClassNode innerClass = (InnerClassNode) call.getType();
ClassNode outerClass = innerClass.getOuterClass();
ClassNode superClass = innerClass.getSuperClass();
if (superClass instanceof InnerClassNode && !superClass.isInterface() && !(superClass.isStaticClass() || ((superClass.getModifiers() & ACC_STATIC) == ACC_STATIC))) {
insertThis0ToSuperCall(call, innerClass);
}
if (!innerClass.getDeclaredConstructors().isEmpty())
return;
if ((innerClass.getModifiers() & ACC_STATIC) != 0)
return;
VariableScope scope = innerClass.getVariableScope();
if (scope == null)
return;
// expressions = constructor call arguments
List<Expression> expressions = ((TupleExpression) call.getArguments()).getExpressions();
// block = init code for the constructor we produce
BlockStatement block = new BlockStatement();
// parameters = parameters of the constructor
final int additionalParamCount = 1 + scope.getReferencedLocalVariablesCount();
List<Parameter> parameters = new ArrayList<Parameter>(expressions.size() + additionalParamCount);
// superCallArguments = arguments for the super call == the constructor call arguments
List<Expression> superCallArguments = new ArrayList<Expression>(expressions.size());
// first we add a super() call for all expressions given in the
// constructor call expression
int pCount = additionalParamCount;
for (Expression expr : expressions) {
pCount++;
// add one parameter for each expression in the
// constructor call
Parameter param = new Parameter(ClassHelper.OBJECT_TYPE, "p" + pCount);
parameters.add(param);
// add to super call
superCallArguments.add(new VariableExpression(param));
}
// add the super call
ConstructorCallExpression cce = new ConstructorCallExpression(ClassNode.SUPER, new TupleExpression(superCallArguments));
block.addStatement(new ExpressionStatement(cce));
// we need to add "this" to access unknown methods/properties
// this is saved in a field named this$0
pCount = 0;
expressions.add(pCount, VariableExpression.THIS_EXPRESSION);
boolean isStatic = isStaticThis(innerClass, scope);
ClassNode outerClassType = getClassNode(outerClass, isStatic);
if (!isStatic && inClosure)
outerClassType = ClassHelper.CLOSURE_TYPE;
outerClassType = outerClassType.getPlainNodeReference();
Parameter thisParameter = new Parameter(outerClassType, "p" + pCount);
parameters.add(pCount, thisParameter);
thisField = innerClass.addField("this$0", PUBLIC_SYNTHETIC, outerClassType, null);
addFieldInit(thisParameter, thisField, block);
// for each shared variable we add a reference and save it as field
for (Iterator it = scope.getReferencedLocalVariablesIterator(); it.hasNext(); ) {
pCount++;
org.codehaus.groovy.ast.Variable var = (org.codehaus.groovy.ast.Variable) it.next();
VariableExpression ve = new VariableExpression(var);
ve.setClosureSharedVariable(true);
ve.setUseReferenceDirectly(true);
expressions.add(pCount, ve);
ClassNode rawReferenceType = ClassHelper.REFERENCE_TYPE.getPlainNodeReference();
Parameter p = new Parameter(rawReferenceType, "p" + pCount);
parameters.add(pCount, p);
p.setOriginType(var.getOriginType());
final VariableExpression initial = new VariableExpression(p);
initial.setSynthetic(true);
initial.setUseReferenceDirectly(true);
final FieldNode pField = innerClass.addFieldFirst(ve.getName(), PUBLIC_SYNTHETIC, rawReferenceType, initial);
pField.setHolder(true);
pField.setOriginType(ClassHelper.getWrapper(var.getOriginType()));
}
innerClass.addConstructor(ACC_SYNTHETIC, parameters.toArray(new Parameter[parameters.size()]), ClassNode.EMPTY_ARRAY, block);
}
use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy by apache.
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;
}
Aggregations