public void call(SourceUnit source) throws CompilationFailedException { List<ClassNode> classes = source.ast.getClasses(); for (ClassNode node : classes) { CompileUnit cu = node.getCompileUnit(); for (Iterator iter = cu.iterateClassNodeToCompile(); iter.hasNext(); ) { String name = (String) iter.next(); SourceUnit su = ast.getScriptSourceLocation(name); List<ClassNode> classesInSourceUnit = su.ast.getClasses(); StringBuilder message = new StringBuilder(); message .append("Compilation incomplete: expected to find the class ") .append(name) .append(" in ") .append(su.getName()); if (classesInSourceUnit.isEmpty()) { message.append(", but the file seems not to contain any classes"); } else { message.append(", but the file contains the classes: "); boolean first = true; for (ClassNode cn : classesInSourceUnit) { if (!first) { message.append(", "); } else { first = false; } message.append(cn.getName()); } } getErrorCollector() .addErrorAndContinue(new SimpleMessage(message.toString(), CompilationUnit.this)); iter.remove(); } } }
public void removeField(String oldName) { ClassNode r = redirect(); if (r.fieldIndex == null) r.fieldIndex = new HashMap<String, FieldNode>(); final Map<String, FieldNode> index = r.fieldIndex; r.fields.remove(index.get(oldName)); index.remove(oldName); }
public Map<String, MethodNode> getDeclaredMethodsMap() { // Start off with the methods from the superclass. ClassNode parent = getSuperClass(); Map<String, MethodNode> result = null; if (parent != null) { result = parent.getDeclaredMethodsMap(); } else { result = new HashMap<String, MethodNode>(); } // add in unimplemented abstract methods from the interfaces for (ClassNode iface : getInterfaces()) { Map<String, MethodNode> ifaceMethodsMap = iface.getDeclaredMethodsMap(); for (String methSig : ifaceMethodsMap.keySet()) { if (!result.containsKey(methSig)) { MethodNode methNode = ifaceMethodsMap.get(methSig); result.put(methSig, methNode); } } } // And add in the methods implemented in this class. for (MethodNode method : getMethods()) { String sig = method.getTypeDescriptor(); result.put(sig, method); } return result; }
private Expression transformInlineConstants(Expression exp) { if (exp instanceof PropertyExpression) { PropertyExpression pe = (PropertyExpression) exp; if (pe.getObjectExpression() instanceof ClassExpression) { ClassExpression ce = (ClassExpression) pe.getObjectExpression(); ClassNode type = ce.getType(); if (type.isEnum()) return exp; Expression constant = findConstant(type.getField(pe.getPropertyAsString())); // GRECLIPSE edit // if (constant != null) return constant; if (constant != null) { String name = pe.getText().replace('$', '.'); Object alias = pe.getNodeMetaData("static.import.alias"); if (alias != null && !alias.equals(pe.getPropertyAsString())) { name += " as " + alias; } // store the qualified name to facilitate organizing static imports constant.setNodeMetaData("static.import", name); return constant; } // GRECLIPSE end } } else if (exp instanceof ListExpression) { ListExpression le = (ListExpression) exp; ListExpression result = new ListExpression(); for (Expression e : le.getExpressions()) { result.addExpression(transformInlineConstants(e)); } return result; } return exp; }
private void assertMembersNamesAreUnique() { Map<String, FieldNode> allDslCollectionFieldNodesOfHierarchy = new HashMap<String, FieldNode>(); for (ClassNode level : ASTHelper.getHierarchyOfDSLObjectAncestors(annotatedClass)) { for (FieldNode field : level.getFields()) { if (!ASTHelper.isListOrMap(field.getType())) continue; String memberName = getElementNameForCollectionField(field); FieldNode conflictingField = allDslCollectionFieldNodesOfHierarchy.get(memberName); if (conflictingField != null) { addCompileError( String.format( "Member name %s is used more than once: %s:%s and %s:%s", memberName, field.getOwner().getName(), field.getName(), conflictingField.getOwner().getName(), conflictingField.getName()), field); return; } allDslCollectionFieldNodesOfHierarchy.put(memberName, field); } } }
private void getAllInterfaces(Set<ClassNode> res) { if (isInterface()) res.add(this); for (ClassNode anInterface : getInterfaces()) { res.add(anInterface); anInterface.getAllInterfaces(res); } }
public void addProperty(PropertyNode node) { node.setDeclaringClass(redirect()); FieldNode field = node.getField(); addField(field); final ClassNode r = redirect(); if (r.properties == null) r.properties = new ArrayList<PropertyNode>(); r.properties.add(node); }
private Expression findStaticField(ClassNode staticImportType, String fieldName) { if (staticImportType.isPrimaryClassNode() || staticImportType.isResolved()) { FieldNode field = staticImportType.getField(fieldName); if (field != null && field.isStatic()) return new PropertyExpression(new ClassExpression(staticImportType), fieldName); } return null; }
private 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; }
public void preprocessClassNode(ClassNode node) { super.preprocessClassNode(node); classes.add(node); getChartData(node.getFeatures().size())[FEATURES_PER_CLASS]++; getChartData(node.getInboundDependencies().size())[INBOUNDS_PER_CLASS]++; getChartData(node.getOutboundDependencies().size())[OUTBOUNDS_PER_CLASS]++; }
/** @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; }
/** * 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; }
public void addMethod(MethodNode node) { node.setDeclaringClass(this); ClassNode base = redirect(); if (base.methodsList.isEmpty()) { base.methodsList = new ArrayList<MethodNode>(); } base.methodsList.add(node); base.methods.put(node.getName(), node); }
public void visitInboundClassNode(ClassNode node) { if (!getCoverage().contains(node)) { getSelectedNodes().add(node); Node copy = getFactory().createClass(node.getName(), node.isConfirmed()); getCopiedNodes().add(copy); copy.addDependency(currentNode); } }
public void addFieldFirst(FieldNode node) { final ClassNode r = redirect(); node.setDeclaringClass(r); node.setOwner(r); if (r.fields == null) r.fields = new LinkedList<FieldNode>(); if (r.fieldIndex == null) r.fieldIndex = new HashMap<String, FieldNode>(); r.fields.addFirst(node); r.fieldIndex.put(node.getName(), node); }
/** * A loop driver for applying operations to all primary ClassNodes in our AST. Automatically skips * units that have already been processed through the current phase. */ public void applyToPrimaryClassNodes(PrimaryClassNodeOperation body) throws CompilationFailedException { // GRECLIPSE: start /*old{ Iterator classNodes = getPrimaryClassNodes(body.needSortedInput()).iterator(); }*/ // newcode List primaryClassNodes = getPrimaryClassNodes(body.needSortedInput()); Iterator classNodes = primaryClassNodes.iterator(); // end while (classNodes.hasNext()) { SourceUnit context = null; try { ClassNode classNode = (ClassNode) classNodes.next(); context = classNode.getModule().getContext(); // GRECLIPSE get to the bottom of this - why are operations running multiple times that // should only run once? if (context == null || context.phase < phase || (context.phase == phase && !context.phaseComplete)) { int offset = 1; Iterator<InnerClassNode> iterator = classNode.getInnerClasses(); while (iterator.hasNext()) { iterator.next(); offset++; } body.call(context, new GeneratorContext(this.ast, offset), classNode); } } catch (CompilationFailedException e) { // fall through, getErrorReporter().failIfErrors() will trigger } catch (NullPointerException npe) { throw npe; } catch (GroovyBugError e) { changeBugText(e, context); throw e; } catch (Exception e) { // check the exception for a nested compilation exception ErrorCollector nestedCollector = null; for (Throwable next = e.getCause(); next != e && next != null; next = next.getCause()) { if (!(next instanceof MultipleCompilationErrorsException)) continue; MultipleCompilationErrorsException mcee = (MultipleCompilationErrorsException) next; nestedCollector = mcee.collector; break; } if (nestedCollector != null) { getErrorCollector().addCollectorContents(nestedCollector); } else { getErrorCollector().addError(new ExceptionMessage(e, configuration.getDebug(), this)); } } } getErrorCollector().failIfErrors(); }
/** * @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; }
public ClassNode getPlainNodeReference() { if (ClassHelper.isPrimitiveType(this)) return this; ClassNode n = new ClassNode(name, modifiers, superClass, null, null); n.isPrimaryNode = false; n.setRedirect(redirect()); if (isArray()) { n.componentType = redirect().getComponentType(); } return n; }
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 declares that it implements the given interface or if one of its * interfaces extends directly or indirectly the interface * <p>NOTE: Doesn't consider an interface to implement itself. I think this is intended to be * called on ClassNodes representing classes, not interfaces. */ public boolean declaresInterface(ClassNode classNode) { ClassNode[] interfaces = redirect().getInterfaces(); for (ClassNode cn : interfaces) { if (cn.equals(classNode)) return true; } for (ClassNode cn : interfaces) { if (cn.declaresInterface(classNode)) return true; } return false; }
/** * 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 "); }
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")))); }
/** * Parse a string, assuming that it is of the type expected by a given NamedParameter. * * <p>This method does not deal with sets; if the NamedParameter is set valued, then the provided * string should correspond to a single member of the set. It is up to the caller to call parse * once for each value that should be parsed as a member of the set. * * @return a non-null reference to the parsed value. */ @Override @SuppressWarnings("unchecked") public <T> T parse(final NamedParameterNode<T> np, final String value) throws ParseException { final ClassNode<T> iface; try { iface = (ClassNode<T>) getNode(np.getFullArgName()); } catch (final NameResolutionException e) { throw new IllegalStateException( "Could not parse validated named parameter argument type. NamedParameter is " + np.getFullName() + " argument type is " + np.getFullArgName()); } Class<?> clazz; String fullName; try { clazz = classForName(iface.getFullName()); fullName = null; } catch (final ClassNotFoundException e) { clazz = null; fullName = iface.getFullName(); } try { if (clazz != null) { return (T) parameterParser.parse(clazz, value); } else { return parameterParser.parse(fullName, value); } } catch (final UnsupportedOperationException e) { try { final Node impl = getNode(value); if (impl instanceof ClassNode && isImplementation(iface, (ClassNode<?>) impl)) { return (T) impl; } throw new ParseException( "Name<" + iface.getFullName() + "> " + np.getFullName() + " cannot take non-subclass " + impl.getFullName(), e); } catch (final NameResolutionException e2) { throw new ParseException( "Name<" + iface.getFullName() + "> " + np.getFullName() + " cannot take non-class " + value, e); } } }
/** * Sets this instance as proxy for the given ClassNode. * * @param cn the class to redirect to. If set to null the redirect will be removed */ public void setRedirect(ClassNode cn) { if (isPrimaryNode) throw new GroovyBugError( "tried to set a redirect for a primary ClassNode (" + getName() + "->" + cn.getName() + ")."); if (cn != null) cn = cn.redirect(); if (cn == this) return; redirect = cn; }
public MethodNode getSetterMethod(String setterName, boolean voidOnly) { for (MethodNode method : getDeclaredMethods(setterName)) { if (setterName.equals(method.getName()) && (!voidOnly || ClassHelper.VOID_TYPE == method.getReturnType()) && method.getParameters().length == 1) { return method; } } ClassNode parent = getSuperClass(); if (parent != null) return parent.getSetterMethod(setterName, voidOnly); return null; }
public MethodNode getGetterMethod(String getterName) { for (MethodNode method : getDeclaredMethods(getterName)) { if (getterName.equals(method.getName()) && ClassHelper.VOID_TYPE != method.getReturnType() && method.getParameters().length == 0) { return method; } } ClassNode parent = getSuperClass(); if (parent != null) return parent.getGetterMethod(getterName); return null; }
protected byte[] transformClass(byte[] bytes, String clssname) { InputStream is = getClass().getResourceAsStream("/" + clssname.replace('.', '/') + ".class"); ClassReader orig = null; try { ClassReader crRepl = new ClassReader(is); ClassNode cnRepl = new ClassNode(Opcodes.ASM4); crRepl.accept(cnRepl, ClassReader.SKIP_FRAMES); ClassReader crOrig = new ClassReader(bytes); ClassNode cnOrig = new ClassNode(Opcodes.ASM4); crOrig.accept(cnOrig, ClassReader.SKIP_FRAMES); for (Object ofnRepl : cnRepl.fields) { FieldNode fnRepl = (FieldNode) ofnRepl; if (hasReplaceAnnotation(fnRepl.visibleAnnotations)) { FieldNode fnOrig = findField(cnOrig.fields, fnRepl); if (fnOrig != null) { cnOrig.fields.remove(fnOrig); cnOrig.fields.add(cnOrig.fields.size(), scrubField(cnOrig, cnRepl, fnRepl)); } } else if (hasAddAnnotation(fnRepl.visibleAnnotations)) { cnOrig.fields.add(cnOrig.fields.size(), scrubField(cnOrig, cnRepl, fnRepl)); } } for (Object omnRepl : cnRepl.methods) { MethodNode mnRepl = (MethodNode) omnRepl; if (hasReplaceAnnotation(mnRepl.visibleAnnotations)) { MethodNode mnOrig = findMethod(cnOrig.methods, mnRepl); if (mnOrig != null) { cnOrig.methods.remove(mnOrig); cnOrig.methods.add(cnOrig.methods.size(), scrubMethod(cnOrig, cnRepl, mnRepl)); } } else if (hasAddAnnotation(mnRepl.visibleAnnotations)) { cnOrig.methods.add(cnOrig.methods.size() + 1, scrubMethod(cnOrig, cnRepl, mnRepl)); } } ClassWriter cwNew = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); cnOrig.accept(cwNew); return cwNew.toByteArray(); } catch (IOException e) { e.printStackTrace(); // To change body of catch statement use File | Settings | File // Templates. } return bytes; }
/** * @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; }
@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); } }