use of org.codehaus.groovy.ast.expr.ConstructorCallExpression in project groovy-core by groovy.
the class Verifier method addGroovyObjectInterfaceAndMethods.
protected void addGroovyObjectInterfaceAndMethods(ClassNode node, final String classInternalName) {
if (!node.isDerivedFromGroovyObject())
node.addInterface(ClassHelper.make(GroovyObject.class));
FieldNode metaClassField = getMetaClassField(node);
if (!node.hasMethod("getMetaClass", Parameter.EMPTY_ARRAY)) {
metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
addMethod(node, !Modifier.isAbstract(node.getModifiers()), "getMetaClass", ACC_PUBLIC, ClassHelper.METACLASS_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
Label nullLabel = new Label();
/**
* the code is:
* if (this.metaClass==null) {
* this.metaClass = this.$getStaticMetaClass
* return this.metaClass
* } else {
* return this.metaClass
* }
* with the optimization that the result of the
* first this.metaClass is duped on the operand
* stack and reused for the return in the else part
*/
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(DUP);
mv.visitJumpInsn(IFNULL, nullLabel);
mv.visitInsn(ARETURN);
mv.visitLabel(nullLabel);
mv.visitInsn(POP);
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(ARETURN);
}
}));
}
Parameter[] parameters = new Parameter[] { new Parameter(ClassHelper.METACLASS_TYPE, "mc") };
if (!node.hasMethod("setMetaClass", parameters)) {
metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
Statement setMetaClassCode;
if (Modifier.isFinal(metaClassField.getModifiers())) {
ConstantExpression text = new ConstantExpression("cannot set read-only meta class");
ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
setMetaClassCode = new ExpressionStatement(cce);
} else {
List list = new ArrayList();
list.add(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
/**
* the code is (meta class is stored in 1):
* this.metaClass = <1>
*/
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(RETURN);
}
});
setMetaClassCode = new BytecodeSequence(list);
}
addMethod(node, !Modifier.isAbstract(node.getModifiers()), "setMetaClass", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY, setMetaClassCode);
}
if (!node.hasMethod("invokeMethod", INVOKE_METHOD_PARAMS)) {
VariableExpression vMethods = new VariableExpression("method");
VariableExpression vArguments = new VariableExpression("arguments");
VariableScope blockScope = new VariableScope();
blockScope.putReferencedLocalVariable(vMethods);
blockScope.putReferencedLocalVariable(vArguments);
addMethod(node, !Modifier.isAbstract(node.getModifiers()), "invokeMethod", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, INVOKE_METHOD_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "invokeMethod", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", true);
mv.visitInsn(ARETURN);
}
}));
}
if (!node.hasMethod("getProperty", GET_PROPERTY_PARAMS)) {
addMethod(node, !Modifier.isAbstract(node.getModifiers()), "getProperty", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, GET_PROPERTY_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "getProperty", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", true);
mv.visitInsn(ARETURN);
}
}));
}
if (!node.hasMethod("setProperty", SET_PROPERTY_PARAMS)) {
addMethod(node, !Modifier.isAbstract(node.getModifiers()), "setProperty", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_PROPERTY_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "setProperty", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", true);
mv.visitInsn(RETURN);
}
}));
}
}
use of org.codehaus.groovy.ast.expr.ConstructorCallExpression 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);
}
}
}
use of org.codehaus.groovy.ast.expr.ConstructorCallExpression in project grails-core by grails.
the class AbstractGrailsArtefactTransformer method performInstanceImplementationInjection.
protected void performInstanceImplementationInjection(SourceUnit source, ClassNode classNode, Map<String, ClassNode> genericsPlaceholders, Class instanceImplementation) {
ClassNode implementationNode;
final ConstructorCallExpression constructorCallExpression;
try {
implementationNode = GrailsASTUtils.replaceGenericsPlaceholders(ClassHelper.make(instanceImplementation), genericsPlaceholders);
constructorCallExpression = GrailsASTUtils.hasZeroArgsConstructor(implementationNode) ? new ConstructorCallExpression(implementationNode, ZERO_ARGS) : null;
} catch (Throwable e) {
// this may well be ok, as we want to be able to compile against, for example, non servlet environments. In this case just bail out.
return;
}
String apiInstanceProperty = INSTANCE_PREFIX + instanceImplementation.getSimpleName();
Expression apiInstance = new VariableExpression(apiInstanceProperty, implementationNode);
if (requiresStaticLookupMethod()) {
final String lookupMethodName = CURRENT_PREFIX + instanceImplementation.getSimpleName();
MethodNode lookupMethod = createStaticLookupMethod(classNode, implementationNode, apiInstanceProperty, lookupMethodName);
apiInstance = new MethodCallExpression(new ClassExpression(classNode), lookupMethodName, ZERO_ARGS);
((MethodCallExpression) apiInstance).setMethodTarget(lookupMethod);
} else if (requiresAutowiring()) {
PropertyNode propertyNode = new PropertyNode(apiInstanceProperty, Modifier.PUBLIC, implementationNode, classNode, constructorCallExpression, null, null);
propertyNode.addAnnotation(AUTO_WIRED_ANNOTATION);
if (getMarkerAnnotation() != null) {
propertyNode.addAnnotation(getMarkerAnnotation());
}
classNode.addProperty(propertyNode);
} else {
FieldNode fieldNode = classNode.getField(apiInstanceProperty);
if (fieldNode == null || (Modifier.isPrivate(fieldNode.getModifiers()) && !fieldNode.getDeclaringClass().equals(classNode))) {
fieldNode = new FieldNode(apiInstanceProperty, PRIVATE_STATIC_MODIFIER, implementationNode, classNode, constructorCallExpression);
classNode.addField(fieldNode);
}
}
while (!implementationNode.equals(AbstractGrailsArtefactTransformer.OBJECT_CLASS)) {
List<MethodNode> declaredMethods = implementationNode.getMethods();
for (MethodNode declaredMethod : declaredMethods) {
if (GrailsASTUtils.isConstructorMethod(declaredMethod)) {
GrailsASTUtils.addDelegateConstructor(classNode, declaredMethod, genericsPlaceholders);
} else if (isCandidateInstanceMethod(classNode, declaredMethod)) {
addDelegateInstanceMethod(classNode, apiInstance, declaredMethod, getMarkerAnnotation(), genericsPlaceholders);
}
}
implementationNode = implementationNode.getSuperClass();
}
performInjectionInternal(apiInstanceProperty, source, classNode);
}
use of org.codehaus.groovy.ast.expr.ConstructorCallExpression in project grails-core by grails.
the class AbstractGrailsArtefactTransformer method performStaticImplementationInjection.
protected void performStaticImplementationInjection(ClassNode classNode, Map<String, ClassNode> genericsPlaceholders, Class staticImplementation) {
ClassNode staticImplementationNode = GrailsASTUtils.replaceGenericsPlaceholders(ClassHelper.make(staticImplementation), genericsPlaceholders);
final List<MethodNode> declaredMethods = staticImplementationNode.getMethods();
final String staticImplementationSimpleName = staticImplementation.getSimpleName();
String apiInstanceProperty = STATIC_PREFIX + staticImplementationSimpleName;
final String lookupMethodName = CURRENT_PREFIX + staticImplementationSimpleName;
if (!requiresStaticLookupMethod()) {
final ConstructorCallExpression constructorCallExpression = new ConstructorCallExpression(staticImplementationNode, ZERO_ARGS);
addApiLookupFieldAndSetter(classNode, staticImplementationNode, apiInstanceProperty, constructorCallExpression);
}
MethodNode lookupMethod = createStaticLookupMethod(classNode, staticImplementationNode, apiInstanceProperty, lookupMethodName);
MethodCallExpression apiLookupMethod = new MethodCallExpression(new ClassExpression(classNode), lookupMethodName, ZERO_ARGS);
apiLookupMethod.setMethodTarget(lookupMethod);
for (MethodNode declaredMethod : declaredMethods) {
if (isStaticCandidateMethod(classNode, declaredMethod)) {
addDelegateStaticMethod(classNode, apiLookupMethod, declaredMethod, genericsPlaceholders);
}
}
}
use of org.codehaus.groovy.ast.expr.ConstructorCallExpression in project grails-core by grails.
the class AbstractGrailsArtefactTransformer method populateAutowiredApiLookupMethod.
protected MethodNode populateAutowiredApiLookupMethod(ClassNode classNode, ClassNode implementationNode, String apiProperty, String methodName, BlockStatement methodBody) {
addApiLookupFieldAndSetter(classNode, implementationNode, apiProperty, null);
VariableExpression apiVar = new VariableExpression(apiProperty, implementationNode);
BlockStatement ifBlock = new BlockStatement();
ArgumentListExpression arguments = new ArgumentListExpression();
arguments.addExpression(new ConstantExpression("Method on class [" + classNode + "] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly."));
ifBlock.addStatement(new ThrowStatement(new ConstructorCallExpression(new ClassNode(IllegalStateException.class), arguments)));
BlockStatement elseBlock = new BlockStatement();
elseBlock.addStatement(new ReturnStatement(apiVar));
methodBody.addStatement(new IfStatement(new BooleanExpression(new BinaryExpression(apiVar, GrailsASTUtils.EQUALS_OPERATOR, GrailsASTUtils.NULL_EXPRESSION)), ifBlock, elseBlock));
MethodNode methodNode = new MethodNode(methodName, PUBLIC_STATIC_MODIFIER, implementationNode, ZERO_PARAMETERS, null, methodBody);
return methodNode;
}
Aggregations