use of org.codehaus.groovy.ast.VariableScope in project groovy-core by groovy.
the class ClosureWriter method getClosureSharedVariables.
protected Parameter[] getClosureSharedVariables(ClosureExpression ce) {
VariableScope scope = ce.getVariableScope();
Parameter[] ret = new Parameter[scope.getReferencedLocalVariablesCount()];
int index = 0;
for (Iterator iter = scope.getReferencedLocalVariablesIterator(); iter.hasNext(); ) {
Variable element = (org.codehaus.groovy.ast.Variable) iter.next();
Parameter p = new Parameter(element.getType(), element.getName());
p.setOriginType(element.getOriginType());
p.setClosureSharedVariable(element.isClosureSharedVariable());
ret[index] = p;
index++;
}
return ret;
}
use of org.codehaus.groovy.ast.VariableScope 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.VariableScope in project grails-core by grails.
the class DelegateAsyncTransformation method applyDelegateAsyncTransform.
private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetApi, String fieldName) {
List<MethodNode> methods = targetApi.getAllDeclaredMethods();
ClassNode promisesClass = ClassHelper.make(Promises.class).getPlainNodeReference();
MethodNode createPromiseMethodTargetWithDecorators = promisesClass.getDeclaredMethod("createPromise", new Parameter[] { new Parameter(new ClassNode(Closure.class), "c"), new Parameter(new ClassNode(List.class), "c") });
DelegateAsyncTransactionalMethodTransformer delegateAsyncTransactionalMethodTransformer = lookupAsyncTransactionalMethodTransformer();
for (MethodNode m : methods) {
if (isCandidateMethod(m)) {
MethodNode existingMethod = classNode.getMethod(m.getName(), m.getParameters());
if (existingMethod == null) {
ClassNode promiseNode = ClassHelper.make(Promise.class).getPlainNodeReference();
ClassNode originalReturnType = m.getReturnType();
if (!originalReturnType.getNameWithoutPackage().equals(VOID)) {
ClassNode returnType;
if (ClassHelper.isPrimitiveType(originalReturnType.redirect())) {
returnType = ClassHelper.getWrapper(originalReturnType.redirect());
} else {
returnType = alignReturnType(classNode, originalReturnType);
}
if (!OBJECT_CLASS_NODE.equals(returnType)) {
promiseNode.setGenericsTypes(new GenericsType[] { new GenericsType(returnType) });
}
}
final BlockStatement methodBody = new BlockStatement();
final BlockStatement promiseBody = new BlockStatement();
final ClosureExpression closureExpression = new ClosureExpression(new Parameter[0], promiseBody);
VariableScope variableScope = new VariableScope();
closureExpression.setVariableScope(variableScope);
VariableExpression thisObject = new VariableExpression("this");
ClassNode delegateAsyncUtilsClassNode = new ClassNode(DelegateAsyncUtils.class);
MethodNode getPromiseDecoratorsMethodNode = delegateAsyncUtilsClassNode.getDeclaredMethods("getPromiseDecorators").get(0);
ListExpression promiseDecorators = new ListExpression();
ArgumentListExpression getPromiseDecoratorsArguments = new ArgumentListExpression(thisObject, promiseDecorators);
delegateAsyncTransactionalMethodTransformer.transformTransactionalMethod(classNode, targetApi, m, promiseDecorators);
MethodCallExpression getDecoratorsMethodCall = new MethodCallExpression(new ClassExpression(delegateAsyncUtilsClassNode), "getPromiseDecorators", getPromiseDecoratorsArguments);
getDecoratorsMethodCall.setMethodTarget(getPromiseDecoratorsMethodNode);
MethodCallExpression createPromiseWithDecorators = new MethodCallExpression(new ClassExpression(promisesClass), "createPromise", new ArgumentListExpression(closureExpression, getDecoratorsMethodCall));
if (createPromiseMethodTargetWithDecorators != null) {
createPromiseWithDecorators.setMethodTarget(createPromiseMethodTargetWithDecorators);
}
methodBody.addStatement(new ExpressionStatement(createPromiseWithDecorators));
final ArgumentListExpression arguments = new ArgumentListExpression();
Parameter[] parameters = copyParameters(StaticTypeCheckingSupport.parameterizeArguments(classNode, m));
for (Parameter p : parameters) {
p.setClosureSharedVariable(true);
variableScope.putReferencedLocalVariable(p);
VariableExpression ve = new VariableExpression(p);
ve.setClosureSharedVariable(true);
arguments.addExpression(ve);
}
MethodCallExpression delegateMethodCall = new MethodCallExpression(new VariableExpression(fieldName), m.getName(), arguments);
promiseBody.addStatement(new ExpressionStatement(delegateMethodCall));
MethodNode newMethodNode = new MethodNode(m.getName(), Modifier.PUBLIC, promiseNode, parameters, null, methodBody);
classNode.addMethod(newMethodNode);
}
}
}
}
use of org.codehaus.groovy.ast.VariableScope in project groovy-core by groovy.
the class MarkupBuilderCodeTransformer method transformMethodCall.
private Expression transformMethodCall(final MethodCallExpression exp) {
String name = exp.getMethodAsString();
if (exp.isImplicitThis() && "include".equals(name)) {
return tryTransformInclude(exp);
} else if (exp.isImplicitThis() && name.startsWith(":")) {
List<Expression> args;
if (exp.getArguments() instanceof ArgumentListExpression) {
args = ((ArgumentListExpression) exp.getArguments()).getExpressions();
} else {
args = Collections.singletonList(exp.getArguments());
}
Expression newArguments = transform(new ArgumentListExpression(new ConstantExpression(name.substring(1)), new ArrayExpression(ClassHelper.OBJECT_TYPE, args)));
MethodCallExpression call = new MethodCallExpression(new VariableExpression("this"), "methodMissing", newArguments);
call.setImplicitThis(true);
call.setSafe(exp.isSafe());
call.setSpreadSafe(exp.isSpreadSafe());
call.setSourcePosition(exp);
return call;
} else if (name != null && name.startsWith("$")) {
MethodCallExpression reformatted = new MethodCallExpression(exp.getObjectExpression(), name.substring(1), exp.getArguments());
reformatted.setImplicitThis(exp.isImplicitThis());
reformatted.setSafe(exp.isSafe());
reformatted.setSpreadSafe(exp.isSpreadSafe());
reformatted.setSourcePosition(exp);
// wrap in a stringOf { ... } closure call
ClosureExpression clos = new ClosureExpression(Parameter.EMPTY_ARRAY, new ExpressionStatement(reformatted));
clos.setVariableScope(new VariableScope());
MethodCallExpression stringOf = new MethodCallExpression(new VariableExpression("this"), "stringOf", clos);
stringOf.setImplicitThis(true);
stringOf.setSourcePosition(reformatted);
return stringOf;
}
return super.transform(exp);
}
use of org.codehaus.groovy.ast.VariableScope in project groovy-core by groovy.
the class AutoNewLineTransformer method visitClosureExpression.
@Override
public void visitClosureExpression(final ClosureExpression expression) {
super.visitClosureExpression(expression);
if (inBuilderMethod) {
Statement oldCode = expression.getCode();
BlockStatement block = oldCode instanceof BlockStatement ? ((BlockStatement) oldCode) : new BlockStatement(Arrays.asList(oldCode), new VariableScope());
List<Statement> statements = block.getStatements();
if (!statements.isEmpty()) {
Statement first = statements.get(0);
Statement last = statements.get(statements.size() - 1);
if (expression.getLineNumber() < first.getLineNumber()) {
// there's a new line between { -> ... and the first statement
statements.add(0, createNewLine(expression));
}
if (expression.getLastLineNumber() > last.getLastLineNumber()) {
// there's a new line between { -> ... and the first statement
statements.add(createNewLine(expression));
}
}
expression.setCode(block);
}
}
Aggregations