public boolean isResolved() { if (clazz != null) return true; if (redirect != null) return redirect.isResolved(); return componentType != null && componentType.isResolved(); }
private static Annotation getTransformClassAnnotation(ClassNode annotatedType) { if (!annotatedType.isResolved()) return null; for (Annotation ann : annotatedType.getTypeClass().getAnnotations()) { // because compiler clients are free to choose any GroovyClassLoader for // resolving ClassNodeS such as annotatedType, we have to compare by name, // and cannot cast the return value to GroovyASTTransformationClass if (ann.annotationType().getName().equals(GroovyASTTransformationClass.class.getName())) { return ann; } } return null; }
/** * This method returns the list of methods named against the supplied parameter that * are defined on the specified receiver, but it will also add "non existing" methods * that will be generated afterwards by the compiler, for example if a method is using * default values and that the specified class node isn't compiled yet. * * @param receiver the receiver where to find methods * @param name the name of the methods to return * @return the methods that are defined on the receiver completed with stubs for future methods */ protected List<MethodNode> findMethodsWithGenerated(ClassNode receiver, String name) { List<MethodNode> methods = receiver.getMethods(name); if (methods.isEmpty() || receiver.isResolved()) return methods; List<MethodNode> result = addGeneratedMethods(receiver, methods); return result; }
private static boolean hasClosureMember(AnnotationNode annotation) { Map<String, Expression> members = annotation.getMembers(); for (Map.Entry<String, Expression> member : members.entrySet()) { if (member.getValue() instanceof ClosureExpression) return true; if (member.getValue() instanceof ClassExpression) { ClassExpression classExpression = (ClassExpression) member.getValue(); Class<?> typeClass = classExpression.getType().isResolved() ? classExpression.getType().redirect().getTypeClass() : null; if (typeClass != null && GeneratedClosure.class.isAssignableFrom(typeClass)) return true; } } return false; }
public void generateClass(ClassNode classNode) throws FileNotFoundException { if (requireSuperResolved && !classNode.getSuperClass().isResolved()) { return;
private static Expression findStaticMethod(ClassNode staticImportType, String methodName, Expression args) { if (staticImportType.isPrimaryClassNode() || staticImportType.isResolved()) { if (staticImportType.hasPossibleStaticMethod(methodName, args)) { return new StaticMethodCallExpression(staticImportType, methodName, args); } } return null; }
/** * Returns the concrete class this classnode relates to. However, this method * is inherently unsafe as it may return null depending on the compile phase you are * using. AST transformations should never use this method directly, but rather obtain * a new class node using {@link #getPlainNodeReference()}. * @return the class this classnode relates to. May return null. */ public Class getTypeClass(){ if (clazz != null) return clazz; if (redirect != null) return redirect.getTypeClass(); ClassNode component = redirect().componentType; if (component!=null && component.isResolved()){ return Array.newInstance(component.getTypeClass(), 0).getClass(); } throw new GroovyBugError("ClassNode#getTypeClass for "+getName()+" is called before the type class is set "); }
/** * @return the ClassNode of the super class of this type */ public ClassNode getSuperClass() { if (!lazyInitDone && !isResolved()) { throw new GroovyBugError("ClassNode#getSuperClass for "+getName()+" called before class resolving"); } ClassNode sn = redirect().getUnresolvedSuperClass(); if (sn!=null) sn=sn.redirect(); return sn; }
public void visitAnnotations(AnnotatedNode node) { List<AnnotationNode> annotations = node.getAnnotations(); if (annotations.isEmpty()) return; Map<String, AnnotationNode> tmpAnnotations = new HashMap<String, AnnotationNode>(); ClassNode annType; for (AnnotationNode an : annotations) { // skip built-in properties if (an.isBuiltIn()) continue; annType = an.getClassNode(); resolveOrFail(annType, ", unable to find class for annotation", an); for (Map.Entry<String, Expression> member : an.getMembers().entrySet()) { Expression newValue = transform(member.getValue()); Expression adjusted = transformInlineConstants(newValue); member.setValue(adjusted); checkAnnotationMemberValue(adjusted); } if (annType.isResolved()) { Class annTypeClass = annType.getTypeClass(); Retention retAnn = (Retention) annTypeClass.getAnnotation(Retention.class); if (retAnn != null && retAnn.value().equals(RetentionPolicy.RUNTIME) && !isRepeatable(annTypeClass)) { // remember runtime/non-repeatable annos (auto collecting of Repeatable annotations is handled elsewhere) AnnotationNode anyPrevAnnNode = tmpAnnotations.put(annTypeClass.getName(), an); if (anyPrevAnnNode != null) { addError("Cannot specify duplicate annotation on the same member : " + annType.getName(), an); } } } } }
private static Expression findStaticField(ClassNode staticImportType, String fieldName) { if (staticImportType.isPrimaryClassNode() || staticImportType.isResolved()) { FieldNode field = getField(staticImportType, fieldName); if (field != null && field.isStatic()) return new PropertyExpression(new ClassExpression(staticImportType), fieldName); } return null; }
private static void visitDeprecation(AnnotatedNode node, AnnotationNode visited) { if (visited.getClassNode().isResolved() && visited.getClassNode().getName().equals("java.lang.Deprecated")) { if (node instanceof MethodNode) { MethodNode mn = (MethodNode) node; mn.setModifiers(mn.getModifiers() | Opcodes.ACC_DEPRECATED); } else if (node instanceof FieldNode) { FieldNode fn = (FieldNode) node; fn.setModifiers(fn.getModifiers() | Opcodes.ACC_DEPRECATED); } else if (node instanceof ClassNode) { ClassNode cn = (ClassNode) node; cn.setModifiers(cn.getModifiers() | Opcodes.ACC_DEPRECATED); } } }
private void visitOverride(AnnotatedNode node, AnnotationNode visited) { ClassNode annotationClassNode = visited.getClassNode(); if (annotationClassNode.isResolved() && annotationClassNode.getName().equals("java.lang.Override")) { if (node instanceof MethodNode && !Boolean.TRUE.equals(node.getNodeMetaData(Verifier.DEFAULT_PARAMETER_GENERATED))) { boolean override = false; MethodNode origMethod = (MethodNode) node; ClassNode cNode = origMethod.getDeclaringClass(); if (origMethod.hasDefaultValue()) { List<MethodNode> variants = cNode.getDeclaredMethods(origMethod.getName()); for (MethodNode m : variants) { if (m.getAnnotations().contains(visited) && isOverrideMethod(m)) { override = true; break; } } } else { override = isOverrideMethod(origMethod); } if (!override) { addError("Method '" + origMethod.getName() + "' from class '" + cNode.getName() + "' does not override " + "method from its superclass or interfaces but is annotated with @Override.", visited); } } } }
ClassNode declaringClass = mn.getDeclaringClass(); ClassNode cn = declaringClass.getOuterClass(); if (cn == null && declaringClass.isResolved()) {
/** * Search for classes using ASM decompiler */ private LookupResult findDecompiled(String name, CompilationUnit compilationUnit, GroovyClassLoader loader) { ClassNode node = ClassHelper.make(name); if (node.isResolved()) { return new LookupResult(null, node); } DecompiledClassNode asmClass = null; String fileName = name.replace('.', '/') + ".class"; URL resource = loader.getResource(fileName); if (resource != null) { try { asmClass = new DecompiledClassNode(AsmDecompiler.parseClass(resource), new AsmReferenceResolver(this, compilationUnit)); if (!asmClass.getName().equals(name)) { // this may happen under Windows because getResource is case insensitive under that OS! asmClass = null; } } catch (IOException e) { // fall through and attempt other search strategies } } if (asmClass != null) { if (isFromAnotherClassLoader(loader, fileName)) { return tryAsScript(name, compilationUnit, asmClass); } return new LookupResult(null, asmClass); } return null; }
public static boolean isKnownImmutableType(ClassNode fieldType, List<String> knownImmutableClasses) { if (builtinOrDeemedType(fieldType, knownImmutableClasses)) return true; if (!fieldType.isResolved()) return false; if ("java.util.Optional".equals(fieldType.getName()) && fieldType.getGenericsTypes() != null && fieldType.getGenericsTypes().length == 1) { GenericsType optionalType = fieldType.getGenericsTypes()[0]; if (optionalType.isResolved() && !optionalType.isPlaceholder() && !optionalType.isWildcard()) { ClassNode valueType = optionalType.getType(); if (builtinOrDeemedType(valueType, knownImmutableClasses)) return true; if (valueType.isEnum()) return true; } } return fieldType.isEnum() || ClassHelper.isPrimitiveType(fieldType) || hasImmutableAnnotation(fieldType); }
ClassExpression ce = (ClassExpression) pe.getObjectExpression(); ClassNode type = ce.getType(); if (type.isEnum() || !(type.isResolved() || type.isPrimaryClassNode())) return exp;
boolean isClass = t.isResolved(); if (!isClass) {
private boolean resolve(ClassNode type, boolean testModuleImports, boolean testDefaultImports, boolean testStaticInnerClasses) { resolveGenericsTypes(type.getGenericsTypes()); if (type.isResolved() || type.isPrimaryClassNode()) return true; if (type.isArray()) { ClassNode element = type.getComponentType();
genericsType.setResolved(genericsType.getType().isResolved());
protected Statement createConstructorStatement(AbstractASTTransformation xform, ClassNode cNode, PropertyNode pNode, boolean namedArgs) { final List<String> knownImmutableClasses = ImmutablePropertyUtils.getKnownImmutableClasses(xform, cNode); final List<String> knownImmutables = ImmutablePropertyUtils.getKnownImmutables(xform, cNode); FieldNode fNode = pNode.getField(); final ClassNode fType = fNode.getType(); Statement statement; if (ImmutablePropertyUtils.isKnownImmutableType(fType, knownImmutableClasses) || isKnownImmutable(pNode.getName(), knownImmutables)) { statement = createConstructorStatementDefault(fNode, namedArgs); } else if (fType.isArray() || implementsCloneable(fType)) { statement = createConstructorStatementArrayOrCloneable(fNode, namedArgs); } else if (derivesFromDate(fType)) { statement = createConstructorStatementDate(fNode, namedArgs); } else if (isOrImplements(fType, COLLECTION_TYPE) || fType.isDerivedFrom(COLLECTION_TYPE) || isOrImplements(fType, MAP_TYPE) || fType.isDerivedFrom(MAP_TYPE)) { statement = createConstructorStatementCollection(fNode, namedArgs); } else if (fType.isResolved()) { xform.addError(ImmutablePropertyUtils.createErrorMessage(cNode.getName(), fNode.getName(), fType.getName(), "compiling"), fNode); statement = EmptyStatement.INSTANCE; } else { statement = createConstructorStatementGuarded(cNode, fNode, namedArgs, knownImmutables, knownImmutableClasses); } return statement; }