Skip to content

Commit

Permalink
GROOVY-11299: prep work
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Jan 28, 2024
1 parent c8f2eb8 commit 482a229
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 41 deletions.
27 changes: 14 additions & 13 deletions src/main/java/org/codehaus/groovy/ast/ClassNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ void remove(Object key, MethodNode value) {
private Map<String, FieldNode> fieldIndex;
private ClassNode superClass;
protected boolean isPrimaryNode;
// TODO: initialize for primary nodes only!!
// TODO: initialize for primary nodes only!
private List<ClassNode> permittedSubclasses = new ArrayList<>();
private List<RecordComponentNode> recordComponents = Collections.emptyList();

Expand Down Expand Up @@ -865,9 +865,9 @@ public List<Statement> getObjectInitializerStatements() {
}

/**
* 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<MethodNode> getDeclaredMethods(String name) {
Expand All @@ -878,25 +878,26 @@ public List<MethodNode> 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<MethodNode> getMethods(String name) {
List<MethodNode> result = new ArrayList<>();
List<MethodNode> 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)) {
Expand All @@ -909,9 +910,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)) {
Expand Down
20 changes: 10 additions & 10 deletions src/main/java/org/codehaus/groovy/classgen/InnerClassVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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_MANDATED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
Expand Down Expand Up @@ -86,12 +86,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()) {
var upperClass = node.getUnresolvedSuperClass(false);
if (upperClass.isInterface() || isTrait(upperClass)) {
node.addInterface(upperClass);
node.setUnresolvedSuperClass(ClassHelper.OBJECT_TYPE);
}
}
}

Expand Down Expand Up @@ -151,9 +151,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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
13 changes: 6 additions & 7 deletions src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -946,15 +946,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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,23 +154,22 @@ private void checkInnerClasses(final ClassNode cNode) {

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);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,6 @@ final class TraitASTTransformationTest {
private String msg = 'foo'
abstract String bar()
public String foo() { bar()+msg }
}
@CompileStatic
class A implements Foo {
Expand Down Expand Up @@ -884,7 +883,7 @@ final class TraitASTTransformationTest {
void update(String msg ) { message = msg}
}
@CompileStatic
class Foo implements TestTrait{
class Foo implements TestTrait {
}
@CompileStatic
Expand Down Expand Up @@ -1016,6 +1015,21 @@ final class TraitASTTransformationTest {
assert c.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'
'''

// GROOVY-8587
assertScript shell, '''
trait A {
Expand Down Expand Up @@ -2192,7 +2206,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
Expand Down

0 comments on commit 482a229

Please sign in to comment.