private void completeEnum(ClassNode enumClass) { boolean isAic = isAnonymousInnerClass(enumClass); if (enumClass.getDeclaredConstructors().size() == 0) { addImplicitConstructors(enumClass, isAic); } for (ConstructorNode ctor : enumClass.getDeclaredConstructors()) { transformConstructor(ctor, isAic); } }
private boolean validateConstructors(ClassNode cNode) { if (cNode.getDeclaredConstructors().size() != 0) { // TODO: allow constructors which only call provided constructor? addError( "Explicit constructors not allowed for " + ImmutableASTTransformation.MY_TYPE_NAME + " class: " + cNode.getNameWithoutPackage(), cNode.getDeclaredConstructors().get(0)); } return true; }
/** * Obtains the default constructor for the given class node. * * @param classNode The class node * @return The default constructor or null if there isn't one */ public static ConstructorNode getDefaultConstructor(ClassNode classNode) { for (ConstructorNode cons : classNode.getDeclaredConstructors()) { if (cons.getParameters().length == 0) { return cons; } } return null; }
/** * Finds a constructor for the given class node and parameter types * * @param classNode The class node * @param constructorParams The parameter types * @return The located constructor or null */ public static ConstructorNode findConstructor( ClassNode classNode, Parameter[] constructorParams) { List<ConstructorNode> declaredConstructors = classNode.getDeclaredConstructors(); for (ConstructorNode declaredConstructor : declaredConstructors) { if (parametersEqual(constructorParams, declaredConstructor.getParameters())) { return declaredConstructor; } } return null; }
private void printConstructors(PrintWriter out, ClassNode classNode) { @SuppressWarnings("unchecked") List<ConstructorNode> constrs = (List<ConstructorNode>) constructors.clone(); if (constrs != null) { constrs.addAll(classNode.getDeclaredConstructors()); for (ConstructorNode constr : constrs) { printConstructor(out, classNode, constr); } } }
static { final List<ConstructorNode> declaredConstructors = INTRANGE_TYPE.getDeclaredConstructors(); ConstructorNode target = null; for (ConstructorNode constructor : declaredConstructors) { final Parameter[] parameters = constructor.getParameters(); if (parameters.length == 3 && ClassHelper.boolean_TYPE.equals(parameters[0].getOriginType())) { target = constructor; break; } } INTRANGE_CTOR = target; }
public void writeClosure(ClosureExpression expression) { CompileStack compileStack = controller.getCompileStack(); MethodVisitor mv = controller.getMethodVisitor(); ClassNode classNode = controller.getClassNode(); AsmClassGenerator acg = controller.getAcg(); // generate closure as public class to make sure it can be properly invoked by classes of the // Groovy runtime without circumventing JVM access checks (see CachedMethod for example). ClassNode closureClass = getOrAddClosureClass(expression, ACC_PUBLIC); String closureClassinternalName = BytecodeHelper.getClassInternalName(closureClass); List constructors = closureClass.getDeclaredConstructors(); ConstructorNode node = (ConstructorNode) constructors.get(0); Parameter[] localVariableParams = node.getParameters(); mv.visitTypeInsn(NEW, closureClassinternalName); mv.visitInsn(DUP); if (controller.isStaticMethod() || compileStack.isInSpecialConstructorCall()) { (new ClassExpression(classNode)).visit(acg); (new ClassExpression(controller.getOutermostClass())).visit(acg); } else { mv.visitVarInsn(ALOAD, 0); controller.getOperandStack().push(ClassHelper.OBJECT_TYPE); loadThis(); } // now let's load the various parameters we're passing // we start at index 2 because the first variable we pass // is the owner instance and at this point it is already // on the stack for (int i = 2; i < localVariableParams.length; i++) { Parameter param = localVariableParams[i]; String name = param.getName(); loadReference(name, controller); if (param.getNodeMetaData(ClosureWriter.UseExistingReference.class) == null) { param.setNodeMetaData(ClosureWriter.UseExistingReference.class, Boolean.TRUE); } } // we may need to pass in some other constructors // cv.visitMethodInsn(INVOKESPECIAL, innerClassinternalName, "<init>", prototype + ")V"); mv.visitMethodInsn( INVOKESPECIAL, closureClassinternalName, "<init>", BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, localVariableParams), false); controller.getOperandStack().replace(ClassHelper.CLOSURE_TYPE, localVariableParams.length); }
private Parameter[] selectAccessibleConstructorFromSuper(ConstructorNode node) { ClassNode type = node.getDeclaringClass(); ClassNode superType = type.getSuperClass(); for (ConstructorNode c : superType.getDeclaredConstructors()) { // Only look at things we can actually call if (c.isPublic() || c.isProtected()) { return c.getParameters(); } } // fall back for parameterless constructor if (superType.isPrimaryClassNode()) { return Parameter.EMPTY_ARRAY; } return null; }
/** Add map and no-arg constructor or mirror those of the superclass (i.e. base enum). */ private void addImplicitConstructors(ClassNode enumClass, boolean aic) { if (aic) { ClassNode sn = enumClass.getSuperClass(); List<ConstructorNode> sctors = new ArrayList<ConstructorNode>(sn.getDeclaredConstructors()); if (sctors.size() == 0) { addMapConstructors(enumClass, false); } else { for (ConstructorNode constructorNode : sctors) { ConstructorNode init = new ConstructorNode( Opcodes.ACC_PUBLIC, constructorNode.getParameters(), ClassNode.EMPTY_ARRAY, new BlockStatement()); enumClass.addConstructor(init); } } } else { addMapConstructors(enumClass, false); } }