diff --git a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java index 68b8d437992..6970dfab1ce 100644 --- a/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java +++ b/src/main/java/org/codehaus/groovy/classgen/InnerClassCompletionVisitor.java @@ -68,6 +68,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS; import static org.codehaus.groovy.ast.tools.GeneralUtils.tryCatchS; 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_PUBLIC; import static org.objectweb.asm.Opcodes.ACC_STATIC; import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC; @@ -101,24 +102,29 @@ protected SourceUnit getSourceUnit() { public void visitClass(final ClassNode node) { classNode = node; thisField = null; - InnerClassNode innerClass = null; - if (!node.isEnum() && !node.isInterface() && node instanceof InnerClassNode) { - innerClass = (InnerClassNode) node; - thisField = innerClass.getField("this$0"); - if (innerClass.getVariableScope() == null && innerClass.getDeclaredConstructors().isEmpty()) { + + if (node.isEnum() || node.isInterface() || isTrait(node.getOuterClass())) return; + + // if the class has an inner class, add methods to support private member access + if (node.getInnerClasses().hasNext()) { + addDispatcherMethods(node); + } + + if (node instanceof InnerClassNode) { + thisField = node.getField("this$0"); + InnerClassNode innerClass = (InnerClassNode) node; + if (innerClass.getVariableScope() == null && node.getDeclaredConstructors().isEmpty()) { // add empty default constructor addGeneratedConstructor(innerClass, ACC_PUBLIC, Parameter.EMPTY_ARRAY, null, null); } - } - if (node.isEnum() || node.isInterface()) return; - // use Iterator.hasNext() to check for available inner classes - if (node.getInnerClasses().hasNext()) addDispatcherMethods(node); - if (innerClass == null) return; - super.visitClass(node); - boolean innerPojo = hasAnnotation(innerClass, ClassHelper.make(POJO.class)) - && hasAnnotation(innerClass, ClassHelper.make(CompileStatic.class)); - if (!innerPojo) { - addMopMethods(innerClass); + + super.visitClass(node); + + boolean innerPojo = hasAnnotation(node, ClassHelper.make(POJO.class)) + && hasAnnotation(node, ClassHelper.make(CompileStatic.class)); + if (!innerPojo) { + addMopMethods(innerClass); + } } } 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..b82460a1b9f 100644 --- a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java +++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java @@ -19,6 +19,8 @@ package org.codehaus.groovy.transform.trait; import groovy.transform.CompilationUnitAware; +import groovy.transform.Sealed; +import groovy.transform.Trait; import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.AnnotatedNode; import org.codehaus.groovy.ast.AnnotationNode; @@ -59,7 +61,7 @@ import java.util.List; import java.util.Set; -import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated; +import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedInnerClass; import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedMethod; import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock; import static org.apache.groovy.util.BeanUtils.capitalize; @@ -72,13 +74,11 @@ import static org.codehaus.groovy.ast.ClassHelper.isWrapperBoolean; import static org.codehaus.groovy.ast.tools.GeneralUtils.args; import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS; -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.fieldX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.params; 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; @@ -123,6 +123,7 @@ public void visit(final ASTNode[] nodes, final SourceUnit source) { ClassNode cNode = (ClassNode) node; if (!checkNotInterface(cNode, Traits.TRAIT_TYPE_NAME)) return; + checkInnerClasses(cNode); checkNoConstructor(cNode); checkExtendsClause(cNode); replaceExtendsByImplements(cNode); @@ -131,6 +132,14 @@ public void visit(final ASTNode[] nodes, final SourceUnit source) { } } + private void checkInnerClasses(final ClassNode cNode) { + for (Iterator it = cNode.getInnerClasses(); it.hasNext(); ) { InnerClassNode ic = it.next(); + if ((ic.getModifiers() & ACC_STATIC) == 0) { + sourceUnit.addError(new SyntaxException("Cannot have non-static inner class inside a trait (" + ic.getName() + ")", ic.getLineNumber(), ic.getColumnNumber())); + } + } + } + private void checkNoConstructor(final ClassNode cNode) { if (!cNode.getDeclaredConstructors().isEmpty()) { addError("Error processing trait '" + cNode.getName() + "'. " + " Constructors are not allowed.", cNode); @@ -164,6 +173,8 @@ public void addDefaultParameterMethods(final ClassNode cn) { } private ClassNode createHelperClass(final ClassNode cNode) { + cNode.setModifiers(ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE); + ClassNode helper = new InnerClassNode( cNode, Traits.helperClassName(cNode), @@ -173,15 +184,14 @@ private ClassNode createHelperClass(final ClassNode cNode) { null ); helper.setStaticClass(true); // GROOVY-7242, GROOVY-7456, etc. - cNode.setModifiers(ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE); - - checkInnerClasses(cNode); - MethodNode initializer = createInitMethod(false, cNode, helper); - MethodNode staticInitializer = createInitMethod(true, cNode, helper); + MethodNode initializer = createInitMethod(false, helper); + MethodNode staticInitializer = createInitMethod(true, helper); // apply the verifier to have the property nodes generated - generatePropertyMethods(cNode); + for (PropertyNode pNode : cNode.getProperties()) { + processProperty(cNode, pNode); + } // prepare fields List fields = new ArrayList<>(); @@ -223,30 +233,26 @@ private ClassNode createHelperClass(final ClassNode cNode) { } // add methods - List methods = new ArrayList<>(cNode.getMethods()); List nonPublicAPIMethods = new ArrayList<>(); List staticInitStatements = null; - for (final MethodNode methodNode : methods) { - boolean declared = methodNode.getDeclaringClass() == cNode; - if (declared) { - if (!methodNode.isSynthetic() && (methodNode.isProtected() || (!methodNode.isPrivate() && !methodNode.isPublic()))) { - sourceUnit.addError(new SyntaxException("Cannot have protected/package-private method in a trait (" + cNode.getName() + "#" + methodNode.getTypeDescriptor() + ")", - methodNode.getLineNumber(), methodNode.getColumnNumber())); - return null; - } - if (!methodNode.isAbstract()) { - MethodNode newMethod = processMethod(cNode, helper, methodNode, fieldHelper, fieldNames); - if (methodNode.isStaticConstructor()) { - staticInitStatements = getCodeAsBlock(newMethod).getStatements(); - } else { - // add non-abstract methods; abstract methods covered from trait interface - helper.addMethod(newMethod); - } - } - if (methodNode.isPrivate() || methodNode.isStatic()) { - nonPublicAPIMethods.add(methodNode); + for (MethodNode methodNode : cNode.getMethods()) { + if (!methodNode.isSynthetic() && (methodNode.isProtected() || methodNode.isPackageScope())) { + sourceUnit.addError(new SyntaxException("Cannot have protected/package-private method in a trait (" + cNode.getName() + "#" + methodNode.getTypeDescriptor() + ")", + methodNode.getLineNumber(), methodNode.getColumnNumber())); + return null; + } + if (!methodNode.isAbstract()) { + MethodNode newMethod = processMethod(cNode, helper, methodNode, fieldHelper, fieldNames); + if (methodNode.isStaticConstructor()) { + staticInitStatements = getCodeAsBlock(newMethod).getStatements(); + } else { + // add non-abstract methods; abstract methods covered from trait interface + helper.addMethod(newMethod); } } + if (methodNode.isPrivate() || methodNode.isStatic()) { + nonPublicAPIMethods.add(methodNode); + } } // remove methods which should not appear in the trait interface @@ -273,23 +279,19 @@ private ClassNode createHelperClass(final ClassNode cNode) { // clear properties to avoid generation of methods cNode.getProperties().clear(); - // copy annotations - copyClassAnnotations(cNode, helper); - markAsGenerated(cNode, helper); - fields = new ArrayList<>(cNode.getFields()); // reuse the full list of fields for (FieldNode field : fields) { cNode.removeField(field.getName()); } - // visit AST xforms + copyClassAnnotations(helper); registerASTTransformations(helper); - sourceUnit.getAST().addClass(helper); + addGeneratedInnerClass(cNode, helper); if (fieldHelper != null) { - sourceUnit.getAST().addClass(fieldHelper); + addGeneratedInnerClass(cNode, fieldHelper); if (staticFieldHelper != null) { - sourceUnit.getAST().addClass(staticFieldHelper); + addGeneratedInnerClass(cNode, staticFieldHelper); } } @@ -301,6 +303,7 @@ private ClassNode createHelperClass(final ClassNode cNode) { resolveScope(staticFieldHelper); } } + return helper; } @@ -319,23 +322,37 @@ private void resolveScope(final ClassNode cNode) { new VariableScopeVisitor(sourceUnit).visitClass(cNode); } - private static BlockStatement getBlockStatement(final MethodNode targetMethod, final Statement code) { - BlockStatement blockStmt; - if (code instanceof BlockStatement) { - blockStmt = (BlockStatement) code; - } else { - blockStmt = block(code); - targetMethod.setCode(blockStmt); + /** + * Copies annotations from the trait to the helper, excluding non-applicable + * items such as {@link Trait @Trait} and {@link Sealed @Sealed}. + */ + private static void copyClassAnnotations(final ClassNode helper) { + for (AnnotationNode annotation : helper.getOuterClass().getAnnotations()) { + ClassNode annotationType = annotation.getClassNode(); + if (!annotationType.equals(Traits.TRAIT_CLASSNODE) + && !annotationType.equals(SEALED_TYPE)) { + helper.addAnnotation(annotation); + } } - return blockStmt; } - private static MethodNode createInitMethod(final boolean isStatic, final ClassNode cNode, final ClassNode helper) { + private /****/ void registerASTTransformations(final ClassNode helper) { + ASTTransformationVisitor.addNewPhaseOperation(compilationUnit, sourceUnit, helper); + // perform an additional operation which has to be done *after* static type checking + compilationUnit.addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> { + if (classNode == helper) { + GroovyClassVisitor visitor = new PostTypeCheckingExpressionReplacer(source); + visitor.visitClass(helper); + } + }, CompilePhase.INSTRUCTION_SELECTION.getPhaseNumber()); + } + + private static MethodNode createInitMethod(final boolean isStatic, final ClassNode helper) { MethodNode initializer = new MethodNode( isStatic ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, VOID_TYPE, - new Parameter[]{createSelfParameter(cNode, isStatic)}, + new Parameter[]{createSelfParameter(helper.getOuterClass(), isStatic)}, ClassNode.EMPTY_ARRAY, new BlockStatement() ); @@ -349,49 +366,37 @@ private static MethodNode createInitMethod(final boolean isStatic, final ClassNo return initializer; } - private void registerASTTransformations(final ClassNode helper) { - ASTTransformationVisitor.addNewPhaseOperation(compilationUnit, sourceUnit, helper); - // perform an additional operation which has to be done *after* static type checking - compilationUnit.addPhaseOperation((final SourceUnit source, final GeneratorContext context, final ClassNode classNode) -> { - if (classNode == helper) { - GroovyClassVisitor visitor = new PostTypeCheckingExpressionReplacer(source); - visitor.visitClass(helper); - } - }, CompilePhase.INSTRUCTION_SELECTION.getPhaseNumber()); - } - - /** - * Copies annotations from the trait to the helper, excluding non-applicable - * items such as {@code @Trait} and {@code @Sealed}. - * - * @param cNode the trait class node - * @param helper the helper class node - */ - private static void copyClassAnnotations(final ClassNode cNode, final ClassNode helper) { - for (AnnotationNode annotation : cNode.getAnnotations()) { - ClassNode annotationType = annotation.getClassNode(); - if (!annotationType.equals(Traits.TRAIT_CLASSNODE) - && !annotationType.equals(SEALED_TYPE)) { - helper.addAnnotation(annotation); - } + private static ClassNode createReceiverType(final boolean isStatic, final ClassNode cNode) { + ClassNode type; + if (isStatic) { + // Class + type = GenericsUtils.makeClassSafe0(CLASS_Type, new GenericsType(cNode)); + } else { + // TraitClass + type = cNode; } + return type; } - private void checkInnerClasses(final ClassNode cNode) { - for (Iterator it = cNode.getInnerClasses(); it.hasNext(); ) { - InnerClassNode origin = it.next(); - if ((origin.getModifiers() & ACC_STATIC) == 0) { - sourceUnit.addError(new SyntaxException("Cannot have non-static inner class inside a trait (" + origin.getName() + ")", origin.getLineNumber(), origin.getColumnNumber())); - } - } + private static Parameter createSelfParameter(final ClassNode cNode, final boolean isStatic) { + ClassNode type = createReceiverType(isStatic, cNode.getPlainNodeReference()); + return new Parameter(type, isStatic ? Traits.STATIC_THIS_OBJECT : Traits.THIS_OBJECT); } - private static void generatePropertyMethods(final ClassNode cNode) { - for (PropertyNode node : cNode.getProperties()) { - processProperty(cNode, node); + private static BlockStatement getBlockStatement(final MethodNode initMethod, final Statement initCode) { + BlockStatement block; + if (initCode instanceof BlockStatement) { + block = (BlockStatement) initCode; + } else { + block = new BlockStatement(); + block.addStatement(initCode); + initMethod.setCode(block); } + return block; } + // + /** * Mostly copied from the {@link Verifier} class but does *not* generate bytecode. */ @@ -441,7 +446,7 @@ && methodNeedsReplacement(cNode, setter)) { Parameter setterParameter = new Parameter(node.getType(), name); var.setAccessedVariable(setterParameter); - MethodNode setter = new MethodNode(setterName, propNodeModifiers, VOID_TYPE, params(setterParameter), ClassNode.EMPTY_ARRAY, setterBlock); + MethodNode setter = new MethodNode(setterName, propNodeModifiers, VOID_TYPE, new Parameter[]{setterParameter}, ClassNode.EMPTY_ARRAY, setterBlock); setter.setSynthetic(true); addGeneratedMethod(cNode, setter); } @@ -579,14 +584,18 @@ private MethodNode processMethod(final ClassNode traitClass, final ClassNode tra methodNode.getExceptions(), processBody(varX(newParams[0]), methodNode.getCode(), traitClass, traitHelperClass, fieldHelper, knownFields) ); - mNode.setSourcePosition(methodNode); - mNode.addAnnotations(filterAnnotations(methodNode.getAnnotations())); - mNode.setGenericsTypes(methodNode.getGenericsTypes()); + for (AnnotationNode annotation : methodNode.getAnnotations()) { + if (!annotation.getClassNode().equals(OVERRIDE_TYPE)) { + mNode.addAnnotation(annotation); + } + } if (methodNode.isAbstract()) { mNode.setModifiers(ACC_PUBLIC | ACC_ABSTRACT); } else { methodNode.addAnnotation(new AnnotationNode(Traits.IMPLEMENTED_CLASSNODE)); } + mNode.setGenericsTypes(methodNode.getGenericsTypes()); + mNode.setSourcePosition(methodNode); methodNode.setCode(null); if (!methodNode.isPrivate() && !methodNode.isStatic()) { @@ -595,34 +604,6 @@ private MethodNode processMethod(final ClassNode traitClass, final ClassNode tra return mNode; } - private static List filterAnnotations(final List annotations) { - List result = new ArrayList<>(annotations.size()); - for (AnnotationNode annotation : annotations) { - if (!annotation.getClassNode().equals(OVERRIDE_TYPE)) { - result.add(annotation); - } - } - return result; - } - - private static Parameter createSelfParameter(final ClassNode traitClass, boolean isStatic) { - final ClassNode rawType = traitClass.getPlainNodeReference(); - ClassNode type = createReceiverType(isStatic, rawType); - return new Parameter(type, isStatic ? Traits.STATIC_THIS_OBJECT : Traits.THIS_OBJECT); - } - - private static ClassNode createReceiverType(final boolean isStatic, final ClassNode rawType) { - ClassNode type; - if (isStatic) { - // Class - type = GenericsUtils.makeClassSafe0(CLASS_Type, new GenericsType(rawType)); - } else { - // TraitClass - type = rawType; - } - return type; - } - private Statement processBody(final VariableExpression thisObject, final Statement code, final ClassNode trait, final ClassNode traitHelper, final ClassNode fieldHelper, final Collection knownFields) { if (code != null) { code.visit(new NAryOperationRewriter(sourceUnit, knownFields)); 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..0804b6dfe4e 100644 --- a/src/main/java/org/codehaus/groovy/transform/trait/Traits.java +++ b/src/main/java/org/codehaus/groovy/transform/trait/Traits.java @@ -179,10 +179,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 diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy index ef37a59a72b..6e2da895132 100644 --- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy +++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy @@ -22,6 +22,7 @@ import groovy.transform.SelfType import org.codehaus.groovy.ast.ClassHelper import org.codehaus.groovy.ast.expr.ClassExpression import org.codehaus.groovy.ast.expr.ListExpression +import org.junit.Ignore import org.junit.Test import static groovy.test.GroovyAssert.assertScript @@ -418,100 +419,6 @@ final class TraitASTTransformationTest { ''' } - @Test - void testClassImplementingTraitWithSameMethod() { - assertScript shell, ''' - trait A { - int foo() { 1 } - } - trait B { - int foo() { 2 } - } - class AB implements A,B { - } - def x = new AB() - assert x.foo() == 2 // default order, B is first - ''' - - assertScript shell, ''' - trait A { - int foo() { 1 } - } - trait B { - int foo() { 2 } - } - class AB implements B,A { - } - def x = new AB() - assert x.foo() == 1 // default order, A is first - ''' - - assertScript shell, ''' - trait A { - int foo() { 1 } - } - trait B { - int foo() { 2 } - } - class AB implements A,B { - int foo() { - A.super.foo() // explicit use of A - } - } - def x = new AB() - assert x.foo() == 1 - ''' - - assertScript shell, ''' - trait A { - int foo() { 1 } - } - trait B { - int foo() { 2 } - } - class AB implements A,B { - int foo() { - A.super.foo() // explicit take of A - } - } - def x = new AB() - assert x.foo() == 1 - ''' - - // make sure it is compatible with @CompileStatic - assertScript shell, ''' - trait A { - int foo() { 1 } - } - trait B { - int foo() { 2 } - } - @CompileStatic - class AB implements A,B { - int foo() { - B.super.foo() - } - } - def x = new AB() - assert x.foo() == 2 - ''' - - // GROOVY-10144 - assertScript shell, ''' - trait T { - def m() { 'T' } - } - class C implements T { - @Override - def m() { - 'C' + T.super.m() - } - } - String result = new C().m() - assert result == 'CT' - ''' - } - @Test void testTraitWithGenerics1() { for (mode in ['','@TypeChecked','@CompileStatic']) { @@ -554,7 +461,8 @@ final class TraitASTTransformationTest { } } - @Test // GROOVY-9760 + // GROOVY-9760 + @Test void testTraitWithGenerics3() { for (mode in ['','@TypeChecked','@CompileStatic']) { assertScript shell, """ @@ -574,7 +482,8 @@ final class TraitASTTransformationTest { } } - @Test // GROOVY-11012 + // GROOVY-11012 + @Test void testTraitWithGenerics4() { for (mode in ['','@TypeChecked','@CompileStatic']) { assertScript shell, """ @@ -1030,7 +939,126 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-9255 + @Test + void testTraitMethodOverloadAndOverride() { + assertScript shell, ''' + trait A { + int foo() { 1 } + } + trait B { + int foo() { 2 } + } + class AB implements A,B { + } + + def x = new AB() + assert x.foo() == 2 // default order, B is first + ''' + + assertScript shell, ''' + trait A { + int foo() { 1 } + } + trait B { + int foo() { 2 } + } + class BA implements B,A { + } + + def x = new BA() + assert x.foo() == 1 // default order, A is first + ''' + + assertScript shell, ''' + trait A { + int foo() { 1 } + } + trait B { + int foo() { 2 } + } + class AB implements A,B { + int foo() { + A.super.foo() // explicit delegation to A + } + } + + def x = new AB() + assert x.foo() == 1 + ''' + + assertScript shell, ''' + trait A { + int foo() { 1 } + } + trait B { + int foo() { 2 } + } + class AB implements A,B { + int foo() { + A.super.foo() // explicit delegation to A + } + } + + def x = new AB() + assert x.foo() == 1 + ''' + + // make sure it is compatible with @CompileStatic + assertScript shell, ''' + trait A { + int foo() { 1 } + } + trait B { + int foo() { 2 } + } + @CompileStatic + class AB implements A,B { + int foo() { + B.super.foo() + } + } + + def x = new AB() + assert x.foo() == 2 + ''' + + assertScript shell, ''' + trait A { + int foo() { 1 } + } + trait B extends A { + int foo() { + A.super.foo() * 2 + } + } + class C implements B { + } + + def c = new C() + assert c.foo() == 2 + ''' + + assertScript shell, ''' + @CompileStatic + trait A { + int foo() { 1 } + } + @CompileStatic + trait B extends A { + int foo() { + A.super.foo() * 2 + } + } + class C implements B { + } + + def c = new C() + assert c.foo() == 2 + ''' + } + + // GROOVY-9255 + @Test void testTraitSuperPropertyGet() { assertScript shell, ''' trait T { @@ -1081,7 +1109,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-9672 + // GROOVY-9672 + @Test void testTraitSuperPropertyGetStatic() { assertScript shell, ''' trait T { @@ -1204,7 +1233,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-9672 + // GROOVY-9672 + @Test void testTraitSuperPropertySetStatic() { assertScript shell, ''' trait T { @@ -1261,7 +1291,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-9673 + // GROOVY-9673 + @Test void testTraitSuperPropertySetWithOverloads() { assertScript shell, ''' trait T { @@ -1298,7 +1329,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-9672 + // GROOVY-9672 + @Test void testTraitSuperCallStatic() { assertScript shell, ''' trait A { @@ -1316,40 +1348,8 @@ final class TraitASTTransformationTest { ''' } + // GROOVY-9256 @Test - void testTraitSuperCallWhenExtendingAnotherTrait() { - assertScript shell, ''' - trait Foo { - int foo() { 1 } - } - trait Bar extends Foo { - int foo() { - 2*Foo.super.foo() - } - } - class Baz implements Bar {} - def b = new Baz() - assert b.foo() == 2 - ''' - - assertScript shell, ''' - @CompileStatic - trait Foo { - int foo() { 1 } - } - @CompileStatic - trait Bar extends Foo { - int foo() { - 2*Foo.super.foo() - } - } - class Baz implements Bar {} - def b = new Baz() - assert b.foo() == 2 - ''' - } - - @Test // GROOVY-9256 void testTraitSuperCallWithinClosure() { assertScript shell, ''' trait T { @@ -1550,7 +1550,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8243 + // GROOVY-8243 + @Test void testSAMCoercion5() { assertScript shell, ''' trait T { @@ -1568,7 +1569,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8244 + // GROOVY-8244 + @Test void testSAMCoercion6() { assertScript shell, ''' trait T { @@ -1781,7 +1783,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-7288 + // GROOVY-7288 + @Test void testClassWithTraitDelegate() { assertScript shell, ''' trait T { @@ -1801,7 +1804,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-9739 + // GROOVY-9739 + @Test void testTraitExtendsTraitWithDelegate() { assertScript shell, ''' class Main implements ClientSupport { @@ -1832,7 +1836,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-9901 + // GROOVY-9901 + @Test void testTraitWithMemozied() { assertScript shell, ''' trait Foo { @@ -1875,7 +1880,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-10553 + // GROOVY-10553 + @Test void testAnnotationShouldBeCarriedOver2() { assertScript shell, ''' import java.lang.annotation.* @@ -2099,9 +2105,9 @@ final class TraitASTTransformationTest { ''' } + // GROOVY-6672 @Test void testTraitShouldNotBeAllowedToExtendInterface() { - // GROOVY-6672 def err = shouldFail shell, ''' trait Foo extends Serializable {} Foo x = null @@ -2254,7 +2260,8 @@ final class TraitASTTransformationTest { assert err =~ 'Prefix expressions on trait fields/properties are not supported in traits' } - @Test // GROOVY-6691 + // GROOVY-6691 + @Test void testTraitImplementingGenericSuperTrait() { assertScript shell, ''' class App {} @@ -2656,7 +2663,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-6708 + // GROOVY-6708 + @Test void testCovariantReturnTypeWithGenericsInheritance() { assertScript shell, ''' trait Top { @@ -2742,7 +2750,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-7058 + // GROOVY-7058 + @Test void testShouldNotThrowNPEBecauseOfIncompleteGenericsTypeInformation() { assertScript shell, ''' class Project { Task task(String name, Map args) {} } @@ -2761,7 +2770,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-7123 + // GROOVY-7123 + @Test void testHelperSetterShouldNotReturnVoid() { assertScript shell, ''' trait A { @@ -2817,7 +2827,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-10767 + // GROOVY-10767 + @Test void testSimpleSelfTypeInSubTrait2() { assertScript shell, ''' trait A { @@ -3009,7 +3020,8 @@ final class TraitASTTransformationTest { } } - @Test // GROOVY-10521 + // GROOVY-10521 + @Test void testVariadicMethodOfPrecompiledTrait() { assertScript shell, """import org.codehaus.groovy.ast.* class CT implements ${T10521.name} { @@ -3043,7 +3055,8 @@ final class TraitASTTransformationTest { """ } - @Test // GROOVY-7287 + // GROOVY-7287 + @Test void testTraitWithMethodLevelGenericsShadowing1() { assertScript shell, ''' trait Configurable { @@ -3090,7 +3103,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-7287 + // GROOVY-7287 + @Test void testTraitWithMethodLevelGenericsShadowing2() { assertScript shell, ''' trait SomeTrait { @@ -3114,7 +3128,8 @@ final class TraitASTTransformationTest { } } - @Test // GROOVY-7297 + // GROOVY-7297 + @Test void testMethodLevelGenericsFromPrecompiledClass() { assertScript shell, """ class C implements ${T7297.name} { @@ -3125,7 +3140,8 @@ final class TraitASTTransformationTest { """ } - @Test // GROOVY-9763 + // GROOVY-9763 + @Test void testTraitWithStaticMethodGenericsSC() { assertScript shell, ''' trait T { @@ -3143,7 +3159,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8281 + // GROOVY-8281 + @Test void testFinalFieldsDependency() { assertScript shell, ''' trait MyTrait { @@ -3158,7 +3175,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8282 + // GROOVY-8282 + @Test void testBareNamedArgumentPrivateMethodCall() { assertScript shell, ''' trait BugReproduction { @@ -3176,7 +3194,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8730 + // GROOVY-8730 + @Test void testAbstractMethodsNotNeededInHelperClass() { assertScript shell, ''' import static groovy.test.GroovyAssert.shouldFail @@ -3195,7 +3214,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8731 + // GROOVY-8731 + @Test void testStaticMethodsIgnoredWhenExistingInstanceMethodsFound() { assertScript shell, ''' trait StaticFooBarBaz { @@ -3220,7 +3240,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-6716 + // GROOVY-6716 + @Test void testAnonymousInnerClassStyleTraitUsage() { assertScript shell, ''' interface Foo { def foo() } @@ -3237,7 +3258,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8722 + // GROOVY-8722 + @Test void testFinalModifierSupport() { assertScript shell, ''' import static java.lang.reflect.Modifier.isFinal @@ -3292,7 +3314,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8880 + // GROOVY-8880 + @Test void testTraitWithInitBlock() { assertScript shell, ''' trait MyTrait { @@ -3312,7 +3335,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8880 + // GROOVY-8880 + @Test void testTraitWithStaticInitBlock() { assertScript shell, ''' trait MyTrait { @@ -3330,7 +3354,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8892 + // GROOVY-8892 + @Test void testTraitWithStaticInitBlockWithAndWithoutProps() { assertScript shell, ''' class Counter { @@ -3354,7 +3379,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8954 + // GROOVY-8954 + @Test void testTraitWithPropertyAlsoFromInterfaceSC() { assertScript shell, ''' interface DomainProp { @@ -3374,7 +3400,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8272 + // GROOVY-8272 + @Test void testTraitAccessToInheritedStaticMethods() { assertScript shell, ''' @CompileStatic @@ -3397,7 +3424,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-10312 + // GROOVY-10312 + @Test void testTraitAccessToInheritedStaticMethods2() { assertScript shell, ''' trait Foo { @@ -3427,7 +3455,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-10312 + // GROOVY-10312 + @Test void testTraitAccessToInheritedStaticMethods3() { assertScript shell, ''' interface Foo { @@ -3455,7 +3484,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-9386 + // GROOVY-9386 + @Test void testTraitPropertyInitializedByTap() { assertScript shell, ''' class P { @@ -3474,7 +3504,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-9386 + // GROOVY-9386 + @Test void testTraitPropertyInitializedByWith() { assertScript shell, ''' class P { @@ -3493,7 +3524,8 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-8000 + // GROOVY-8000 + @Test void testTraitMultiLevelGenerics() { assertScript shell, ''' trait TopTrait { X getSomeThing() {} @@ -3522,17 +3554,20 @@ final class TraitASTTransformationTest { ''' } - @Test // GROOVY-9660 + // GROOVY-9660 + @Test void testAsGenericsParam() { assertScript shell, ''' trait Data {} class TestData implements Data {} class AbstractData{ D data } + new AbstractData() ''' } // GROOVY-10598 + @Ignore @Test void testAssignOperators() { assertScript shell, ''' trait T { @@ -3546,6 +3581,7 @@ final class TraitASTTransformationTest { def var = null } } + new C().test() ''' }