public static ClassNode getFurthestParent(ClassNode classNode) { ClassNode parent = classNode.getSuperClass(); while (parent != null && !getFullName(parent).equals("java.lang.Object")) { classNode = parent; parent = parent.getSuperClass(); } return classNode; }
public static ClassNode getFurthestUnresolvedParent(ClassNode classNode) { ClassNode parent = classNode.getSuperClass(); while (parent != null && !getFullName(parent).equals("java.lang.Object") && !parent.isResolved() && !Modifier.isAbstract(parent.getModifiers())) { classNode = parent; parent = parent.getSuperClass(); } return classNode; }
public static boolean hasOrInheritsProperty(ClassNode classNode, String propertyName) { if (hasProperty(classNode, propertyName)) { return true; } ClassNode parent = classNode.getSuperClass(); while (parent != null && !getFullName(parent).equals("java.lang.Object")) { if (hasProperty(parent, propertyName)) { return true; } parent = parent.getSuperClass(); } return false; }
/** * Snoops through the declaring class and all parents looking for methods * * <ul> * <li><code>public String getMessage(java.lang.String)</code> * <li><code>public String getMessage(java.lang.String, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[])</code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[], java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.List)</code> * <li><code>public String getMessage(java.lang.String, java.util.List, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.util.Map)</code> * <li><code>public String getMessage(java.lang.String, java.util.Map, java.util.Locale)</code> * <li><code>public String getMessage(java.lang.String, java.lang.String)</code> * <li><code>public String getMessage(java.lang.String, java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.lang.Object[], java.lang.String) * </code> * <li><code> * public String getMessage(java.lang.String, java.lang.Object[], java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.List, java.lang.String)</code> * <li><code> * public String getMessage(java.lang.String, java.util.List, java.lang.String, java.util.Locale) * </code> * <li><code>public String getMessage(java.lang.String, java.util.Map, java.lang.String)</code> * <li><code> * public String getMessage(java.lang.String, java.util.Map, java.lang.String, java.util.Locale) * </code> * </ul> * * If any are defined all must be defined or a compilation error results. * * @param declaringClass the class to search * @param sourceUnit the source unit, for error reporting. {@code @NotNull}. * @return true if property change support should be added */ protected static boolean needsMessageSource(ClassNode declaringClass, SourceUnit sourceUnit) { boolean found = false; ClassNode consideredClass = declaringClass; while (consideredClass != null) { for (MethodNode method : consideredClass.getMethods()) { // just check length, MOP will match it up found = method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 1; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 2; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 3; found |= method.getName().equals(METHOD_GET_MESSAGE) && method.getParameters().length == 4; if (found) return false; } consideredClass = consideredClass.getSuperClass(); } if (found) { sourceUnit .getErrorCollector() .addErrorAndContinue( new SimpleMessage( "@MessageSourceAware cannot be processed on " + declaringClass.getName() + " because some but not all of variants of getMessage() were declared in the current class or super classes.", sourceUnit)); return false; } return true; }
@SuppressWarnings("rawtypes") public static boolean implementsOrInheritsZeroArgMethod( ClassNode classNode, String methodName, List ignoreClasses) { if (implementsZeroArgMethod(classNode, methodName)) { return true; } ClassNode parent = classNode.getSuperClass(); while (parent != null && !getFullName(parent).equals("java.lang.Object")) { if (!ignoreClasses.contains(parent) && implementsZeroArgMethod(parent, methodName)) { return true; } parent = parent.getSuperClass(); } return false; }
public boolean addGeneratedClosureConstructorCall(ConstructorCallExpression call) { ClassNode classNode = controller.getClassNode(); if (!classNode.declaresInterface(ClassHelper.GENERATED_CLOSURE_Type)) return false; AsmClassGenerator acg = controller.getAcg(); OperandStack operandStack = controller.getOperandStack(); MethodVisitor mv = controller.getMethodVisitor(); mv.visitVarInsn(ALOAD, 0); ClassNode callNode = classNode.getSuperClass(); TupleExpression arguments = (TupleExpression) call.getArguments(); if (arguments.getExpressions().size() != 2) throw new GroovyBugError( "expected 2 arguments for closure constructor super call, but got" + arguments.getExpressions().size()); arguments.getExpression(0).visit(acg); operandStack.box(); arguments.getExpression(1).visit(acg); operandStack.box(); // TODO: replace with normal String, p not needed Parameter p = new Parameter(ClassHelper.OBJECT_TYPE, "_p"); String descriptor = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, new Parameter[] {p, p}); mv.visitMethodInsn( INVOKESPECIAL, BytecodeHelper.getClassInternalName(callNode), "<init>", descriptor, false); operandStack.remove(2); return true; }
@Override public void visitConstructorCallExpression(final ConstructorCallExpression call) { super.visitConstructorCallExpression(call); MethodNode target = (MethodNode) call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET); if (target == null && call.getLineNumber() > 0) { addError("Target constructor for constructor call expression hasn't been set", call); } else { if (target == null) { // try to find a target ArgumentListExpression argumentListExpression = InvocationWriter.makeArgumentList(call.getArguments()); List<Expression> expressions = argumentListExpression.getExpressions(); ClassNode[] args = new ClassNode[expressions.size()]; for (int i = 0; i < args.length; i++) { args[i] = typeChooser.resolveType(expressions.get(i), classNode); } MethodNode constructor = findMethodOrFail( call, call.isSuperCall() ? classNode.getSuperClass() : classNode, "<init>", args); call.putNodeMetaData(DIRECT_METHOD_CALL_TARGET, constructor); target = constructor; } } if (target != null) { memorizeInitialExpressions(target); } }
private int getSuperClassCount(ClassNode element) { int count = 0; while (element != null) { count++; element = element.getSuperClass(); } return count; }
/** * This methods creates a list of all methods with this name of the current class and of all super * classes * * @return the methods list * @see #getDeclaredMethods(String) */ public List<MethodNode> getMethods(String name) { List<MethodNode> answer = new ArrayList<MethodNode>(); ClassNode node = this; while (node != null) { answer.addAll(node.getDeclaredMethods(name)); node = node.getSuperClass(); } return answer; }
/** * Finds a field matching the given name in this class or a parent class. * * @param name the name of the field of interest * @return the method matching the given name and parameters or null */ public FieldNode getField(String name) { ClassNode node = this; while (node != null) { FieldNode fn = node.getDeclaredField(name); if (fn != null) return fn; node = node.getSuperClass(); } return null; }
private void changeBaseScriptTypeFromClass(final ClassNode parent, final AnnotationNode node) { // Expression value = node.getMember("value"); // if (!(value instanceof ClassExpression)) { // addError("Annotation " + MY_TYPE_NAME + " member 'value' should be a class // literal.", value); // return; // } changeBaseScriptType(parent, parent, parent.getSuperClass()); }
public static List<MethodNode> getAllMethods(ClassNode type) { ClassNode node = type; List<MethodNode> result = new ArrayList<MethodNode>(); while (node != null) { result.addAll(node.getMethods()); node = node.getSuperClass(); } return result; }
private static boolean classNodeUsesReferences(ClassNode classNode) { boolean ret = classNode.getSuperClass() == ClassHelper.CLOSURE_TYPE; if (ret) return ret; if (classNode instanceof InnerClassNode) { InnerClassNode inner = (InnerClassNode) classNode; return inner.isAnonymous(); } return false; }
public static List<PropertyNode> getAllProperties(ClassNode type) { ClassNode node = type; List<PropertyNode> result = new ArrayList<PropertyNode>(); while (node != null) { result.addAll(node.getProperties()); node = node.getSuperClass(); } return result; }
private void checkClassForOverwritingFinal(ClassNode cn) { ClassNode superCN = cn.getSuperClass(); if (superCN == null) return; if (!isFinal(superCN.getModifiers())) return; StringBuilder msg = new StringBuilder(); msg.append("You are not allowed to overwrite the final "); msg.append(getDescription(superCN)); msg.append("."); addError(msg.toString(), cn); }
private boolean hasStaticProperty(ClassNode staticImportType, String propName) { ClassNode classNode = staticImportType; while (classNode != null) { for (PropertyNode pn : classNode.getProperties()) { if (pn.getName().equals(propName) && pn.isStatic()) return true; } classNode = classNode.getSuperClass(); } return false; }
/** * @param classNode the class node for the interface * @return true if this class or any base class implements the given interface */ public boolean implementsInterface(ClassNode classNode) { ClassNode node = redirect(); do { if (node.declaresInterface(classNode)) { return true; } node = node.getSuperClass(); } while (node != null); return false; }
/** * Determines if the class or interface represented by the superClass argument is either the same * as, or is a superclass or superinterface of, the class or interface represented by the * specified subClass parameter. * * @param superClass The super class to check * @param childClass The sub class the check * @return true if the childClass is either equal to or a sub class of the specified superClass */ private static boolean isAssignableFrom(ClassNode superClass, ClassNode childClass) { ClassNode currentSuper = childClass; while (currentSuper != null) { if (currentSuper.equals(superClass)) { return true; } currentSuper = currentSuper.getSuperClass(); } return false; }
private void createKeyConstructor() { annotatedClass.addConstructor( ACC_PUBLIC, params(param(STRING_TYPE, "key")), NO_EXCEPTIONS, block( ASTHelper.isDSLObject(annotatedClass.getSuperClass()) ? ctorSuperS(args("key")) : ctorSuperS(), assignS(propX(varX("this"), keyField.getName()), varX("key")))); }
private void checkMethodForWeakerAccessPrivileges(MethodNode mn, ClassNode cn) { Parameter[] params = mn.getParameters(); for (MethodNode superMethod : cn.getSuperClass().getMethods(mn.getName())) { Parameter[] superParams = superMethod.getParameters(); if (!hasEqualParameterTypes(params, superParams)) continue; if ((mn.isPrivate() && !superMethod.isPrivate()) || (mn.isProtected() && superMethod.isPublic())) { addWeakerAccessError(cn, mn, params, superMethod); return; } } }
private void checkMethodsForOverridingFinal(ClassNode cn) { for (MethodNode method : cn.getMethods()) { Parameter[] params = method.getParameters(); for (MethodNode superMethod : cn.getSuperClass().getMethods(method.getName())) { Parameter[] superParams = superMethod.getParameters(); if (!hasEqualParameterTypes(params, superParams)) continue; if (!superMethod.isFinal()) break; addInvalidUseOfFinalError(method, params, superMethod.getDeclaringClass()); return; } } }
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; }
private void changeBaseScriptType( final AnnotatedNode parent, final ClassNode cNode, final ClassNode baseScriptType) { if (!cNode.isScriptBody()) { addError("Annotation " + MY_TYPE_NAME + " can only be used within a Script.", parent); return; } if (!baseScriptType.isScript()) { addError( "Declared type " + baseScriptType + " does not extend groovy.lang.Script class!", parent); return; } cNode.setSuperClass(baseScriptType); // Method in base script that will contain the script body code. MethodNode runScriptMethod = ClassHelper.findSAM(baseScriptType); // If they want to use a name other than than "run", then make the change. if (isCustomScriptBodyMethod(runScriptMethod)) { MethodNode defaultMethod = cNode.getDeclaredMethod("run", Parameter.EMPTY_ARRAY); // GROOVY-6706: Sometimes an NPE is thrown here. // The reason is that our transform is getting called more than once sometimes. if (defaultMethod != null) { cNode.removeMethod(defaultMethod); MethodNode methodNode = new MethodNode( runScriptMethod.getName(), runScriptMethod.getModifiers() & ~ACC_ABSTRACT, runScriptMethod.getReturnType(), runScriptMethod.getParameters(), runScriptMethod.getExceptions(), defaultMethod.getCode()); // The AST node metadata has the flag that indicates that this method is a script body. // It may also be carrying data for other AST transforms. methodNode.copyNodeMetaData(defaultMethod); cNode.addMethod(methodNode); } } // If the new script base class does not have a contextual constructor (g.l.Binding), then we // won't either. // We have to do things this way (and rely on just default constructors) because the logic that // generates // the constructors for our script class have already run. if (cNode.getSuperClass().getDeclaredConstructor(CONTEXT_CTOR_PARAMETERS) == null) { ConstructorNode orphanedConstructor = cNode.getDeclaredConstructor(CONTEXT_CTOR_PARAMETERS); cNode.removeConstructor(orphanedConstructor); } }
public static List<FieldNode> getSuperNonPropertyFields(ClassNode cNode) { final List<FieldNode> result; if (cNode == ClassHelper.OBJECT_TYPE) { result = new ArrayList<FieldNode>(); } else { result = getSuperNonPropertyFields(cNode.getSuperClass()); } for (FieldNode fNode : cNode.getFields()) { if (!fNode.isStatic() && cNode.getProperty(fNode.getName()) == null) { result.add(fNode); } } return result; }
public static List<FieldNode> getSuperPropertyFields(ClassNode cNode) { final List<FieldNode> result; if (cNode == ClassHelper.OBJECT_TYPE) { result = new ArrayList<FieldNode>(); } else { result = getSuperPropertyFields(cNode.getSuperClass()); } for (PropertyNode pNode : cNode.getProperties()) { if (!pNode.isStatic()) { result.add(pNode.getField()); } } return result; }
/** * @param type the ClassNode of interest * @return true if this node is derived from the given ClassNode */ public boolean isDerivedFrom(ClassNode type) { if (this.equals(ClassHelper.VOID_TYPE)) { return type.equals(ClassHelper.VOID_TYPE); } if (type.equals(ClassHelper.OBJECT_TYPE)) return true; ClassNode node = this; while (node != null) { if (type.equals(node)) { return true; } node = node.getSuperClass(); } return false; }
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); } } }
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; }
public MethodNode tryFindPossibleMethod(String name, Expression arguments) { int count = 0; if (arguments instanceof TupleExpression) { TupleExpression tuple = (TupleExpression) arguments; // TODO this won't strictly be true when using list expansion in argument calls count = tuple.getExpressions().size(); } else return null; MethodNode res = null; ClassNode node = this; TupleExpression args = (TupleExpression) arguments; do { for (MethodNode method : node.getMethods(name)) { if (method.getParameters().length == count) { boolean match = true; for (int i = 0; i != count; ++i) if (!args.getType().isDerivedFrom(method.getParameters()[i].getType())) { match = false; break; } if (match) { if (res == null) res = method; else { if (res.getParameters().length != count) return null; if (node.equals(this)) return null; match = true; for (int i = 0; i != count; ++i) if (!res.getParameters()[i].getType().equals(method.getParameters()[i].getType())) { match = false; break; } if (!match) return null; } } } } node = node.getSuperClass(); } while (node != null); return res; }
boolean makeGetField( final Expression receiver, final ClassNode receiverType, final String fieldName, final boolean implicitThis, final boolean samePackage) { FieldNode field = receiverType.getField(fieldName); // direct access is allowed if we are in the same class as the declaring class // or we are in an inner class if (field != null && isDirectAccessAllowed(field, controller.getClassNode(), samePackage)) { CompileStack compileStack = controller.getCompileStack(); MethodVisitor mv = controller.getMethodVisitor(); if (field.isStatic()) { mv.visitFieldInsn( GETSTATIC, BytecodeHelper.getClassInternalName(field.getOwner()), fieldName, BytecodeHelper.getTypeDescription(field.getOriginType())); controller.getOperandStack().push(field.getOriginType()); } else { if (implicitThis) { compileStack.pushImplicitThis(implicitThis); } receiver.visit(controller.getAcg()); if (implicitThis) compileStack.popImplicitThis(); if (!controller.getOperandStack().getTopOperand().isDerivedFrom(field.getOwner())) { mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(field.getOwner())); } mv.visitFieldInsn( GETFIELD, BytecodeHelper.getClassInternalName(field.getOwner()), fieldName, BytecodeHelper.getTypeDescription(field.getOriginType())); } controller.getOperandStack().replace(field.getOriginType()); return true; } ClassNode superClass = receiverType.getSuperClass(); if (superClass != null) { return makeGetField(receiver, superClass, fieldName, implicitThis, false); } return false; }