This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push: new 84b03c4 GROOVY-10102: trait SelfType: continue checking self type for self types 84b03c4 is described below commit 84b03c439fc4d5fa73f89210882b62a131588263 Author: Eric Milles <eric.mil...@thomsonreuters.com> AuthorDate: Wed May 26 09:48:31 2021 -0500 GROOVY-10102: trait SelfType: continue checking self type for self types --- .../codehaus/groovy/transform/trait/Traits.java | 46 ++++++++--------- src/test/groovy/transform/stc/BugsSTCTest.groovy | 57 +++++++++++++++++----- 2 files changed, 69 insertions(+), 34 deletions(-) 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 2dfb5e1..8edeb25 100644 --- a/src/main/java/org/codehaus/groovy/transform/trait/Traits.java +++ b/src/main/java/org/codehaus/groovy/transform/trait/Traits.java @@ -300,13 +300,12 @@ public abstract class Traits { * Collects all the self types that a type should extend or implement, given * the traits is implements. Collects from interfaces and superclasses too. * @param receiver a class node that may implement a trait - * @param selfTypes a collection where the list of self types will be written - * @return the selfTypes collection itself + * @param selfTypes a set where the self types will be put + * @return the {@code selfTypes} collection + * * @since 2.4.0 */ - public static LinkedHashSet<ClassNode> collectSelfTypes( - ClassNode receiver, - LinkedHashSet<ClassNode> selfTypes) { + public static LinkedHashSet<ClassNode> collectSelfTypes(final ClassNode receiver, final LinkedHashSet<ClassNode> selfTypes) { return collectSelfTypes(receiver, selfTypes, true, true); } @@ -314,28 +313,30 @@ public abstract class Traits { * Collects all the self types that a type should extend or implement, given * the traits is implements. * @param receiver a class node that may implement a trait - * @param selfTypes a collection where the list of self types will be written + * @param selfTypes a set where the self types will be put * @param checkInterfaces should the interfaces that the node implements be collected too - * @param checkSuper should we collect from the superclass too - * @return the selfTypes collection itself + * @param checkSuperClass should we collect from the superclass too + * @return the {@code selfTypes} collection + * * @since 2.4.0 */ - public static LinkedHashSet<ClassNode> collectSelfTypes( - ClassNode receiver, - LinkedHashSet<ClassNode> selfTypes, - boolean checkInterfaces, - boolean checkSuper) { + public static LinkedHashSet<ClassNode> collectSelfTypes(final ClassNode receiver, final LinkedHashSet<ClassNode> selfTypes, final boolean checkInterfaces, final boolean checkSuperClass) { if (Traits.isTrait(receiver)) { List<AnnotationNode> annotations = receiver.getAnnotations(SELFTYPE_CLASSNODE); for (AnnotationNode annotation : annotations) { Expression value = annotation.getMember("value"); if (value instanceof ClassExpression) { - selfTypes.add(value.getType()); + ClassNode selfType = value.getType(); + if (selfTypes.add(selfType)) { + collectSelfTypes(selfType, selfTypes, checkInterfaces, checkSuperClass); + } } else if (value instanceof ListExpression) { - List<Expression> expressions = ((ListExpression) value).getExpressions(); - for (Expression expression : expressions) { + for (Expression expression : ((ListExpression) value).getExpressions()) { if (expression instanceof ClassExpression) { - selfTypes.add(expression.getType()); + ClassNode selfType = expression.getType(); + if (selfTypes.add(selfType)) { + collectSelfTypes(selfType, selfTypes, checkInterfaces, checkSuperClass); + } } } } @@ -343,14 +344,15 @@ public abstract class Traits { } if (checkInterfaces) { ClassNode[] interfaces = receiver.getInterfaces(); - for (ClassNode anInterface : interfaces) { - collectSelfTypes(anInterface, selfTypes, true, checkSuper); + for (ClassNode interFace : interfaces) { + if (!selfTypes.contains(interFace)) { + collectSelfTypes(interFace, selfTypes, true, checkSuperClass); + } } } - - if (checkSuper) { + if (checkSuperClass) { ClassNode superClass = receiver.getSuperClass(); - if (superClass != null) { + if (superClass != null && !ClassHelper.isObjectType(superClass)) { collectSelfTypes(superClass, selfTypes, checkInterfaces, true); } } diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy b/src/test/groovy/transform/stc/BugsSTCTest.groovy index d9ad1c9..0781a77 100644 --- a/src/test/groovy/transform/stc/BugsSTCTest.groovy +++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy @@ -103,6 +103,39 @@ class BugsSTCTest extends StaticTypeCheckingTestCase { ''', 'Cannot find matching method <UnionType:C+T>#x' } + // GROOVY-10102 + void testShouldDetectValidMethodUseWithinTraitWithCompileStaticAndSelfType() { + assertScript ''' + import groovy.transform.* + + trait A { + String foo = 'foo' + String m(String s, Closure x) { + s + x() + } + } + @SelfType(A) + trait B { + } + @SelfType(B) + trait C { + } + @CompileStatic + @SelfType(C) + trait D { + def test() { + String s = foo + m(s) { + s.toUpperCase() + } + } + } + + class E implements A, B, C, D { } + assert new E().test() == 'fooFOO' + ''' + } + // GROOVY-10106 void testCallStaticOrPrivateMethodInTraitFieldInitializer() { ['private', 'static', 'private static'].each { mods -> @@ -139,19 +172,19 @@ class BugsSTCTest extends StaticTypeCheckingTestCase { void testGroovy5444() { assertScript ''' - def curr = { System.currentTimeMillis() } - - 5.times { - @ASTTest(phase=INSTRUCTION_SELECTION, value= { - assert node.getNodeMetaData(INFERRED_TYPE) == Long_TYPE - }) - def t0 = curr() - 100000.times { - "echo" - } - println (curr() - t0) - }''' + def millis = { System.currentTimeMillis() } + 5.times { + @ASTTest(phase=INSTRUCTION_SELECTION, value= { + assert node.getNodeMetaData(INFERRED_TYPE) == Long_TYPE + }) + def t0 = millis() + 1000.times { + "echo" + } + def elapsed = millis() - t0 + } + ''' } void testGroovy5487ReturnNull() {