diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java index 221e776ffc..d9346f6af4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ClassScope.java @@ -127,6 +127,14 @@ public class ClassScope extends AbstractJavaScope { List nameOccurrences = getMethodDeclarations().get(decl); if (nameOccurrences == null) { // TODO may be a class name: Foo.this.super(); + + // search inner classes + for (ClassNameDeclaration innerClass : getClassDeclarations().keySet()) { + Scope innerClassScope = innerClass.getScope(); + if (innerClassScope.contains(javaOccurrence)) { + innerClassScope.addNameOccurrence(javaOccurrence); + } + } } else { nameOccurrences.add(javaOccurrence); Node n = javaOccurrence.getLocation(); @@ -174,48 +182,17 @@ public class ClassScope extends AbstractJavaScope { Set result = new HashSet<>(); if (occurrence.isMethodOrConstructorInvocation()) { final boolean hasAuxclasspath = getEnclosingScope(SourceFileScope.class).hasAuxclasspath(); - for (MethodNameDeclaration mnd : methodDeclarations.keySet()) { - if (mnd.getImage().equals(occurrence.getImage())) { - List parameterTypes = determineParameterTypes(mnd); - List argumentTypes = determineArgumentTypes(occurrence, parameterTypes); + matchMethodDeclaration(occurrence, methodDeclarations.keySet(), hasAuxclasspath, result); - if (!mnd.isVarargs() && occurrence.getArgumentCount() == mnd.getParameterCount() - && (!hasAuxclasspath || parameterTypes.equals(argumentTypes))) { - result.add(mnd); - } else if (mnd.isVarargs()) { - int varArgIndex = parameterTypes.size() - 1; - TypedNameDeclaration varArgType = parameterTypes.get(varArgIndex); - - // first parameter is varArg, calling method might have - // 0 or more arguments - // or the calling method has enough arguments to fill in - // the parameters before the vararg - if ((varArgIndex == 0 || argumentTypes.size() >= varArgIndex) - && (!hasAuxclasspath || parameterTypes - .subList(0, varArgIndex).equals(argumentTypes.subList(0, varArgIndex)))) { - - if (!hasAuxclasspath) { - result.add(mnd); - continue; - } - - boolean sameType = true; - for (int i = varArgIndex; i < argumentTypes.size(); i++) { - if (!varArgType.equals(argumentTypes.get(i))) { - sameType = false; - break; - } - } - if (sameType) { - result.add(mnd); - } - } - } - } - } if (isEnum && "valueOf".equals(occurrence.getImage())) { result.add(createBuiltInMethodDeclaration("valueOf", "String")); } + + if (result.isEmpty()) { + for (ClassNameDeclaration innerClass : getClassDeclarations().keySet()) { + matchMethodDeclaration(occurrence, innerClass.getScope().getDeclarations(MethodNameDeclaration.class).keySet(), hasAuxclasspath, result); + } + } return result; } if (occurrence.isMethodReference()) { @@ -255,6 +232,50 @@ public class ClassScope extends AbstractJavaScope { return result; } + private void matchMethodDeclaration(JavaNameOccurrence occurrence, + Set methodDeclarations, final boolean hasAuxclasspath, + Set result) { + for (MethodNameDeclaration mnd : methodDeclarations) { + if (mnd.getImage().equals(occurrence.getImage())) { + List parameterTypes = determineParameterTypes(mnd); + List argumentTypes = determineArgumentTypes(occurrence, parameterTypes); + + if (!mnd.isVarargs() && occurrence.getArgumentCount() == mnd.getParameterCount() + && (!hasAuxclasspath || parameterTypes.equals(argumentTypes))) { + result.add(mnd); + } else if (mnd.isVarargs()) { + int varArgIndex = parameterTypes.size() - 1; + TypedNameDeclaration varArgType = parameterTypes.get(varArgIndex); + + // first parameter is varArg, calling method might have + // 0 or more arguments + // or the calling method has enough arguments to fill in + // the parameters before the vararg + if ((varArgIndex == 0 || argumentTypes.size() >= varArgIndex) + && (!hasAuxclasspath || parameterTypes + .subList(0, varArgIndex).equals(argumentTypes.subList(0, varArgIndex)))) { + + if (!hasAuxclasspath) { + result.add(mnd); + continue; + } + + boolean sameType = true; + for (int i = varArgIndex; i < argumentTypes.size(); i++) { + if (!varArgType.equals(argumentTypes.get(i))) { + sameType = false; + break; + } + } + if (sameType) { + result.add(mnd); + } + } + } + } + } + } + /** * Creates a fake method name declaration for built-in methods from Java * like the Enum Method "valueOf". diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/AccessorMethodGeneration.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/AccessorMethodGeneration.xml index c1d04a8abd..97c3e6cf7f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/AccessorMethodGeneration.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/AccessorMethodGeneration.xml @@ -121,12 +121,12 @@ public class Foo { } ]]> - + 1 - 9 + 8