#1276, #1278, #1279, #1280 False positive in UnusedPrivateMethod

Make the auxclasspath option optional. Falls back to the old behavior,
which prevents many false positives.
But it introduces the false negative case #1226, if no auxclasspath is set.
This commit is contained in:
Andreas Dangel
2014-11-15 12:21:18 +01:00
parent 60fe895abf
commit a5bc2a079f
4 changed files with 47 additions and 13 deletions

View File

@ -144,7 +144,8 @@ public class ClassScope extends AbstractJavaScope {
if (!mnd.isVarargs()
&& occurrence.getArgumentCount() == mnd.getParameterCount()
&& parameterTypes.equals(argumentTypes)) {
&& (!getEnclosingScope(SourceFileScope.class).hasAuxclasspath()
|| parameterTypes.equals(argumentTypes))) {
return mnd;
} else if (mnd.isVarargs()) {
int varArgIndex = parameterTypes.size() - 1;
@ -153,8 +154,14 @@ public class ClassScope extends AbstractJavaScope {
// 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)
&& parameterTypes.subList(0, varArgIndex).equals(argumentTypes.subList(0, varArgIndex))) {
&& (!getEnclosingScope(SourceFileScope.class).hasAuxclasspath()
|| parameterTypes.subList(0, varArgIndex).equals(argumentTypes.subList(0, varArgIndex)))) {
boolean sameType = true;
if (!getEnclosingScope(SourceFileScope.class).hasAuxclasspath()) {
return mnd;
}
for (int i = varArgIndex; i < argumentTypes.size(); i++) {
if (!varArgType.equals(argumentTypes.get(i))) {
sameType = false;

View File

@ -45,6 +45,17 @@ public class SourceFileScope extends AbstractJavaScope {
}
}
/**
* Whether an auxclasspath has been configured or not.
* This can be used to enable/disable more detailed symbol table analysis and type resolution
* can be used - or to fall back to more simple implementation.
* @return <code>true</code> if the auxclasspath is configured and types can be resolved reliably.
* @see #resolveType(String)
*/
public boolean hasAuxclasspath() {
return types.hasAuxclasspath();
}
/**
* Tries to resolve a class by name.
* @param name the name of the class

View File

@ -11,6 +11,7 @@ import java.util.Map;
import java.util.Set;
import net.sourceforge.pmd.lang.java.typeresolution.PMDASMClassLoader;
import net.sourceforge.pmd.util.ClasspathClassLoader;
/**
* Keeps track of the types encountered in a ASTCompilationUnit
@ -18,6 +19,7 @@ import net.sourceforge.pmd.lang.java.typeresolution.PMDASMClassLoader;
public class TypeSet {
private final PMDASMClassLoader pmdClassLoader;
private boolean hasAuxclasspath;
/**
* The {@link TypeSet} provides type resolution for the symbol facade.
@ -35,9 +37,18 @@ public class TypeSet {
if (cl == null) {
cl = TypeSet.class.getClassLoader();
}
hasAuxclasspath = cl instanceof ClasspathClassLoader;
pmdClassLoader = PMDASMClassLoader.getInstance(cl);
}
/**
* Whether the classloader is using the auxclasspath or not.
* @return <code>true</code> if the classloader is using the auxclasspath feature
*/
public boolean hasAuxclasspath() {
return hasAuxclasspath;
}
/**
* A resolver that can resolve a class by name. The name can be a simple name or a fully qualified name.
*/

View File

@ -200,17 +200,22 @@ public abstract class RuleTst {
/**
* Run the rule on the given code and put the violations in the report.
*/
public void runTestFromString(String code, Rule rule, Report report, LanguageVersion languageVersion) throws PMDException {
PMD p = new PMD();
p.getConfiguration().setDefaultLanguageVersion(languageVersion);
RuleContext ctx = new RuleContext();
ctx.setReport(report);
ctx.setSourceCodeFilename("n/a");
ctx.setLanguageVersion(languageVersion);
ctx.setIgnoreExceptions(false);
RuleSet rules = new RuleSet();
rules.addRule(rule);
p.getSourceCodeProcessor().processSourceCode(new StringReader(code), new RuleSets(rules), ctx);
public void runTestFromString(String code, Rule rule, Report report, LanguageVersion languageVersion) {
try {
PMD p = new PMD();
p.getConfiguration().setDefaultLanguageVersion(languageVersion);
p.getConfiguration().prependClasspath("."); // configure the "auxclasspath" option for unit testing
RuleContext ctx = new RuleContext();
ctx.setReport(report);
ctx.setSourceCodeFilename("n/a");
ctx.setLanguageVersion(languageVersion);
ctx.setIgnoreExceptions(false);
RuleSet rules = new RuleSet();
rules.addRule(rule);
p.getSourceCodeProcessor().processSourceCode(new StringReader(code), new RuleSets(rules), ctx);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**