diff --git a/src/main/java/org/codehaus/groovy/ast/ClassNode.java b/src/main/java/org/codehaus/groovy/ast/ClassNode.java index 58710326465..f2cadddd1dd 100644 --- a/src/main/java/org/codehaus/groovy/ast/ClassNode.java +++ b/src/main/java/org/codehaus/groovy/ast/ClassNode.java @@ -867,9 +867,9 @@ public void positionStmtsAfterEnumInitStmts(List staticFieldStatement } /** - * This method returns a list of all methods of the given name - * defined in the current class - * @return the method list + * Returns a list of all methods with the given name from this class. + * + * @return method list (possibly empty) * @see #getMethods(String) */ public List getDeclaredMethods(String name) { @@ -880,25 +880,26 @@ public List getDeclaredMethods(String name) { } /** - * This method creates a list of all methods with this name of the - * current class and of all super classes - * @return the methods list + * Returns a list of all methods with the given name from this class and its + * super class(es). + * + * @return method list (possibly empty) * @see #getDeclaredMethods(String) */ public List getMethods(String name) { - List result = new ArrayList<>(); + List list = new ArrayList<>(4); ClassNode node = this; while (node != null) { - result.addAll(node.getDeclaredMethods(name)); + list.addAll(node.getDeclaredMethods(name)); node = node.getSuperClass(); } - return result; + return list; } /** * Finds a method matching the given name and parameters in this class. * - * @return the method matching the given name and parameters or null + * @return method node or null */ public MethodNode getDeclaredMethod(String name, Parameter[] parameters) { for (MethodNode method : getDeclaredMethods(name)) { @@ -911,9 +912,9 @@ public MethodNode getDeclaredMethod(String name, Parameter[] parameters) { /** * Finds a method matching the given name and parameters in this class - * or any parent class. + * or any super class. * - * @return the method matching the given name and parameters or null + * @return method node or null */ public MethodNode getMethod(String name, Parameter[] parameters) { for (MethodNode method : getMethods(name)) { diff --git a/src/main/java/org/codehaus/groovy/ast/InnerClassNode.java b/src/main/java/org/codehaus/groovy/ast/InnerClassNode.java index 8b24118e6fb..85590a4a302 100644 --- a/src/main/java/org/codehaus/groovy/ast/InnerClassNode.java +++ b/src/main/java/org/codehaus/groovy/ast/InnerClassNode.java @@ -23,7 +23,7 @@ import java.util.LinkedList; /** - * Represents an inner class declaration + * Represents an inner class definition. */ public class InnerClassNode extends ClassNode { @@ -37,7 +37,7 @@ public class InnerClassNode extends ClassNode { * @param superClass the base class name - use "java.lang.Object" if no direct base class */ public InnerClassNode(ClassNode outerClass, String name, int modifiers, ClassNode superClass) { - this(outerClass, name, modifiers, superClass, ClassHelper.EMPTY_TYPE_ARRAY, MixinNode.EMPTY_ARRAY); + this(outerClass, name, modifiers, superClass, ClassNode.EMPTY_ARRAY, MixinNode.EMPTY_ARRAY); } /** @@ -50,7 +50,7 @@ public InnerClassNode(ClassNode outerClass, String name, int modifiers, ClassNod this.outerClass = outerClass; if (outerClass.innerClasses == null) - outerClass.innerClasses = new LinkedList (); + outerClass.innerClasses = new LinkedList<>(); outerClass.innerClasses.add(this); } @@ -59,7 +59,7 @@ public ClassNode getOuterClass() { return outerClass; } - public ClassNode getOuterMostClass() { + public ClassNode getOuterMostClass() { ClassNode outerClass = getOuterClass(); while (outerClass instanceof InnerClassNode) { outerClass = outerClass.getOuterClass(); @@ -67,9 +67,6 @@ public ClassNode getOuterMostClass() { return outerClass; } - /** - * @return the field node on the outer class or null if this is not an inner class - */ @Override public FieldNode getOuterField(String name) { return outerClass.getDeclaredField(name); diff --git a/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitor.java b/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitor.java index 3855d959db2..44a3787c02c 100644 --- a/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitor.java +++ b/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitor.java @@ -39,7 +39,6 @@ import org.codehaus.groovy.ast.stmt.ExpressionStatement; import org.codehaus.groovy.control.CompilationUnit; import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.transform.trait.Traits; import java.util.ArrayList; import java.util.Arrays; @@ -50,6 +49,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.callX; import static org.codehaus.groovy.ast.tools.GeneralUtils.constX; import static org.codehaus.groovy.ast.tools.GeneralUtils.varX; +import static org.codehaus.groovy.transform.trait.Traits.isTrait; import static org.objectweb.asm.Opcodes.ACC_FINAL; import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import static org.objectweb.asm.Opcodes.ACC_STATIC; @@ -85,12 +85,12 @@ public void visitClass(ClassNode node) { super.visitClass(node); - if (node.isEnum() || node.isInterface()) return; - if (innerClass == null) return; - - if (node.getSuperClass().isInterface() || Traits.isAnnotatedWithTrait(node.getSuperClass())) { - node.addInterface(node.getUnresolvedSuperClass()); - node.setUnresolvedSuperClass(ClassHelper.OBJECT_TYPE); + if (innerClass != null && innerClass.isAnonymous()) { + ClassNode upperClass= node.getUnresolvedSuperClass(false); + if (upperClass.isInterface() || isTrait(upperClass)) { + node.addInterface(upperClass); + node.setUnresolvedSuperClass(ClassHelper.OBJECT_TYPE); + } } } @@ -150,9 +150,9 @@ public void visitConstructorCallExpression(ConstructorCallExpression call) { InnerClassNode innerClass = (InnerClassNode) call.getType(); ClassNode outerClass = innerClass.getOuterClass(); - ClassNode superClass = innerClass.getSuperClass(); - if (!superClass.isInterface() && superClass.getOuterClass() != null - && !(superClass.isStaticClass() || (superClass.getModifiers() & ACC_STATIC) != 0)) { + ClassNode upperClass = innerClass.getUnresolvedSuperClass(false); + if (upperClass.getOuterClass() != null && !upperClass.isInterface() + && !(upperClass.isStaticClass() || (upperClass.getModifiers() & ACC_STATIC) != 0)) { insertThis0ToSuperCall(call, innerClass); } if (!innerClass.getDeclaredConstructors().isEmpty()) return; diff --git a/src/main/java/org/codehaus/groovy/control/GenericsVisitor.java b/src/main/java/org/codehaus/groovy/control/GenericsVisitor.java index 79a0ada9524..d71f0647794 100644 --- a/src/main/java/org/codehaus/groovy/control/GenericsVisitor.java +++ b/src/main/java/org/codehaus/groovy/control/GenericsVisitor.java @@ -61,11 +61,11 @@ public GenericsVisitor(final SourceUnit source) { @Override public void visitClass(final ClassNode node) { - ClassNode sn = node.getUnresolvedSuperClass(false); - if (checkWildcard(sn)) return; + ClassNode sc = node.getUnresolvedSuperClass(false); + if (checkWildcard(sc)) return; boolean isAIC = node instanceof InnerClassNode && ((InnerClassNode) node).isAnonymous(); - checkGenericsUsage(sn, node.getSuperClass(), isAIC ? Boolean.TRUE : null); + checkGenericsUsage(sc, sc.redirect(), isAIC ? Boolean.TRUE : null); for (ClassNode face : node.getInterfaces()) { checkGenericsUsage(face); } diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java index 271c925847f..3ddc87b5478 100644 --- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java +++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java @@ -948,15 +948,14 @@ private static boolean isVisibleNestedClass(final ClassNode innerType, final Cla private boolean directlyImplementsTrait(final ClassNode trait) { ClassNode[] interfaces = currentClass.getInterfaces(); - if (interfaces == null) { - return currentClass.getSuperClass().equals(trait); - } - for (ClassNode node : interfaces) { - if (node.equals(trait)) { - return true; + if (interfaces != null) { + for (ClassNode face : interfaces) { + if (face.equals(trait)) { + return true; + } } } - return currentClass.getSuperClass().equals(trait); + return currentClass.getUnresolvedSuperClass().equals(trait); } private void checkThisAndSuperAsPropertyAccess(final PropertyExpression expression) { diff --git a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java index dea2d75d157..dd187c645f2 100644 --- a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java +++ b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java @@ -219,7 +219,7 @@ && getSourceUnit().getAST().getClasses().contains(traitType.redirect())) { traitType.redirect().setNodeMetaData(UNRESOLVED_HELPER_CLASS, helperType); return helperType; } - return Traits.findHelper(traitType); + return Traits.findHelper(traitType).getPlainNodeReference(); } private ClassNode getTraitSuperTarget(final Expression exp) { diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java index 5bf9f2c07a0..a8db6785ac5 100644 --- a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java +++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java @@ -133,23 +133,22 @@ public void visit(final ASTNode[] nodes, final SourceUnit source) { private void checkNoConstructor(final ClassNode cNode) { if (!cNode.getDeclaredConstructors().isEmpty()) { - addError("Error processing trait '" + cNode.getName() + "'. " + " Constructors are not allowed.", cNode); + addError("Error processing trait '" + cNode.getName() + "'. Constructors are not allowed.", cNode); } } private void checkExtendsClause(final ClassNode cNode) { - ClassNode superClass = cNode.getSuperClass(); + ClassNode superClass = cNode.getUnresolvedSuperClass(false); if (superClass.isInterface() && !Traits.isTrait(superClass)) { - addError("Trait cannot extend an interface. Use 'implements' instead", cNode); + addError("A trait cannot extend an interface. Use 'implements' instead.", cNode); } } private static void replaceExtendsByImplements(final ClassNode cNode) { - ClassNode superClass = cNode.getUnresolvedSuperClass(); + ClassNode superClass = cNode.getUnresolvedSuperClass(false); if (Traits.isTrait(superClass)) { // move from super class to interface cNode.setSuperClass(OBJECT_TYPE); - cNode.setUnresolvedSuperClass(OBJECT_TYPE); cNode.addInterface(superClass); } } @@ -537,7 +536,7 @@ private void processField(final FieldNode field, final MethodNode initializer, f FieldNode dummyField = new FieldNode( dummyFieldName, ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, - field.getOriginType().getPlainNodeReference(), + field.getOriginType(), fieldHelper, null ); diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java index 9520f59665b..186e980d456 100644 --- a/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java +++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitComposer.java @@ -31,16 +31,11 @@ import org.codehaus.groovy.ast.PropertyNode; import org.codehaus.groovy.ast.expr.ArgumentListExpression; import org.codehaus.groovy.ast.expr.ArrayExpression; -import org.codehaus.groovy.ast.expr.BinaryExpression; -import org.codehaus.groovy.ast.expr.CastExpression; import org.codehaus.groovy.ast.expr.ClassExpression; -import org.codehaus.groovy.ast.expr.ConstantExpression; import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.expr.MethodCallExpression; import org.codehaus.groovy.ast.expr.StaticMethodCallExpression; -import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.ast.stmt.EmptyStatement; -import org.codehaus.groovy.ast.stmt.ExpressionStatement; import org.codehaus.groovy.ast.stmt.Statement; import org.codehaus.groovy.ast.tools.GeneralUtils; import org.codehaus.groovy.ast.tools.GenericsUtils; @@ -50,8 +45,6 @@ import org.codehaus.groovy.runtime.InvokerHelper; import org.codehaus.groovy.runtime.MetaClassHelper; import org.codehaus.groovy.syntax.SyntaxException; -import org.codehaus.groovy.syntax.Token; -import org.codehaus.groovy.syntax.Types; import org.codehaus.groovy.transform.ASTTransformationCollectorCodeVisitor; import org.codehaus.groovy.transform.sc.StaticCompileTransformation; import org.codehaus.groovy.transform.stc.StaticTypesMarker; @@ -73,6 +66,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.block; import static org.codehaus.groovy.ast.tools.GeneralUtils.callX; import static org.codehaus.groovy.ast.tools.GeneralUtils.castX; +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX; import static org.codehaus.groovy.ast.tools.GeneralUtils.constX; import static org.codehaus.groovy.ast.tools.GeneralUtils.ifElseS; import static org.codehaus.groovy.ast.tools.GeneralUtils.isInstanceOfX; @@ -80,7 +74,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS; import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt; import static org.codehaus.groovy.ast.tools.GeneralUtils.varX; -import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse; /** * This class contains a static utility method {@link #doExtendTraits(org.codehaus.groovy.ast.ClassNode, org.codehaus.groovy.control.SourceUnit, org.codehaus.groovy.control.CompilationUnit)} @@ -134,10 +127,10 @@ private static void applyTrait(final ClassNode trait, final ClassNode cNode, fin String name = methodNode.getName(); Parameter[] helperMethodParams = methodNode.getParameters(); int nParams = helperMethodParams.length; - if (nParams > 0 && !methodNode.isAbstract() && ((methodNode.getModifiers() & Opcodes.ACC_STATIC) != 0) + if (nParams > 0 && methodNode.isStatic() && !methodNode.isAbstract() && (!name.contains("$") || (methodNode.getModifiers() & Opcodes.ACC_SYNTHETIC) == 0)) { ArgumentListExpression argList = new ArgumentListExpression(); - argList.addExpression(new VariableExpression("this")); + argList.addExpression(varX("this")); Parameter[] origParams = new Parameter[nParams - 1]; Parameter[] params = new Parameter[nParams - 1]; System.arraycopy(methodNode.getParameters(), 1, params, 0, params.length); @@ -149,7 +142,7 @@ private static void applyTrait(final ClassNode trait, final ClassNode cNode, fin for (int i = 1; i < nParams; i += 1) { Parameter parameter = helperMethodParams[i]; ClassNode originType = parameter.getOriginType(); - ClassNode fixedType = correctToGenericsSpecRecurse(methodGenericsSpec, originType); + ClassNode fixedType = GenericsUtils.correctToGenericsSpecRecurse(methodGenericsSpec, originType); Parameter newParam = new Parameter(fixedType, parameter.getName()); List copied = new LinkedList<>(); List notCopied = new LinkedList<>(); @@ -157,23 +150,22 @@ private static void applyTrait(final ClassNode trait, final ClassNode cNode, fin newParam.addAnnotations(copied); params[i - 1] = newParam; origParams[i - 1] = parameter; - argList.addExpression(new VariableExpression(newParam)); + argList.addExpression(varX(newParam)); } createForwarderMethod(trait, cNode, methodNode, originalMethod, helperClassNode, methodGenericsSpec, helperMethodParams, origParams, params, argList, unit); } } - MethodCallExpression staticInitCall = new MethodCallExpression( - new ClassExpression(helperClassNode), + + MethodCallExpression staticInitCall = callX( + classX(helperClassNode), Traits.STATIC_INIT_METHOD, - new ArgumentListExpression(new ClassExpression(cNode))); + classX(cNode)); MethodNode staticInitMethod = new MethodNode( Traits.STATIC_INIT_METHOD, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, ClassHelper.VOID_TYPE, new Parameter[] {new Parameter(ClassHelper.CLASS_Type,"clazz")}, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE); staticInitMethod.setDeclaringClass(helperClassNode); staticInitCall.setMethodTarget(staticInitMethod); - cNode.addStaticInitializerStatements(Collections.singletonList(new ExpressionStatement( - staticInitCall - )), false); + cNode.addStaticInitializerStatements(Collections.singletonList(stmt(staticInitCall)), false); if (fieldHelperClassNode != null && !cNode.declaresInterface(fieldHelperClassNode)) { // we should implement the field helper interface too cNode.addInterface(fieldHelperClassNode); @@ -205,7 +197,7 @@ private static void applyTrait(final ClassNode trait, final ClassNode cNode, fin fieldName = fieldName.substring(0, suffixIdx); String operation = methodNode.getName().substring(suffixIdx + 1); boolean getter = "get".equals(operation); - ClassNode returnType = correctToGenericsSpecRecurse(genericsSpec, methodNode.getReturnType()); + ClassNode returnType = GenericsUtils.correctToGenericsSpecRecurse(genericsSpec, methodNode.getReturnType()); int fieldMods = 0; int isStatic = 0; boolean publicField = true; @@ -261,7 +253,7 @@ private static void applyTrait(final ClassNode trait, final ClassNode cNode, fin if (isStatic == 0) { cNode.addObjectInitializerStatements(stmt); } else { - List staticStatements = new ArrayList(); + List staticStatements = new ArrayList<>(); staticStatements.add(stmt); cNode.addStaticInitializerStatements(staticStatements, true); } @@ -274,7 +266,7 @@ private static void applyTrait(final ClassNode trait, final ClassNode cNode, fin newParams = Parameter.EMPTY_ARRAY; } else { ClassNode originType = methodNode.getParameters()[0].getOriginType(); - ClassNode fixedType = originType.isGenericsPlaceHolder()?ClassHelper.OBJECT_TYPE:correctToGenericsSpecRecurse(genericsSpec, originType); + ClassNode fixedType = originType.isGenericsPlaceHolder()?ClassHelper.OBJECT_TYPE:GenericsUtils.correctToGenericsSpecRecurse(genericsSpec, originType); newParams = new Parameter[]{new Parameter(fixedType, "val")}; } @@ -283,9 +275,8 @@ private static void applyTrait(final ClassNode trait, final ClassNode cNode, fin Statement body = getter ? returnS(fieldExpr) : (finalSetter ? null : stmt( - new BinaryExpression( + assignX( fieldExpr, - Token.newSymbol(Types.EQUAL, 0, 0), varX(newParams[0]) ) )); @@ -306,38 +297,25 @@ private static void applyTrait(final ClassNode trait, final ClassNode cNode, fin } } } - cNode.addObjectInitializerStatements(new ExpressionStatement( - new MethodCallExpression( - new ClassExpression(helperClassNode), - Traits.INIT_METHOD, - new ArgumentListExpression(new VariableExpression("this"))) + cNode.addObjectInitializerStatements(stmt( + callX(classX(helperClassNode), Traits.INIT_METHOD, varX("this")) )); } private static void createForwarderMethod( - ClassNode trait, - ClassNode targetNode, - MethodNode helperMethod, - MethodNode originalMethod, - ClassNode helperClassNode, - Map genericsSpec, - Parameter[] helperMethodParams, - Parameter[] traitMethodParams, - Parameter[] forwarderParams, - ArgumentListExpression helperMethodArgList, SourceUnit unit) { - MethodCallExpression mce = new MethodCallExpression( - new ClassExpression(helperClassNode), + ClassNode trait, ClassNode targetNode, MethodNode helperMethod, MethodNode originalMethod, ClassNode helperClassNode, Map genericsSpec, + Parameter[] helperMethodParams, Parameter[] traitMethodParams, Parameter[] forwarderParams, ArgumentListExpression helperMethodArgList, SourceUnit unit) { + MethodCallExpression mce = callX( + classX(helperClassNode), helperMethod.getName(), helperMethodArgList ); mce.setImplicitThis(false); - ClassNode[] exceptionNodes = correctToGenericsSpecRecurse(genericsSpec, copyExceptions(helperMethod.getExceptions())); - ClassNode fixedReturnType = correctToGenericsSpecRecurse(genericsSpec, helperMethod.getReturnType()); - boolean noCastRequired = genericsSpec.isEmpty() || fixedReturnType.getName().equals(ClassHelper.VOID_TYPE.getName()); - Expression forwardExpression = noCastRequired ? mce : new CastExpression(fixedReturnType,mce); - // we could rely on the first parameter name ($static$self) but that information is not - // guaranteed to be always present + ClassNode[] exceptionTypes = GenericsUtils.correctToGenericsSpecRecurse(genericsSpec, copyExceptions(helperMethod.getExceptions())); + ClassNode returnType = GenericsUtils.correctToGenericsSpecRecurse(genericsSpec, helperMethod.getReturnType()); + boolean castRequired = !genericsSpec.isEmpty() && !helperMethod.isVoidMethod(); + boolean isHelperForStaticMethod = ClassHelper.isClassType(helperMethodParams[0].getOriginType()); if (helperMethod.isPrivate() && !isHelperForStaticMethod) { // GROOVY-7213: do not create forwarder for private methods @@ -353,10 +331,10 @@ private static void createForwarderMethod( MethodNode forwarder = new MethodNode( helperMethod.getName(), modifiers, - fixedReturnType, + returnType, forwarderParams, - exceptionNodes, - new ExpressionStatement(forwardExpression) + exceptionTypes, + stmt(castRequired ? castX(returnType, mce) : mce) ); List copied = new LinkedList<>(); List notCopied = Collections.emptyList(); // at this point, should *always* stay empty @@ -379,8 +357,8 @@ private static void createForwarderMethod( } // add a helper annotation indicating that it is a bridge method AnnotationNode bridgeAnnotation = new AnnotationNode(Traits.TRAITBRIDGE_CLASSNODE); - bridgeAnnotation.addMember("traitClass", new ClassExpression(trait)); - bridgeAnnotation.addMember("desc", new ConstantExpression(BytecodeHelper.getMethodDescriptor(helperMethod.getReturnType(), traitMethodParams))); + bridgeAnnotation.addMember("traitClass", classX(trait)); + bridgeAnnotation.addMember("desc", constX(BytecodeHelper.getMethodDescriptor(helperMethod.getReturnType(), traitMethodParams))); forwarder.addAnnotation(bridgeAnnotation); MethodNode existingMethod = findExistingMethod(targetNode, forwarder); @@ -411,8 +389,7 @@ private static SyntaxException createException(ClassNode trait, ClassNode target if (bridgeAnno != null) { Expression traitClass = bridgeAnno.getMember("traitClass"); if (traitClass instanceof ClassExpression) { - ClassExpression ce = (ClassExpression) traitClass; - fromTrait = ce.getType().getNameWithoutPackage(); + fromTrait = traitClass.getType().getNameWithoutPackage(); } } middle = "in '" + targetNode.getNameWithoutPackage(); @@ -430,7 +407,7 @@ private static SyntaxException createException(ClassNode trait, ClassNode target private static GenericsType[] removeNonPlaceHolders(GenericsType[] oldTypes) { if (oldTypes==null || oldTypes.length==0) return oldTypes; - ArrayList l = new ArrayList(Arrays.asList(oldTypes)); + ArrayList l = new ArrayList<>(Arrays.asList(oldTypes)); Iterator it = l.iterator(); boolean modified = false; while (it.hasNext()) { @@ -451,11 +428,11 @@ private static GenericsType[] removeNonPlaceHolders(GenericsType[] oldTypes) { * @param genericsSpec */ private static void createSuperForwarder(ClassNode targetNode, MethodNode forwarder, final Map genericsSpec) { - List interfaces = new ArrayList(Traits.collectAllInterfacesReverseOrder(targetNode, new LinkedHashSet())); + List interfaces = new ArrayList<>(Traits.collectAllInterfacesReverseOrder(targetNode, new LinkedHashSet<>())); String name = forwarder.getName(); Parameter[] forwarderParameters = forwarder.getParameters(); - LinkedHashSet traits = new LinkedHashSet(); - List superForwarders = new LinkedList(); + LinkedHashSet traits = new LinkedHashSet<>(); + List superForwarders = new LinkedList<>(); for (ClassNode node : interfaces) { if (Traits.isTrait(node)) { MethodNode method = node.getDeclaredMethod(name, forwarderParameters); @@ -490,14 +467,14 @@ private static void doCreateSuperForwarder(final ClassNode targetNode, final Met for (int i = 0; i < parameters.length; i++) { Parameter parameter = parameters[i]; ClassNode originType = parameter.getOriginType(); - superForwarderParams[i] = new Parameter(correctToGenericsSpecRecurse(genericsSpec, originType), parameter.getName()); + superForwarderParams[i] = new Parameter(GenericsUtils.correctToGenericsSpecRecurse(genericsSpec, originType), parameter.getName()); } for (int i = 0; i < interfacesToGenerateForwarderFor.length; i++) { final ClassNode current = interfacesToGenerateForwarderFor[i]; final ClassNode next = i < interfacesToGenerateForwarderFor.length - 1 ? interfacesToGenerateForwarderFor[i + 1] : null; String forwarderName = Traits.getSuperTraitMethodName(current, forwarderMethod.getName()); if (targetNode.getDeclaredMethod(forwarderName, superForwarderParams) == null) { - ClassNode returnType = correctToGenericsSpecRecurse(genericsSpec, forwarderMethod.getReturnType()); + ClassNode returnType = GenericsUtils.correctToGenericsSpecRecurse(genericsSpec, forwarderMethod.getReturnType()); Statement delegate = next == null ? createSuperFallback(forwarderMethod, returnType) : createDelegatingForwarder(forwarderMethod, next); MethodNode methodNode = addGeneratedMethod(targetNode, forwarderName, Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, returnType, superForwarderParams, ClassNode.EMPTY_ARRAY, delegate); diff --git a/src/main/java/org/codehaus/groovy/transform/trait/Traits.java b/src/main/java/org/codehaus/groovy/transform/trait/Traits.java index d304d0578cf..8a99930e39b 100644 --- a/src/main/java/org/codehaus/groovy/transform/trait/Traits.java +++ b/src/main/java/org/codehaus/groovy/transform/trait/Traits.java @@ -47,8 +47,6 @@ import java.util.LinkedList; import java.util.List; -import static org.codehaus.groovy.ast.ClassHelper.isClassType; - /** * A collection of utility methods used to deal with traits. * @@ -110,7 +108,7 @@ static String remappedFieldName(final ClassNode traitNode, final String name) { } private static ClassNode unwrapOwner(ClassNode owner) { - if (isClassType(owner) && owner.getGenericsTypes() != null && owner.getGenericsTypes().length == 1) { + if (ClassHelper.isClassType(owner) && owner.getGenericsTypes() != null && owner.getGenericsTypes().length == 1) { return owner.getGenericsTypes()[0].getType(); } return owner; @@ -134,22 +132,22 @@ static TraitHelpersTuple findHelpers(final ClassNode trait) { ClassNode staticFieldHelperClassNode = null; Iterator innerClasses = trait.redirect().getInnerClasses(); if (innerClasses != null && innerClasses.hasNext()) { - // trait defined in same source unit + // trait declared in same unit while (innerClasses.hasNext()) { ClassNode icn = innerClasses.next(); - if (icn.getName().endsWith(Traits.FIELD_HELPER)) { + if (icn.getName().endsWith(Traits.TRAIT_HELPER)) { + helperClassNode = icn; + } else if (icn.getName().endsWith(Traits.FIELD_HELPER)) { fieldHelperClassNode = icn; } else if (icn.getName().endsWith(Traits.STATIC_FIELD_HELPER)) { staticFieldHelperClassNode = icn; - } else if (icn.getName().endsWith(Traits.TRAIT_HELPER)) { - helperClassNode = icn; } } } else { // precompiled trait try { - final ClassLoader classLoader = trait.getTypeClass().getClassLoader(); String helperClassName = Traits.helperClassName(trait); + ClassLoader classLoader = trait.getTypeClass().getClassLoader(); helperClassNode = ClassHelper.make(Class.forName(helperClassName, false, classLoader)); try { fieldHelperClassNode = ClassHelper.make(classLoader.loadClass(Traits.fieldHelperClassName(trait))); @@ -158,7 +156,7 @@ static TraitHelpersTuple findHelpers(final ClassNode trait) { // not a problem, the field helpers may be absent } } catch (ClassNotFoundException e) { - throw new GroovyBugError("Couldn't find trait helper classes on compile classpath!",e); + throw new GroovyBugError("Couldn't find trait helper classes on compile classpath!", e); } } return new TraitHelpersTuple(helperClassNode, fieldHelperClassNode, staticFieldHelperClassNode); @@ -179,10 +177,9 @@ public static boolean isTrait(final ClassNode cNode) { * @return true if the classnode represents a trait */ public static boolean isTrait(final Class clazz) { - return clazz!=null && clazz.getAnnotation(Trait.class)!=null; + return clazz != null && clazz.getAnnotation(Trait.class) != null; } - /** * Returns true if the specified class node is annotated with the {@link Trait} interface. * @param cNode a class node @@ -408,5 +405,4 @@ public static List findTraits(final ClassNode cNode) { */ String desc(); } - } diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy index 07f48aff62f..f809fdd148f 100644 --- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy +++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy @@ -2209,7 +2209,7 @@ final class TraitASTTransformationTest { trait Foo extends Serializable {} Foo x = null ''' - assert err =~ 'Trait cannot extend an interface.' + assert err =~ 'A trait cannot extend an interface.' } @Test