
org.codehaus.groovy.transform.SingletonASTTransformation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of groovy-jdk14 Show documentation
Show all versions of groovy-jdk14 Show documentation
Groovy: A powerful, dynamic language for the JVM
The newest version!
/*
* Copyright 2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.groovy.transform;
import org.codehaus.groovy.ast.*;
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.*;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.syntax.Token;
import org.objectweb.asm.Opcodes;
import java.util.List;
import java.util.Iterator;
/**
* Handles generation of code for the @Singleton annotation
*
* @author Alex Tkachman
*/
@GroovyASTTransformation(phase= CompilePhase.CANONICALIZATION)
public class SingletonASTTransformation implements ASTTransformation, Opcodes {
/**
*
* @param nodes the ast nodes
* @param source the source unit for the nodes
*/
public void visit(ASTNode[] nodes, SourceUnit source) {
if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class");
}
AnnotatedNode parent = (AnnotatedNode) nodes[1];
AnnotationNode node = (AnnotationNode) nodes[0];
if (parent instanceof ClassNode) {
ClassNode classNode = (ClassNode) parent;
final Expression member = node.getMember("lazy");
if(member instanceof ConstantExpression && ((ConstantExpression)member).getValue().equals(true))
createLazy(classNode);
else
createNonLazy(classNode);
}
}
private void createNonLazy(ClassNode classNode) {
final FieldNode fieldNode = classNode.addField("instance", ACC_PUBLIC|ACC_FINAL|ACC_STATIC, classNode, new ConstructorCallExpression(classNode, new ArgumentListExpression()));
createConstructor(classNode, fieldNode);
final BlockStatement body = new BlockStatement();
body.addStatement(new ReturnStatement(new FieldExpression(fieldNode)));
classNode.addMethod("getInstance", ACC_STATIC|ACC_PUBLIC, classNode, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body);
}
private void createLazy(ClassNode classNode) {
final FieldNode fieldNode = classNode.addField("instance", ACC_PRIVATE|ACC_STATIC|ACC_VOLATILE, classNode, null);
createConstructor(classNode, fieldNode);
final BlockStatement body = new BlockStatement();
final FieldExpression instanceExpression = new FieldExpression(fieldNode);
body.addStatement(new IfStatement(
new BooleanExpression(new BinaryExpression(instanceExpression, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)),
new ReturnStatement(instanceExpression),
new SynchronizedStatement(
new ClassExpression(classNode),
new IfStatement(
new BooleanExpression(new BinaryExpression(instanceExpression, Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)),
new ReturnStatement(instanceExpression),
new ReturnStatement(new BinaryExpression(instanceExpression,Token.newSymbol("=",-1,-1), new ConstructorCallExpression(classNode, new ArgumentListExpression())))
)
)
));
classNode.addMethod("getInstance", ACC_STATIC|ACC_PUBLIC, classNode, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body);
}
private void createConstructor(ClassNode classNode, FieldNode field) {
final List list = classNode.getDeclaredConstructors();
MethodNode found = null;
for (Iterator it = list.iterator(); it.hasNext(); ) {
MethodNode mn = (MethodNode) it.next();
final Parameter[] parameters = mn.getParameters();
if (parameters == null || parameters.length == 0) {
found = mn;
break;
}
}
if (found == null) {
final BlockStatement body = new BlockStatement();
body.addStatement(new IfStatement(
new BooleanExpression(new BinaryExpression(new FieldExpression(field), Token.newSymbol("!=",-1,-1), ConstantExpression.NULL)),
new ThrowStatement(
new ConstructorCallExpression(ClassHelper.make(RuntimeException.class),
new ArgumentListExpression(
new ConstantExpression("Can't instantiate singleton " + classNode.getName() + ". Use " + classNode.getName() + ".instance" )))),
new EmptyStatement()));
classNode.addConstructor(new ConstructorNode(ACC_PRIVATE, body));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy