use of org.codehaus.groovy.ast.stmt.BlockStatement in project groovy-core by groovy.
the class MemoizedASTTransformation method visit.
public void visit(ASTNode[] nodes, final SourceUnit source) {
init(nodes, source);
AnnotationNode annotationNode = (AnnotationNode) nodes[0];
AnnotatedNode annotatedNode = (AnnotatedNode) nodes[1];
if (MY_TYPE.equals(annotationNode.getClassNode()) && annotatedNode instanceof MethodNode) {
MethodNode methodNode = (MethodNode) annotatedNode;
if (methodNode.isAbstract()) {
addError("Annotation " + MY_TYPE_NAME + " cannot be used for abstract methods.", methodNode);
return;
}
if (methodNode.isVoidMethod()) {
addError("Annotation " + MY_TYPE_NAME + " cannot be used for void methods.", methodNode);
return;
}
ClassNode ownerClassNode = methodNode.getDeclaringClass();
MethodNode delegatingMethod = buildDelegatingMethod(methodNode, ownerClassNode);
ownerClassNode.addMethod(delegatingMethod);
int modifiers = FieldNode.ACC_PRIVATE | FieldNode.ACC_FINAL;
if (methodNode.isStatic()) {
modifiers = modifiers | FieldNode.ACC_STATIC;
}
int protectedCacheSize = getMemberIntValue(annotationNode, PROTECTED_CACHE_SIZE_NAME);
int maxCacheSize = getMemberIntValue(annotationNode, MAX_CACHE_SIZE_NAME);
MethodCallExpression memoizeClosureCallExpression = buildMemoizeClosureCallExpression(delegatingMethod, protectedCacheSize, maxCacheSize);
String memoizedClosureFieldName = buildUniqueName(ownerClassNode, CLOSURE_LABEL, methodNode);
FieldNode memoizedClosureField = new FieldNode(memoizedClosureFieldName, modifiers, newClass(ClassHelper.CLOSURE_TYPE), null, memoizeClosureCallExpression);
ownerClassNode.addField(memoizedClosureField);
BlockStatement newCode = new BlockStatement();
MethodCallExpression closureCallExpression = callX(fieldX(memoizedClosureField), CLOSURE_CALL_METHOD_NAME, args(methodNode.getParameters()));
closureCallExpression.setImplicitThis(false);
newCode.addStatement(returnS(closureCallExpression));
methodNode.setCode(newCode);
VariableScopeVisitor visitor = new VariableScopeVisitor(source);
visitor.visitClass(ownerClassNode);
}
}
use of org.codehaus.groovy.ast.stmt.BlockStatement in project groovy-core by groovy.
the class SingletonASTTransformation method createConstructor.
private void createConstructor(ClassNode classNode, FieldNode field, String propertyName, boolean isStrict) {
final List<ConstructorNode> cNodes = classNode.getDeclaredConstructors();
ConstructorNode foundNoArg = null;
for (ConstructorNode cNode : cNodes) {
final Parameter[] parameters = cNode.getParameters();
if (parameters == null || parameters.length == 0) {
foundNoArg = cNode;
break;
}
}
if (isStrict && cNodes.size() != 0) {
for (ConstructorNode cNode : cNodes) {
addError("@Singleton didn't expect to find one or more additional constructors: remove constructor(s) or set strict=false", cNode);
}
}
if (foundNoArg == null) {
final BlockStatement body = new BlockStatement();
body.addStatement(ifS(notNullX(varX(field)), new ThrowStatement(ctorX(make(RuntimeException.class), args(constX("Can't instantiate singleton " + classNode.getName() + ". Use " + classNode.getName() + "." + propertyName))))));
classNode.addConstructor(new ConstructorNode(ACC_PRIVATE, body));
}
}
use of org.codehaus.groovy.ast.stmt.BlockStatement in project groovy-core by groovy.
the class Verifier method addDefaultConstructor.
protected void addDefaultConstructor(ClassNode node) {
if (!node.getDeclaredConstructors().isEmpty())
return;
BlockStatement empty = new BlockStatement();
empty.setSourcePosition(node);
ConstructorNode constructor = new ConstructorNode(ACC_PUBLIC, empty);
constructor.setSourcePosition(node);
constructor.setHasNoRealSourcePosition(true);
node.addConstructor(constructor);
}
use of org.codehaus.groovy.ast.stmt.BlockStatement in project groovy-core by groovy.
the class Verifier method addDefaultParameterMethods.
/**
* Creates a new helper method for each combination of default parameter expressions
*/
protected void addDefaultParameterMethods(final ClassNode node) {
List methods = new ArrayList(node.getMethods());
addDefaultParameters(methods, new DefaultArgsAction() {
public void call(ArgumentListExpression arguments, Parameter[] newParams, MethodNode method) {
final BlockStatement code = new BlockStatement();
MethodNode newMethod = new MethodNode(method.getName(), method.getModifiers(), method.getReturnType(), newParams, method.getExceptions(), code);
// GROOVY-5681 and GROOVY-5632
for (Expression argument : arguments.getExpressions()) {
if (argument instanceof CastExpression) {
argument = ((CastExpression) argument).getExpression();
}
if (argument instanceof ConstructorCallExpression) {
ClassNode type = argument.getType();
if (type instanceof InnerClassNode && ((InnerClassNode) type).isAnonymous()) {
type.setEnclosingMethod(newMethod);
}
}
// check whether closure shared variables refer to params with default values (GROOVY-5632)
if (argument instanceof ClosureExpression) {
final List<Parameter> newMethodNodeParameters = Arrays.asList(newParams);
CodeVisitorSupport visitor = new CodeVisitorSupport() {
@Override
public void visitVariableExpression(VariableExpression expression) {
Variable v = expression.getAccessedVariable();
if (!(v instanceof Parameter))
return;
Parameter param = (Parameter) v;
if (param.hasInitialExpression() && code.getVariableScope().getDeclaredVariable(param.getName()) == null && !newMethodNodeParameters.contains(param)) {
VariableExpression localVariable = new VariableExpression(param.getName(), ClassHelper.makeReference());
DeclarationExpression declarationExpression = new DeclarationExpression(localVariable, Token.newSymbol(Types.EQUAL, -1, -1), new ConstructorCallExpression(ClassHelper.makeReference(), param.getInitialExpression()));
code.addStatement(new ExpressionStatement(declarationExpression));
code.getVariableScope().putDeclaredVariable(localVariable);
}
}
};
visitor.visitClosureExpression((ClosureExpression) argument);
}
}
MethodCallExpression expression = new MethodCallExpression(VariableExpression.THIS_EXPRESSION, method.getName(), arguments);
expression.setMethodTarget(method);
expression.setImplicitThis(true);
if (method.isVoidMethod()) {
code.addStatement(new ExpressionStatement(expression));
} else {
code.addStatement(new ReturnStatement(expression));
}
List<AnnotationNode> annotations = method.getAnnotations();
if (annotations != null) {
newMethod.addAnnotations(annotations);
}
MethodNode oldMethod = node.getDeclaredMethod(method.getName(), newParams);
if (oldMethod != null) {
throw new RuntimeParserException("The method with default parameters \"" + method.getTypeDescriptor() + "\" defines a method \"" + newMethod.getTypeDescriptor() + "\" that is already defined.", method);
}
addPropertyMethod(newMethod);
newMethod.setGenericsTypes(method.getGenericsTypes());
}
});
}
use of org.codehaus.groovy.ast.stmt.BlockStatement in project groovy-core by groovy.
the class Verifier method addInitialization.
protected void addInitialization(ClassNode node, ConstructorNode constructorNode) {
Statement firstStatement = constructorNode.getFirstStatement();
// if some transformation decided to generate constructor then it probably knows who it does
if (firstStatement instanceof BytecodeSequence)
return;
ConstructorCallExpression first = getFirstIfSpecialConstructorCall(firstStatement);
// in case of this(...) let the other constructor do the init
if (first != null && (first.isThisCall()))
return;
List<Statement> statements = new ArrayList<Statement>();
List<Statement> staticStatements = new ArrayList<Statement>();
final boolean isEnum = node.isEnum();
List<Statement> initStmtsAfterEnumValuesInit = new ArrayList<Statement>();
Set<String> explicitStaticPropsInEnum = new HashSet<String>();
if (isEnum) {
for (PropertyNode propNode : node.getProperties()) {
if (!propNode.isSynthetic() && propNode.getField().isStatic()) {
explicitStaticPropsInEnum.add(propNode.getField().getName());
}
}
for (FieldNode fieldNode : node.getFields()) {
if (!fieldNode.isSynthetic() && fieldNode.isStatic() && fieldNode.getType() != node) {
explicitStaticPropsInEnum.add(fieldNode.getName());
}
}
}
if (!Traits.isTrait(node)) {
for (FieldNode fn : node.getFields()) {
addFieldInitialization(statements, staticStatements, fn, isEnum, initStmtsAfterEnumValuesInit, explicitStaticPropsInEnum);
}
}
statements.addAll(node.getObjectInitializerStatements());
Statement code = constructorNode.getCode();
BlockStatement block = new BlockStatement();
List<Statement> otherStatements = block.getStatements();
if (code instanceof BlockStatement) {
block = (BlockStatement) code;
otherStatements = block.getStatements();
} else if (code != null) {
otherStatements.add(code);
}
if (!otherStatements.isEmpty()) {
if (first != null) {
// it is super(..) since this(..) is already covered
otherStatements.remove(0);
statements.add(0, firstStatement);
}
Statement stmtThis$0 = getImplicitThis$0StmtIfInnerClass(otherStatements);
if (stmtThis$0 != null) {
// since there can be field init statements that depend on method/property dispatching
// that uses this$0, it needs to bubble up before the super call itself (GROOVY-4471)
statements.add(0, stmtThis$0);
}
statements.addAll(otherStatements);
}
BlockStatement newBlock = new BlockStatement(statements, block.getVariableScope());
newBlock.setSourcePosition(block);
constructorNode.setCode(newBlock);
if (!staticStatements.isEmpty()) {
if (isEnum) {
/*
* GROOVY-3161: initialize statements for explicitly declared static fields
* inside an enum should come after enum values are initialized
*/
staticStatements.removeAll(initStmtsAfterEnumValuesInit);
node.addStaticInitializerStatements(staticStatements, true);
if (!initStmtsAfterEnumValuesInit.isEmpty()) {
node.positionStmtsAfterEnumInitStmts(initStmtsAfterEnumValuesInit);
}
} else {
node.addStaticInitializerStatements(staticStatements, true);
}
}
}
Aggregations