use of org.codehaus.groovy.ast.VariableScope in project groovy by apache.
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 by apache.
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);
}
}
use of org.codehaus.groovy.ast.VariableScope 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.VariableScope in project groovy by apache.
the class ReturnAdder method addReturnsIfNeeded.
private Statement addReturnsIfNeeded(Statement statement, VariableScope scope) {
if (statement instanceof ReturnStatement || statement instanceof BytecodeSequence || statement instanceof ThrowStatement) {
return statement;
}
if (statement instanceof EmptyStatement) {
final ReturnStatement returnStatement = new ReturnStatement(ConstantExpression.NULL);
listener.returnStatementAdded(returnStatement);
return returnStatement;
}
if (statement instanceof ExpressionStatement) {
ExpressionStatement expStmt = (ExpressionStatement) statement;
Expression expr = expStmt.getExpression();
ReturnStatement ret = new ReturnStatement(expr);
ret.setSourcePosition(expr);
ret.setStatementLabel(statement.getStatementLabel());
listener.returnStatementAdded(ret);
return ret;
}
if (statement instanceof SynchronizedStatement) {
SynchronizedStatement sync = (SynchronizedStatement) statement;
final Statement code = addReturnsIfNeeded(sync.getCode(), scope);
if (doAdd)
sync.setCode(code);
return sync;
}
if (statement instanceof IfStatement) {
IfStatement ifs = (IfStatement) statement;
final Statement ifBlock = addReturnsIfNeeded(ifs.getIfBlock(), scope);
final Statement elseBlock = addReturnsIfNeeded(ifs.getElseBlock(), scope);
if (doAdd) {
ifs.setIfBlock(ifBlock);
ifs.setElseBlock(elseBlock);
}
return ifs;
}
if (statement instanceof SwitchStatement) {
SwitchStatement swi = (SwitchStatement) statement;
for (CaseStatement caseStatement : swi.getCaseStatements()) {
final Statement code = adjustSwitchCaseCode(caseStatement.getCode(), scope, false);
if (doAdd)
caseStatement.setCode(code);
}
final Statement defaultStatement = adjustSwitchCaseCode(swi.getDefaultStatement(), scope, true);
if (doAdd)
swi.setDefaultStatement(defaultStatement);
return swi;
}
if (statement instanceof TryCatchStatement) {
TryCatchStatement trys = (TryCatchStatement) statement;
final boolean[] missesReturn = new boolean[1];
new ReturnAdder(new ReturnStatementListener() {
@Override
public void returnStatementAdded(ReturnStatement returnStatement) {
missesReturn[0] = true;
}
}).addReturnsIfNeeded(trys.getFinallyStatement(), scope);
boolean hasFinally = !(trys.getFinallyStatement() instanceof EmptyStatement);
// there is nothing to do
if (hasFinally && !missesReturn[0])
return trys;
// add returns to try and catch blocks
final Statement tryStatement = addReturnsIfNeeded(trys.getTryStatement(), scope);
if (doAdd)
trys.setTryStatement(tryStatement);
final int len = trys.getCatchStatements().size();
for (int i = 0; i != len; ++i) {
final CatchStatement catchStatement = trys.getCatchStatement(i);
final Statement code = addReturnsIfNeeded(catchStatement.getCode(), scope);
if (doAdd)
catchStatement.setCode(code);
}
return trys;
}
if (statement instanceof BlockStatement) {
BlockStatement block = (BlockStatement) statement;
final List list = block.getStatements();
if (!list.isEmpty()) {
int idx = list.size() - 1;
Statement last = addReturnsIfNeeded((Statement) list.get(idx), block.getVariableScope());
if (doAdd)
list.set(idx, last);
if (!statementReturns(last)) {
final ReturnStatement returnStatement = new ReturnStatement(ConstantExpression.NULL);
listener.returnStatementAdded(returnStatement);
if (doAdd)
list.add(returnStatement);
}
} else {
ReturnStatement ret = new ReturnStatement(ConstantExpression.NULL);
ret.setSourcePosition(block);
listener.returnStatementAdded(ret);
return ret;
}
BlockStatement newBlock = new BlockStatement(list, block.getVariableScope());
newBlock.setSourcePosition(block);
return newBlock;
}
if (statement == null) {
final ReturnStatement returnStatement = new ReturnStatement(ConstantExpression.NULL);
listener.returnStatementAdded(returnStatement);
return returnStatement;
} else {
final List list = new ArrayList();
list.add(statement);
final ReturnStatement returnStatement = new ReturnStatement(ConstantExpression.NULL);
listener.returnStatementAdded(returnStatement);
list.add(returnStatement);
BlockStatement newBlock = new BlockStatement(list, new VariableScope(scope));
newBlock.setSourcePosition(statement);
return newBlock;
}
}
use of org.codehaus.groovy.ast.VariableScope 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