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
commit 2930ead60a3e48977d02593d78242282dfc2ee9b Author: Eric Milles <[email protected]> AuthorDate: Thu Sep 19 14:04:14 2024 -0500 add `getNestHost(ClassNode)` --- .../apache/groovy/ast/tools/ClassNodeUtils.java | 103 +++++++++++++++++---- .../groovy/classgen/AsmClassGenerator.java | 13 +-- .../codehaus/groovy/classgen/GeneratorContext.java | 31 +++---- .../groovy/classgen/asm/WriterController.java | 9 +- .../classgen/asm/sc/StaticInvocationWriter.java | 12 +-- ...icTypesBinaryExpressionMultiTypeDispatcher.java | 4 +- .../transform/stc/StaticTypeCheckingVisitor.java | 12 +-- 7 files changed, 115 insertions(+), 69 deletions(-) diff --git a/src/main/java/org/apache/groovy/ast/tools/ClassNodeUtils.java b/src/main/java/org/apache/groovy/ast/tools/ClassNodeUtils.java index 4020d3dd1a..03e0e9ffcb 100644 --- a/src/main/java/org/apache/groovy/ast/tools/ClassNodeUtils.java +++ b/src/main/java/org/apache/groovy/ast/tools/ClassNodeUtils.java @@ -71,6 +71,8 @@ public class ClassNodeUtils { * * @param cNode the type to format * @return a human-readable version of the type name (java.lang.String[] for example) + * + * @since 2.5.0 */ public static String formatTypeName(final ClassNode cNode) { if (cNode.isArray()) { @@ -94,6 +96,8 @@ public class ClassNodeUtils { * Returns an existing method if one exists or else create a new method and mark it as {@code @Generated}. * * @see ClassNode#addMethod(String, int, ClassNode, Parameter[], ClassNode[], Statement) + * + * @since 2.5.3 */ public static MethodNode addGeneratedMethod(final ClassNode cNode, final String name, final int modifiers, final ClassNode returnType, final Parameter[] parameters, final ClassNode[] exceptions, final Statement code) { @@ -109,6 +113,8 @@ public class ClassNodeUtils { * Adds a method and mark it as {@code @Generated}. * * @see ClassNode#addMethod(MethodNode) + * + * @since 2.5.3 */ public static void addGeneratedMethod(final ClassNode cNode, final MethodNode mNode) { cNode.addMethod(mNode); @@ -119,6 +125,8 @@ public class ClassNodeUtils { * Adds a method and mark it as {@code @Generated}. * * @see ClassNode#addMethod(MethodNode) + * + * @since 3.0.8 */ public static void addGeneratedMethod(final ClassNode cNode, final MethodNode mNode, final boolean skipChecks) { cNode.addMethod(mNode); @@ -129,6 +137,8 @@ public class ClassNodeUtils { * Adds an inner class that is marked as {@code @Generated}. * * @see org.codehaus.groovy.ast.ModuleNode#addClass(ClassNode) + * + * @since 2.5.7 */ public static void addGeneratedInnerClass(final ClassNode cNode, final ClassNode inner) { cNode.getModule().addClass(inner); @@ -139,6 +149,8 @@ public class ClassNodeUtils { * Adds a method that is marked as {@code @Generated}. * * @see ClassNode#addConstructor(int, Parameter[], ClassNode[], Statement) + * + * @since 2.5.3 */ public static ConstructorNode addGeneratedConstructor(final ClassNode classNode, final int modifiers, final Parameter[] parameters, final ClassNode[] exceptions, final Statement code) { ConstructorNode ctorNode = new ConstructorNode(modifiers, parameters, exceptions, code); @@ -150,6 +162,8 @@ public class ClassNodeUtils { * Adds a method that is marked as {@code @Generated}. * * @see ClassNode#addConstructor(ConstructorNode) + * + * @since 2.5.3 */ public static void addGeneratedConstructor(final ClassNode classNode, final ConstructorNode ctorNode) { classNode.addConstructor(ctorNode); @@ -157,10 +171,9 @@ public class ClassNodeUtils { } /** - * Adds methods from the super class. + * Gets methods from the super class. * - * @param cNode The ClassNode - * @return A map of methods + * @since 2.5.0 */ public static Map<String, MethodNode> getDeclaredMethodsFromSuper(final ClassNode cNode) { ClassNode parent = cNode.getSuperClass(); @@ -177,6 +190,8 @@ public class ClassNodeUtils { * * @param cNode The ClassNode * @param methodsMap A map of existing methods to alter + * + * @since 2.5.0 */ public static void addDeclaredMethodsFromInterfaces(final ClassNode cNode, final Map<String, MethodNode> methodsMap) { for (ClassNode iface : cNode.getInterfaces()) { @@ -195,6 +210,8 @@ public class ClassNodeUtils { * * @param cNode The ClassNode * @return A map of methods + * + * @since 2.5.0 */ public static Map<String, MethodNode> getDeclaredMethodsFromInterfaces(final ClassNode cNode) { Map<String, MethodNode> methodsMap = new LinkedHashMap<>(); @@ -208,6 +225,8 @@ public class ClassNodeUtils { * * @param cNode The ClassNode * @param methodsMap A map of existing methods to alter + * + * @since 2.5.0 */ public static void addDeclaredMethodsFromAllInterfaces(final ClassNode cNode, final Map<String, MethodNode> methodsMap) { List<ClassNode> cnInterfaces = Arrays.asList(cNode.getInterfaces()); @@ -221,14 +240,17 @@ public class ClassNodeUtils { } /** - * Returns true if the given method has a possibly matching static method with the given name and arguments. - * Handles default arguments and optionally spread expressions. + * Determines if the given method has a possibly matching static method with + * the given name and arguments. Handles default arguments and (optionally) + * spread expressions. * * @param cNode the ClassNode of interest * @param name the name of the method of interest * @param arguments the arguments to match against * @param trySpread whether to try to account for SpreadExpressions within the arguments * @return {@code true} if a matching method was found. + * + * @since 2.5.0 */ public static boolean hasPossibleStaticMethod(final ClassNode cNode, final String name, final Expression arguments, final boolean trySpread) { int count = 0; boolean foundSpread = false; @@ -290,7 +312,9 @@ public class ClassNodeUtils { } /** - * Returns true if we have a static accessor + * Determines if the given class has the named static property. + * + * @since 2.5.0 */ public static boolean hasPossibleStaticProperty(final ClassNode cNode, final String methodName) { // assume explicit static method call checked first so we can assume a simple check here @@ -308,6 +332,8 @@ public class ClassNodeUtils { * * @param accessorName the accessor name of interest, e.g. getAge * @return the property name, e.g. age, or original if not a valid property accessor name + * + * @since 2.5.0 */ public static String getPropNameForAccessor(final String accessorName) { if (!isValidAccessorName(accessorName)) return accessorName; @@ -316,10 +342,13 @@ public class ClassNodeUtils { } /** - * Detects whether the given accessor name starts with "get", "set" or "is" followed by at least one character. + * Determines if the given accessor name starts with "get", "set" or "is" + * followed by at least one character. * * @param accessorName the accessor name of interest, e.g. getAge * @return true if a valid prefix is found + * + * @since 2.5.0 */ public static boolean isValidAccessorName(final String accessorName) { if (accessorName.startsWith("get") || accessorName.startsWith("is") || accessorName.startsWith("set")) { @@ -330,10 +359,9 @@ public class ClassNodeUtils { } /** - * Check if the type is declared {@code non-sealed} + * Determines if the type is declared {@code non-sealed}. * - * @param cn the type - * @return the check result + * @since 5.0.0 */ public static boolean isNonSealed(final ClassNode cn) { if (cn instanceof DecompiledClassNode) { @@ -355,6 +383,11 @@ public class ClassNodeUtils { return superClass.isSealed() && !(isFinal(cn.getModifiers()) || cn.isSealed()); } + /** + * Determines if the given class has the named static property. + * + * @since 2.5.0 + */ public static boolean hasStaticProperty(final ClassNode cNode, final String propName) { PropertyNode found = getStaticProperty(cNode, propName); if (found == null) { @@ -366,12 +399,13 @@ public class ClassNodeUtils { } /** - * Detects whether a static property with the given name is within the class - * or a super class. + * Finds static property within the class or super class. * * @param cNode the ClassNode of interest * @param propName the property name * @return the static property if found or else null + * + * @since 2.5.0 */ public static PropertyNode getStaticProperty(final ClassNode cNode, final String propName) { ClassNode classNode = cNode; @@ -387,17 +421,33 @@ public class ClassNodeUtils { } /** - * Detects whether a given ClassNode is an inner class (non-static). + * Returns the nest host of the given class, which may be the class itself. + * + * @since 5.0.0 + */ + public static ClassNode getNestHost(ClassNode cNode) { + while (cNode.getOuterClass() != null) { + cNode = cNode.getOuterClass(); + } + return cNode; + } + + /** + * Determines if the given ClassNode is a non-static inner class. * * @param cNode the ClassNode of interest * @return true if the given node is a (non-static) inner class, else false + * + * @since 2.5.0 */ public static boolean isInnerClass(final ClassNode cNode) { return cNode.getOuterClass() != null && !Modifier.isStatic(cNode.getModifiers()); } /** - * Checks if the source ClassNode is compatible with the target ClassNode + * Determines if the source ClassNode is compatible with the target ClassNode. + * + * @since 4.0.0 */ public static boolean isCompatibleWith(ClassNode source, ClassNode target) { if (source.equals(target)) return true; @@ -411,6 +461,11 @@ public class ClassNodeUtils { && (source.isDerivedFrom(target) || source.implementsInterface(target)); } + /** + * Determines if the given ClassNode declares a zero argument constructor. + * + * @since 2.5.0 + */ public static boolean hasNoArgConstructor(final ClassNode cNode) { List<ConstructorNode> constructors = cNode.getDeclaredConstructors(); for (ConstructorNode next : constructors) { @@ -422,11 +477,13 @@ public class ClassNodeUtils { } /** - * Determines if an explicit (non-generated) constructor is in the class. + * Determines if the given ClassNode declares an explicit (non-generated) constructor. * * @param xform if non-null, add an error if an explicit constructor is found * @param cNode the type of the containing class * @return true if an explicit (non-generated) constructor was found + * + * @since 2.5.0 */ public static boolean hasExplicitConstructor(final AbstractASTTransformation xform, final ClassNode cNode) { List<ConstructorNode> declaredConstructors = cNode.getDeclaredConstructors(); @@ -451,7 +508,8 @@ public class ClassNodeUtils { * @param first a ClassNode * @param second a ClassNode * @return true if both given nodes have the same package name - * @throws NullPointerException if either of the given nodes are null + * + * @since 2.5.0 */ public static boolean samePackageName(final ClassNode first, final ClassNode second) { return Objects.equals(first.getPackageName(), second.getPackageName()); @@ -524,10 +582,15 @@ public class ClassNodeUtils { return null; } - public static boolean isSubtype(final ClassNode maybeSuperclassOrInterface, final ClassNode candidateChild) { - return maybeSuperclassOrInterface.isInterface() || candidateChild.isInterface() - ? isOrImplements(candidateChild, maybeSuperclassOrInterface) - : candidateChild.isDerivedFrom(maybeSuperclassOrInterface); + /** + * Determines if given class is, extends or implements a class or interface. + * + * @since 4.0.16 + */ + public static boolean isSubtype(final ClassNode maybeExtendedOrImplemented, final ClassNode cNode) { + return maybeExtendedOrImplemented.isInterface() || cNode.isInterface() + ? isOrImplements(cNode, maybeExtendedOrImplemented) + : cNode.isDerivedFrom(maybeExtendedOrImplemented); } //-------------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java index b25c542500..da58703feb 100644 --- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java +++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java @@ -134,6 +134,7 @@ import java.util.Optional; import java.util.function.Consumer; import static org.apache.groovy.ast.tools.ClassNodeUtils.getField; +import static org.apache.groovy.ast.tools.ClassNodeUtils.getNestHost; import static org.apache.groovy.ast.tools.ExpressionUtils.isNullConstant; import static org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression; import static org.codehaus.groovy.ast.ClassHelper.isClassType; @@ -329,7 +330,7 @@ public class AsmClassGenerator extends ClassGenerator { if (classNode instanceof InnerClassNode && !(classNode instanceof InterfaceHelperClassNode)) { makeInnerClassEntry(classNode); // GROOVY-4649, et al. - ClassNode nestHost = controller.getOutermostClass(); // GROOVY-10687 + ClassNode nestHost = getNestHost(classNode); // GROOVY-10687 classVisitor.visitNestHost(BytecodeHelper.getClassInternalName(nestHost)); MethodNode enclosingMethod = classNode.getEnclosingMethod(); @@ -379,7 +380,7 @@ public class AsmClassGenerator extends ClassGenerator { } // GROOVY-10687 if (classNode.getOuterClass() == null && classNode.getInnerClasses().hasNext()) { - makeNestMatesEntries(classNode); + makeNestmateEntries(classNode); } // GROOVY-4649, GROOVY-6750, GROOVY-6808 for (Iterator<InnerClassNode> it = classNode.getInnerClasses(); it.hasNext(); ) { @@ -451,11 +452,11 @@ public class AsmClassGenerator extends ClassGenerator { classVisitor.visitInnerClass(innerClassInternalName, outerClassInternalName, innerClassName, modifiers); } - private void makeNestMatesEntries(final ClassNode classNode) { + private void makeNestmateEntries(final ClassNode classNode) { for (Iterator<InnerClassNode> it = classNode.getInnerClasses(); it.hasNext(); ) { ClassNode innerClass = it.next(); classVisitor.visitNestMember(BytecodeHelper.getClassInternalName(innerClass)); - makeNestMatesEntries(innerClass); + makeNestmateEntries(innerClass); } } @@ -1048,8 +1049,8 @@ public class AsmClassGenerator extends ClassGenerator { } /** - * Determines if the given class can directly access the given field (via - * {@code GETFIELD}, {@code GETSTATIC}, etc. bytecode instructions). + * Determines if the given field can be directly accessed by the given class + * (via {@code GETFIELD}, {@code GETSTATIC}, etc. bytecode instructions). */ public static boolean isFieldDirectlyAccessible(final FieldNode field, final ClassNode accessingClass) { return field != null && isMemberDirectlyAccessible(field.getModifiers(), field.getDeclaringClass(), accessingClass); diff --git a/src/main/java/org/codehaus/groovy/classgen/GeneratorContext.java b/src/main/java/org/codehaus/groovy/classgen/GeneratorContext.java index 72d6f485d6..fcd115a280 100644 --- a/src/main/java/org/codehaus/groovy/classgen/GeneratorContext.java +++ b/src/main/java/org/codehaus/groovy/classgen/GeneratorContext.java @@ -34,11 +34,11 @@ public class GeneratorContext { private int syntheticMethodIdx = 0; private final CompileUnit compileUnit; - public GeneratorContext(CompileUnit compileUnit) { + public GeneratorContext(final CompileUnit compileUnit) { this.compileUnit = compileUnit; } - public GeneratorContext(CompileUnit compileUnit, int innerClassOffset) { + public GeneratorContext(final CompileUnit compileUnit, final int innerClassOffset) { this.compileUnit = compileUnit; this.innerClassIdx = innerClassOffset; } @@ -51,30 +51,23 @@ public class GeneratorContext { return compileUnit; } - public String getNextClosureInnerName(ClassNode owner, ClassNode enclosingClass, MethodNode enclosingMethod) { - return getNextInnerName(owner, enclosingClass, enclosingMethod, "closure"); + public String getNextClosureInnerName(final ClassNode owner, final ClassNode enclosingClass, final MethodNode enclosingMethod) { + return getNextInnerName(enclosingClass, enclosingMethod, "closure"); } - public String getNextLambdaInnerName(ClassNode owner, ClassNode enclosingClass, MethodNode enclosingMethod) { - return getNextInnerName(owner, enclosingClass, enclosingMethod, "lambda"); + public String getNextLambdaInnerName(final ClassNode owner, final ClassNode enclosingClass, final MethodNode enclosingMethod) { + return getNextInnerName(enclosingClass, enclosingMethod, "lambda"); } - private String getNextInnerName(ClassNode owner, ClassNode enclosingClass, MethodNode enclosingMethod, String classifier) { - String methodName = ""; - if (enclosingMethod != null) { - methodName = enclosingMethod.getName(); - - if (enclosingClass.isDerivedFrom(ClassHelper.CLOSURE_TYPE)) { - methodName = ""; - } else { - methodName = "_" + encodeAsValidClassName(methodName); - } + private String getNextInnerName(final ClassNode enclosingClass, final MethodNode enclosingMethod, final String classifier) { + String typeName = "_" + classifier + closureClassIdx++; + if (enclosingMethod != null && !ClassHelper.isGeneratedFunction(enclosingClass)) { + typeName = "_" + encodeAsValidClassName(enclosingMethod.getName()) + typeName; } - - return methodName + "_" + classifier + closureClassIdx++; + return typeName; } - public String getNextConstructorReferenceSyntheticMethodName(MethodNode enclosingMethodNode) { + public String getNextConstructorReferenceSyntheticMethodName(final MethodNode enclosingMethodNode) { return "ctorRef$" + (null == enclosingMethodNode ? "" diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java index d81897aec2..dfa8b1ec53 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import static org.apache.groovy.ast.tools.ClassNodeUtils.getNestHost; import static org.codehaus.groovy.ast.ClassHelper.isGeneratedFunction; public class WriterController { @@ -57,7 +58,6 @@ public class WriterController { private UnaryExpressionHelper unaryExpressionHelper, fastPathUnaryExpressionHelper; private AssertionWriter assertionWriter; private String internalBaseClassName; - private ClassNode outermostClass; private MethodNode methodNode; private ConstructorNode constructorNode; private GeneratorContext context; @@ -91,7 +91,6 @@ public class WriterController { if (invokedynamic) this.optimizeForInt = false; this.classNode = cn; - this.outermostClass = null; this.internalClassName = BytecodeHelper.getClassInternalName(cn); this.bytecodeVersion = config.getBytecodeVersion(); @@ -288,11 +287,7 @@ public class WriterController { } public ClassNode getOutermostClass() { - if (outermostClass == null) { - List<ClassNode> outers = classNode.getOuterClasses(); - outermostClass = !outers.isEmpty() ? outers.get(outers.size() - 1) : classNode; - } - return outermostClass; + return getNestHost(classNode); } public String getInternalClassName() { diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java index 8cf40bc7f8..e9198ca39e 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java @@ -74,6 +74,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import static org.apache.groovy.ast.tools.ClassNodeUtils.formatTypeName; +import static org.apache.groovy.ast.tools.ClassNodeUtils.isSubtype; import static org.apache.groovy.ast.tools.ClassNodeUtils.samePackageName; import static org.apache.groovy.ast.tools.ExpressionUtils.isNullConstant; import static org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression; @@ -229,7 +230,7 @@ public class StaticInvocationWriter extends InvocationWriter { } else { thisExpr = varX("thisObject", thisType); // adjust for multiple levels of nesting - while (!thisType.isDerivedFrom(target) && !thisType.implementsInterface(target)) { + while (!isSubtype(target, thisType)) { FieldNode thisZero = thisType.getDeclaredField("this$0"); if (thisZero != null) { thisExpr = attrX(thisExpr, "this$0"); @@ -258,7 +259,7 @@ public class StaticInvocationWriter extends InvocationWriter { ClassNode lookupClassNode; if (target.isProtected()) { lookupClassNode = controller.getClassNode(); - while (lookupClassNode != null && !lookupClassNode.isDerivedFrom(target.getDeclaringClass())) { + while (lookupClassNode != null && !isSubtype(target.getDeclaringClass(), lookupClassNode)) { lookupClassNode = lookupClassNode.getOuterClass(); } if (lookupClassNode == null) { @@ -273,7 +274,7 @@ public class StaticInvocationWriter extends InvocationWriter { Expression newReceiver = receiver; if (implicitThis) { if (!controller.isInGeneratedFunction()) { - if (!thisClass.isDerivedFrom(lookupClassNode)) + if (!isSubtype(lookupClassNode, thisClass)) newReceiver = propX(classX(lookupClassNode), "this"); } else if (thisClass != null) { newReceiver = thisObjectExpression(thisClass, lookupClassNode); @@ -367,14 +368,13 @@ public class StaticInvocationWriter extends InvocationWriter { if (!implicitThis && !isThisOrSuper(receiver) && !samePackageName(node, classNode) && StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(node, target.getDeclaringClass())) { writeMethodAccessError(target, receiver != null ? receiver : args); - } else if (!node.isDerivedFrom(target.getDeclaringClass()) && tryBridgeMethod(target, receiver, implicitThis, args, classNode)) { + } else if (!isSubtype(target.getDeclaringClass(), node) && tryBridgeMethod(target, receiver, implicitThis, args, classNode)) { return true; } } else if (target.isPublic() && receiver != null) { if (implicitThis && controller.isInGeneratedFunction() - && !classNode.isDerivedFrom(target.getDeclaringClass()) - && !classNode.implementsInterface(target.getDeclaringClass())) { + && !isSubtype(target.getDeclaringClass(), classNode)) { fixedReceiver = thisObjectExpression(classNode, target.getDeclaringClass()); if (!(fixedReceiver instanceof VariableExpression)) fixedImplicitThis = false; } diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java index 0a3d79666f..325c685814 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java @@ -352,8 +352,8 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres MethodCallExpression mce = callThisX("getThisObject"); mce.setImplicitThis(true); mce.setMethodTarget(CLOSURE_GETTHISOBJECT_METHOD); - mce.putNodeMetaData(INFERRED_TYPE, controller.getOutermostClass()); - pexp = castX(controller.getOutermostClass(), mce); + mce.putNodeMetaData(INFERRED_TYPE, controller.getThisType()); + pexp = castX(controller.getThisType(), mce); } else { pexp = propX(classX(outerClass), "this"); ((PropertyExpression) pexp).setImplicitThis(true); diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index f2a9c0032c..2d46571a71 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -145,6 +145,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; +import static org.apache.groovy.ast.tools.ClassNodeUtils.getNestHost; import static org.apache.groovy.ast.tools.MethodNodeUtils.withDefaultArgumentMethods; import static org.apache.groovy.util.BeanUtils.capitalize; import static org.apache.groovy.util.BeanUtils.decapitalize; @@ -578,13 +579,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { } } - private static ClassNode getOutermost(ClassNode cn) { - while (cn.getOuterClass() != null) { - cn = cn.getOuterClass(); - } - return cn; - } - private static void addPrivateFieldOrMethodAccess(final Expression source, final ClassNode cn, final StaticTypesMarker key, final ASTNode accessedMember) { cn.getNodeMetaData(key, x -> new LinkedHashSet<>()).add(accessedMember); source.putNodeMetaData(key, accessedMember); @@ -597,7 +591,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { if (fn != null && fn.isPrivate() && !fn.isSynthetic()) { ClassNode declaringClass = fn.getDeclaringClass(); ClassNode enclosingClass = typeCheckingContext.getEnclosingClassNode(); - if (declaringClass == enclosingClass ? typeCheckingContext.getEnclosingClosure() != null : getOutermost(declaringClass) == getOutermost(enclosingClass)) { + if (declaringClass == enclosingClass ? typeCheckingContext.getEnclosingClosure() != null : getNestHost(declaringClass) == getNestHost(enclosingClass)) { StaticTypesMarker accessKind = lhsOfAssignment ? PV_FIELDS_MUTATION : PV_FIELDS_ACCESS; addPrivateFieldOrMethodAccess(source, declaringClass, accessKind, fn); } @@ -920,7 +914,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { int modifiers = resultType.getModifiers(); ClassNode enclosingType = typeCheckingContext.getEnclosingClassNode(); if (!Modifier.isPublic(modifiers) && !enclosingType.equals(resultType) - && !getOutermost(enclosingType).equals(getOutermost(resultType)) + && !getNestHost(enclosingType).equals(getNestHost(resultType)) && (Modifier.isPrivate(modifiers) || !inSamePackage(enclosingType, resultType))) { resultType = originType; // TODO: Find accessible type in hierarchy of resultType? } else if (GenericsUtils.hasUnresolvedGenerics(resultType)) { // GROOVY-9033, GROOVY-10089, et al.
