private int getSuperInterfaceCount(ClassNode element) { int count = 1; ClassNode[] interfaces = element.getInterfaces(); for (ClassNode anInterface : interfaces) { count = Math.max(count, getSuperInterfaceCount(anInterface) + 1); } return count; }
public static Set<ClassNode> getInterfacesAndSuperInterfaces(ClassNode type) { Set<ClassNode> res = new HashSet<ClassNode>(); if (type.isInterface()) { res.add(type); return res; } ClassNode next = type; while (next != null) { Collections.addAll(res, next.getInterfaces()); next = next.getSuperClass(); } return res; }
public static String getGenericsSignature(ClassNode node) { if (!usesGenericsInClassSignature(node)) return null; GenericsType[] genericsTypes = node.getGenericsTypes(); StringBuffer ret = new StringBuffer(100); getGenericsTypeSpec(ret, genericsTypes); GenericsType extendsPart = new GenericsType(node.getUnresolvedSuperClass(false)); writeGenericsBounds(ret, extendsPart, true); ClassNode[] interfaces = node.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { GenericsType interfacePart = new GenericsType(interfaces[i]); writeGenericsBounds(ret, interfacePart, false); } return ret.toString(); }
private static boolean usesGenericsInClassSignature(ClassNode node) { if (!node.isUsingGenerics()) return false; if (hasGenerics(node)) return true; ClassNode sclass = node.getUnresolvedSuperClass(false); if (sclass.isUsingGenerics()) return true; ClassNode[] interfaces = node.getInterfaces(); if (interfaces != null) { for (int i = 0; i < interfaces.length; i++) { if (interfaces[i].isUsingGenerics()) return true; } } return false; }
/** * Interface class nodes retrieved from {@link org.codehaus.groovy.ast.ClassNode#getInterfaces()} * or {@link org.codehaus.groovy.ast.ClassNode#getAllInterfaces()} are returned with generic type * arguments. This method allows returning a parameterized interface given the parameterized class * node which implements this interface. * * @param hint the class node where generics types are parameterized * @param target the interface we want to parameterize generics types * @return a parameterized interface class node */ public static ClassNode parameterizeType(final ClassNode hint, final ClassNode target) { ClassNode interfaceFromClassNode = null; if (hint.equals(target)) interfaceFromClassNode = hint; if (ClassHelper.OBJECT_TYPE.equals(target) && target.isUsingGenerics() && target.getGenericsTypes() != null && target.getGenericsTypes()[0].isPlaceholder()) { // Object<T> return ClassHelper.getWrapper(hint); } if (interfaceFromClassNode == null) { ClassNode[] interfaces = hint.getInterfaces(); for (ClassNode node : interfaces) { if (node.equals(target)) { interfaceFromClassNode = node; break; } else if (node.implementsInterface(target)) { // ex: classNode = LinkedList<A> , node=List<E> , anInterface = Iterable<T> return parameterizeType(parameterizeType(hint, node), target); } } } if (interfaceFromClassNode == null && hint.getUnresolvedSuperClass() != null) { return parameterizeType(hint.getUnresolvedSuperClass(), target); } if (interfaceFromClassNode == null) { // return target; interfaceFromClassNode = hint; } Map<String, GenericsType> parameters = new HashMap<String, GenericsType>(); extractPlaceholders(hint, parameters); ClassNode node = target.getPlainNodeReference(); GenericsType[] interfaceGTs = interfaceFromClassNode.getGenericsTypes(); if (interfaceGTs == null) return target; GenericsType[] types = new GenericsType[interfaceGTs.length]; for (int i = 0; i < interfaceGTs.length; i++) { GenericsType interfaceGT = interfaceGTs[i]; types[i] = interfaceGT; if (interfaceGT.isPlaceholder()) { String name = interfaceGT.getName(); if (parameters.containsKey(name)) { types[i] = parameters.get(name); } } } node.setGenericsTypes(types); return node; }
private void checkImplementsAndExtends(ClassNode node) { ClassNode cn = node.getSuperClass(); if (cn.isInterface() && !node.isInterface()) { addError( "You are not allowed to extend the " + getDescription(cn) + ", use implements instead.", node); } for (ClassNode anInterface : node.getInterfaces()) { cn = anInterface; if (!cn.isInterface()) { addError( "You are not allowed to implement the " + getDescription(cn) + ", use extends instead.", node); } } }
// GroovyClassVisitor interface // ------------------------------------------------------------------------- public void visitClass(ClassNode classNode) { try { this.classNode = classNode; this.internalClassName = BytecodeHelper.getClassInternalName(classNode); // System.out.println("Generating class: " + classNode.getName()); this.internalBaseClassName = BytecodeHelper.getClassInternalName(classNode.getSuperClass()); cv.visit( Opcodes.V1_3, classNode.getModifiers(), internalClassName, (String) null, internalBaseClassName, BytecodeHelper.getClassInternalNames(classNode.getInterfaces())); classNode.visitContents(this); for (Iterator iter = innerClasses.iterator(); iter.hasNext(); ) { ClassNode innerClass = (ClassNode) iter.next(); ClassNode innerClassType = innerClass; String innerClassInternalName = BytecodeHelper.getClassInternalName(innerClassType); String outerClassName = internalClassName; // default for inner classes MethodNode enclosingMethod = innerClass.getEnclosingMethod(); if (enclosingMethod != null) { // local inner classes do not specify the outer class name outerClassName = null; } cv.visitInnerClass( innerClassInternalName, outerClassName, innerClassType.getName(), innerClass.getModifiers()); } cv.visitEnd(); } catch (GroovyRuntimeException e) { e.setModule(classNode.getModule()); throw e; } }
private void printClassContents(PrintWriter out, ClassNode classNode) throws FileNotFoundException { if (classNode instanceof InnerClassNode && ((InnerClassNode) classNode).isAnonymous()) { // if it is an anonymous inner class, don't generate the stub code for it. return; } try { Verifier verifier = new Verifier() { public void addCovariantMethods(ClassNode cn) {} protected void addTimeStamp(ClassNode node) {} protected void addInitialization(ClassNode node) {} protected void addPropertyMethod(MethodNode method) { doAddMethod(method); } protected void addReturnIfNeeded(MethodNode node) {} protected void addMethod( ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code) { doAddMethod( new MethodNode(name, modifiers, returnType, parameters, exceptions, code)); } protected void addConstructor( Parameter[] newParams, ConstructorNode ctor, Statement code, ClassNode node) { if (code instanceof ExpressionStatement) { // GROOVY-4508 Statement temp = code; code = new BlockStatement(); ((BlockStatement) code).addStatement(temp); } ConstructorNode ctrNode = new ConstructorNode(ctor.getModifiers(), newParams, ctor.getExceptions(), code); ctrNode.setDeclaringClass(node); constructors.add(ctrNode); } protected void addDefaultParameters(DefaultArgsAction action, MethodNode method) { final Parameter[] parameters = method.getParameters(); final Expression[] saved = new Expression[parameters.length]; for (int i = 0; i < parameters.length; i++) { if (parameters[i].hasInitialExpression()) saved[i] = parameters[i].getInitialExpression(); } super.addDefaultParameters(action, method); for (int i = 0; i < parameters.length; i++) { if (saved[i] != null) parameters[i].setInitialExpression(saved[i]); } } private void doAddMethod(MethodNode method) { String sig = method.getTypeDescriptor(); if (propertyMethodsWithSigs.containsKey(sig)) return; propertyMethods.add(method); propertyMethodsWithSigs.put(sig, method); } @Override protected void addDefaultConstructor(ClassNode node) { // not required for stub generation } }; verifier.visitClass(classNode); currentModule = classNode.getModule(); boolean isInterface = classNode.isInterface(); boolean isEnum = (classNode.getModifiers() & Opcodes.ACC_ENUM) != 0; boolean isAnnotationDefinition = classNode.isAnnotationDefinition(); printAnnotations(out, classNode); printModifiers( out, classNode.getModifiers() & ~(isInterface ? Opcodes.ACC_ABSTRACT : 0) & ~(isEnum ? Opcodes.ACC_FINAL : 0)); if (isInterface) { if (isAnnotationDefinition) { out.print("@"); } out.print("interface "); } else if (isEnum) { out.print("enum "); } else { out.print("class "); } String className = classNode.getNameWithoutPackage(); if (classNode instanceof InnerClassNode) className = className.substring(className.lastIndexOf("$") + 1); out.println(className); printGenericsBounds(out, classNode, true); ClassNode superClass = classNode.getUnresolvedSuperClass(false); if (!isInterface && !isEnum) { out.print(" extends "); printType(out, superClass); } ClassNode[] interfaces = classNode.getInterfaces(); if (interfaces != null && interfaces.length > 0 && !isAnnotationDefinition) { if (isInterface) { out.println(" extends"); } else { out.println(" implements"); } for (int i = 0; i < interfaces.length - 1; ++i) { out.print(" "); printType(out, interfaces[i]); out.print(","); } out.print(" "); printType(out, interfaces[interfaces.length - 1]); } out.println(" {"); printFields(out, classNode); printMethods(out, classNode, isEnum); for (Iterator<InnerClassNode> inner = classNode.getInnerClasses(); inner.hasNext(); ) { // GROOVY-4004: Clear the methods from the outer class so that they don't get duplicated in // inner ones propertyMethods.clear(); propertyMethodsWithSigs.clear(); constructors.clear(); printClassContents(out, inner.next()); } out.println("}"); } finally { propertyMethods.clear(); propertyMethodsWithSigs.clear(); constructors.clear(); currentModule = null; } }