use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method visitConstructorCallExpression.
@Override
public void visitConstructorCallExpression(ConstructorCallExpression call) {
super.visitConstructorCallExpression(call);
if (extension.beforeMethodCall(call)) {
extension.afterMethodCall(call);
return;
}
ClassNode receiver = call.isThisCall() ? typeCheckingContext.getEnclosingClassNode() : call.isSuperCall() ? typeCheckingContext.getEnclosingClassNode().getSuperClass() : call.getType();
Expression arguments = call.getArguments();
ArgumentListExpression argumentList = InvocationWriter.makeArgumentList(arguments);
checkForbiddenSpreadArgument(argumentList);
ClassNode[] args = getArgumentTypes(argumentList);
if (args.length > 0 && typeCheckingContext.getEnclosingClosure() != null && argumentList.getExpression(0) instanceof VariableExpression && ((VariableExpression) argumentList.getExpression(0)).isThisExpression() && call.getType() instanceof InnerClassNode && call.getType().getOuterClass().equals(args[0]) && !call.getType().isStaticClass()) {
args[0] = CLOSURE_TYPE;
}
MethodNode node = null;
if (args.length == 1 && implementsInterfaceOrIsSubclassOf(args[0], MAP_TYPE) && findMethod(receiver, "<init>", ClassNode.EMPTY_ARRAY).size() == 1 && findMethod(receiver, "<init>", args).isEmpty()) {
// bean-style constructor
node = typeCheckMapConstructor(call, receiver, arguments);
if (node != null) {
storeTargetMethod(call, node);
extension.afterMethodCall(call);
return;
}
}
node = findMethodOrFail(call, receiver, "<init>", args);
if (node != null) {
if (node.getParameters().length == 0 && args.length == 1 && implementsInterfaceOrIsSubclassOf(args[0], MAP_TYPE)) {
node = typeCheckMapConstructor(call, receiver, arguments);
} else {
typeCheckMethodsWithGenericsOrFail(receiver, args, node, call);
}
if (node != null)
storeTargetMethod(call, node);
}
extension.afterMethodCall(call);
}
use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.
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.InnerClassNode in project groovy-core by groovy.
the class InnerClassCompletionVisitor method shouldImplicitlyPassThisPara.
private boolean shouldImplicitlyPassThisPara(ConstructorCallExpression cce) {
boolean pass = false;
ClassNode superCN = classNode.getSuperClass();
if (cce.isThisCall()) {
pass = true;
} else if (cce.isSuperCall()) {
// needs to be passed
if (!superCN.isEnum() && !superCN.isInterface() && superCN instanceof InnerClassNode) {
InnerClassNode superInnerCN = (InnerClassNode) superCN;
if (!isStatic(superInnerCN) && classNode.getOuterClass().isDerivedFrom(superCN.getOuterClass())) {
pass = true;
}
}
}
return pass;
}
use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.
the class InnerClassCompletionVisitor method addDefaultMethods.
private void addDefaultMethods(InnerClassNode node) {
final boolean isStatic = isStatic(node);
ClassNode outerClass = node.getOuterClass();
final String classInternalName = org.codehaus.groovy.classgen.asm.BytecodeHelper.getClassInternalName(node);
final String outerClassInternalName = getInternalName(outerClass, isStatic);
final String outerClassDescriptor = getTypeDescriptor(outerClass, isStatic);
final int objectDistance = getObjectDistance(outerClass);
// add method dispatcher
Parameter[] parameters = new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name"), new Parameter(ClassHelper.OBJECT_TYPE, "args") };
String methodName = "methodMissing";
if (isStatic)
addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
MethodNode method = node.addSyntheticMethod(methodName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
BlockStatement block = new BlockStatement();
if (isStatic) {
setMethodDispatcherCode(block, new ClassExpression(outerClass), parameters);
} else {
block.addStatement(new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
getThis(mv, classInternalName, outerClassDescriptor, outerClassInternalName);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$invoke$" + objectDistance, "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", false);
mv.visitInsn(ARETURN);
}
}));
}
method.setCode(block);
// add property getter dispatcher
parameters = new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name"), new Parameter(ClassHelper.OBJECT_TYPE, "val") };
methodName = "propertyMissing";
if (isStatic)
addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
method = node.addSyntheticMethod(methodName, Opcodes.ACC_PUBLIC, ClassHelper.VOID_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
block = new BlockStatement();
if (isStatic) {
setPropertySetterDispatcher(block, new ClassExpression(node.getOuterClass()), parameters);
} else {
block.addStatement(new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
getThis(mv, classInternalName, outerClassDescriptor, outerClassInternalName);
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$set$" + objectDistance, "(Ljava/lang/String;Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
}
}));
}
method.setCode(block);
// add property setter dispatcher
parameters = new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name") };
methodName = "propertyMissing";
if (isStatic)
addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
method = node.addSyntheticMethod(methodName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
block = new BlockStatement();
if (isStatic) {
setPropertyGetterDispatcher(block, new ClassExpression(node.getOuterClass()), parameters);
} else {
block.addStatement(new BytecodeSequence(new BytecodeInstruction() {
public void visit(MethodVisitor mv) {
getThis(mv, classInternalName, outerClassDescriptor, outerClassInternalName);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$get$" + objectDistance, "(Ljava/lang/String;)Ljava/lang/Object;", false);
mv.visitInsn(ARETURN);
}
}));
}
method.setCode(block);
}
use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.
the class InnerClassCompletionVisitor method visitClass.
@Override
public void visitClass(ClassNode node) {
this.classNode = node;
thisField = null;
InnerClassNode innerClass = null;
if (!node.isEnum() && !node.isInterface() && node instanceof InnerClassNode) {
innerClass = (InnerClassNode) node;
thisField = innerClass.getField("this$0");
if (innerClass.getVariableScope() == null && innerClass.getDeclaredConstructors().isEmpty()) {
// add dummy constructor
innerClass.addConstructor(ACC_PUBLIC, Parameter.EMPTY_ARRAY, null, null);
}
}
if (node.isEnum() || node.isInterface())
return;
// use Iterator.hasNext() to check for available inner classes
if (node.getInnerClasses().hasNext())
addDispatcherMethods(node);
if (innerClass == null)
return;
super.visitClass(node);
addDefaultMethods(innerClass);
}
Aggregations