Merge branch master from upstream

This commit is contained in:
oowekyala
2017-07-18 00:42:33 +02:00
150 changed files with 6029 additions and 4885 deletions

View File

@ -20,7 +20,7 @@ import net.sourceforge.pmd.lang.java.oom.metrics.visitors.JavaNcssVisitor;
* <p>The standard version's precise rules for counting statements comply with <a href="http://www.kclee.de/clemens/java/javancss/">JavaNCSS
* rules</a>. The only difference is that import and package statements are not counted.
*
* <p>Version {@link Version#JAVANCSS}: Import and package statements are counted. This version fully complies with
* <p>Version {@link NcssVersion#JAVANCSS}: Import and package statements are counted. This version fully complies with
* JavaNcss rules.
*
* @author Clément Fournier
@ -31,7 +31,7 @@ public final class NcssMetric {
/** Variants of NCSS. */
public enum Version implements MetricVersion {
public enum NcssVersion implements MetricVersion {
/** JavaNCSS compliant cyclo visitor. */
JAVANCSS
}
@ -46,7 +46,7 @@ public final class NcssMetric {
@Override
public double computeFor(ASTAnyTypeDeclaration node, MetricVersion version) {
JavaParserVisitor visitor = (NcssMetric.Version.JAVANCSS.equals(version))
JavaParserVisitor visitor = (NcssVersion.JAVANCSS.equals(version))
? new JavaNcssVisitor()
: new DefaultNcssVisitor();
@ -66,7 +66,7 @@ public final class NcssMetric {
@Override
public double computeFor(ASTMethodOrConstructorDeclaration node, MetricVersion version) {
JavaParserVisitor visitor = (NcssMetric.Version.JAVANCSS.equals(version))
JavaParserVisitor visitor = (NcssVersion.JAVANCSS.equals(version))
? new JavaNcssVisitor()
: new DefaultNcssVisitor();

View File

@ -4,13 +4,15 @@
package net.sourceforge.pmd.lang.java.oom.rule;
import java.util.HashMap;
import java.util.Map;
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
import net.sourceforge.pmd.lang.java.oom.Metrics;
import net.sourceforge.pmd.lang.java.oom.api.ClassMetricKey;
import net.sourceforge.pmd.lang.java.oom.api.Metric;
import net.sourceforge.pmd.lang.java.oom.api.Metric.Version;
import net.sourceforge.pmd.lang.java.oom.api.MetricVersion;
import net.sourceforge.pmd.lang.java.oom.api.OperationMetricKey;
@ -38,13 +40,17 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule {
"reportMethods", "Add method average violations to the report", true, 3.0f);
private static final String[] VERSION_LABELS = {"standard", "ignoreBooleanPaths"};
private static final Map<String, MetricVersion> VERSION_MAP;
private static final MetricVersion[] CYCLO_VERSIONS = {Metric.Version.STANDARD, CycloVersion.IGNORE_BOOLEAN_PATHS};
static {
VERSION_MAP = new HashMap<>();
VERSION_MAP.put("standard", Version.STANDARD);
VERSION_MAP.put("ignoreBooleanPaths", CycloVersion.IGNORE_BOOLEAN_PATHS);
}
private static final EnumeratedProperty<MetricVersion> CYCLO_VERSION_DESCRIPTOR = new EnumeratedProperty<>(
"cycloVersion", "Choose a variant of Cyclo or the standard",
VERSION_LABELS, CYCLO_VERSIONS, 0, 3.0f);
VERSION_MAP, Version.STANDARD, MetricVersion.class, 3.0f);
private int reportLevel;
private boolean reportClasses = true;
@ -63,10 +69,9 @@ public class CyclomaticComplexityRule extends AbstractJavaMetricsRule {
@Override
public Object visit(ASTCompilationUnit node, Object data) {
reportLevel = getProperty(REPORT_LEVEL_DESCRIPTOR);
cycloVersion = getProperty(CYCLO_VERSION_DESCRIPTOR);
reportClasses = getProperty(REPORT_CLASSES_DESCRIPTOR);
reportMethods = getProperty(REPORT_METHODS_DESCRIPTOR);
Object version = getProperty(CYCLO_VERSION_DESCRIPTOR);
cycloVersion = version instanceof MetricVersion ? (MetricVersion) version : Version.STANDARD;
super.visit(node, data);
return data;

View File

@ -4,6 +4,9 @@
package net.sourceforge.pmd.lang.java.oom.rule;
import java.util.HashMap;
import java.util.Map;
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
@ -14,7 +17,7 @@ import net.sourceforge.pmd.lang.java.oom.api.Metric;
import net.sourceforge.pmd.lang.java.oom.api.MetricVersion;
import net.sourceforge.pmd.lang.java.oom.api.OperationMetricKey;
import net.sourceforge.pmd.lang.java.oom.api.ResultOption;
import net.sourceforge.pmd.lang.java.oom.metrics.NcssMetric.Version;
import net.sourceforge.pmd.lang.java.oom.metrics.NcssMetric.NcssVersion;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaMetricsRule;
import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty;
import net.sourceforge.pmd.lang.rule.properties.IntegerProperty;
@ -33,13 +36,17 @@ public final class NcssCountRule extends AbstractJavaMetricsRule {
private static final IntegerProperty CLASS_REPORT_LEVEL_DESCRIPTOR = new IntegerProperty(
"classReportLevel", "Metric reporting threshold for classes", 1, 1000, 250, 1.0f);
private static final String[] VERSION_LABELS = {"standard", "javaNcss"};
private static final Map<String, MetricVersion> VERSION_MAP;
private static final MetricVersion[] CYCLO_VERSIONS = {Metric.Version.STANDARD, Version.JAVANCSS};
static {
VERSION_MAP = new HashMap<>();
VERSION_MAP.put("standard", Metric.Version.STANDARD);
VERSION_MAP.put("javaNcss", NcssVersion.JAVANCSS);
}
private static final EnumeratedProperty<MetricVersion> NCSS_VERSION_DESCRIPTOR = new EnumeratedProperty<>(
"ncssVersion", "Choose a variant of Ncss or the standard",
VERSION_LABELS, CYCLO_VERSIONS, 0, 3.0f);
VERSION_MAP, Metric.Version.STANDARD, MetricVersion.class, 3.0f);
private int methodReportLevel;
@ -58,8 +65,7 @@ public final class NcssCountRule extends AbstractJavaMetricsRule {
public Object visit(ASTCompilationUnit node, Object data) {
methodReportLevel = getProperty(METHOD_REPORT_LEVEL_DESCRIPTOR);
classReportLevel = getProperty(CLASS_REPORT_LEVEL_DESCRIPTOR);
Object version = getProperty(NCSS_VERSION_DESCRIPTOR);
ncssVersion = version instanceof MetricVersion ? (MetricVersion) version : Metric.Version.STANDARD;
ncssVersion = getProperty(NCSS_VERSION_DESCRIPTOR);
super.visit(node, data);
return data;

View File

@ -4,6 +4,12 @@
package net.sourceforge.pmd.lang.java.rule.basic;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sourceforge.pmd.PropertySource;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement;
@ -22,19 +28,27 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule {
public static final String CHECK_DO = "do";
public static final String CHECK_WHILE = "while";
private static final String[] ALL_LOOP_TYPES_LABELS = new String[] { CHECK_FOR, CHECK_DO, CHECK_WHILE };
private static final String[] ALL_LOOP_TYPES_VALUES = ALL_LOOP_TYPES_LABELS;
private static final int[] ALL_LOOP_TYPES_DEFAULTS = new int[] { 0, 1, 2 };
private static final Map<String, String> LOOP_TYPES_MAPPINGS;
private static final List<String> DEFAULTS = Arrays.asList(CHECK_FOR, CHECK_DO, CHECK_WHILE);
static {
Map<String, String> mappings = new HashMap<>();
mappings.put(CHECK_FOR, CHECK_FOR);
mappings.put(CHECK_DO, CHECK_DO);
mappings.put(CHECK_WHILE, CHECK_WHILE);
LOOP_TYPES_MAPPINGS = Collections.unmodifiableMap(mappings);
}
public static final EnumeratedMultiProperty<String> CHECK_BREAK_LOOP_TYPES = new EnumeratedMultiProperty<>(
"checkBreakLoopTypes", "Check for break statements in loop types", ALL_LOOP_TYPES_LABELS,
ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 1);
"checkBreakLoopTypes", "Check for break statements in loop types", LOOP_TYPES_MAPPINGS, DEFAULTS,
String.class, 1);
public static final EnumeratedMultiProperty<String> CHECK_CONTINUE_LOOP_TYPES = new EnumeratedMultiProperty<>(
"checkContinueLoopTypes", "Check for continue statements in loop types", ALL_LOOP_TYPES_LABELS,
ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 2);
"checkContinueLoopTypes", "Check for continue statements in loop types", LOOP_TYPES_MAPPINGS, DEFAULTS,
String.class, 2);
public static final EnumeratedMultiProperty<String> CHECK_RETURN_LOOP_TYPES = new EnumeratedMultiProperty<>(
"checkReturnLoopTypes", "Check for return statements in loop types", ALL_LOOP_TYPES_LABELS,
ALL_LOOP_TYPES_VALUES, ALL_LOOP_TYPES_DEFAULTS, 3);
"checkReturnLoopTypes", "Check for return statements in loop types", LOOP_TYPES_MAPPINGS, DEFAULTS,
String.class, 3);
public AvoidBranchingStatementAsLastInLoopRule() {
definePropertyDescriptor(CHECK_BREAK_LOOP_TYPES);
@ -46,6 +60,7 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule {
addRuleChainVisit(ASTReturnStatement.class);
}
@Override
public Object visit(ASTBreakStatement node, Object data) {
// skip breaks, that are within a switch statement
@ -55,15 +70,6 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule {
return check(CHECK_BREAK_LOOP_TYPES, node, data);
}
@Override
public Object visit(ASTContinueStatement node, Object data) {
return check(CHECK_CONTINUE_LOOP_TYPES, node, data);
}
@Override
public Object visit(ASTReturnStatement node, Object data) {
return check(CHECK_RETURN_LOOP_TYPES, node, data);
}
protected Object check(EnumeratedMultiProperty<String> property, Node node, Object data) {
Node parent = node.getNthParent(5);
@ -83,22 +89,24 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule {
return data;
}
protected boolean hasPropertyValue(EnumeratedMultiProperty<String> property, String value) {
final Object[] values = getProperty(property);
for (int i = 0; i < values.length; i++) {
if (value.equals(values[i])) {
return true;
}
}
return false;
return getProperty(property).contains(value);
}
public boolean checksNothing() {
return getProperty(CHECK_BREAK_LOOP_TYPES).length == 0 && getProperty(CHECK_CONTINUE_LOOP_TYPES).length == 0
&& getProperty(CHECK_RETURN_LOOP_TYPES).length == 0;
@Override
public Object visit(ASTContinueStatement node, Object data) {
return check(CHECK_CONTINUE_LOOP_TYPES, node, data);
}
@Override
public Object visit(ASTReturnStatement node, Object data) {
return check(CHECK_RETURN_LOOP_TYPES, node, data);
}
/**
* @see PropertySource#dysfunctionReason()
*/
@ -106,4 +114,11 @@ public class AvoidBranchingStatementAsLastInLoopRule extends AbstractJavaRule {
public String dysfunctionReason() {
return checksNothing() ? "All loop types are ignored" : null;
}
public boolean checksNothing() {
return getProperty(CHECK_BREAK_LOOP_TYPES).size() == 0 && getProperty(CHECK_CONTINUE_LOOP_TYPES).size() == 0
&& getProperty(CHECK_RETURN_LOOP_TYPES).size() == 0;
}
}

View File

@ -21,7 +21,7 @@ public class AvoidUsingHardCodedIPRule extends AbstractJavaRule {
public static final EnumeratedMultiProperty<String> CHECK_ADDRESS_TYPES_DESCRIPTOR = new EnumeratedMultiProperty<>(
"checkAddressTypes", "Check for IP address types.", new String[] { IPV4, IPV6, IPV4_MAPPED_IPV6 },
new String[] { IPV4, IPV6, IPV4_MAPPED_IPV6 }, new int[] { 0, 1, 2 }, 2.0f);
new String[] { IPV4, IPV6, IPV4_MAPPED_IPV6 }, new int[] { 0, 1, 2 }, String.class, 2.0f);
// Provides 4 capture groups that can be used for additional validation
protected static final String IPV4_REGEXP = "([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})";
@ -195,7 +195,7 @@ public class AvoidUsingHardCodedIPRule extends AbstractJavaRule {
}
public boolean hasChosenAddressTypes() {
return getProperty(CHECK_ADDRESS_TYPES_DESCRIPTOR).length > 0;
return getProperty(CHECK_ADDRESS_TYPES_DESCRIPTOR).size() > 0;
}
/**

View File

@ -18,7 +18,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.Comment;
import net.sourceforge.pmd.lang.rule.properties.BooleanProperty;
import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty;
import net.sourceforge.pmd.util.CollectionUtil;
import net.sourceforge.pmd.util.StringUtil;
/**
@ -32,11 +31,11 @@ public class CommentContentRule extends AbstractCommentRule {
private boolean caseSensitive;
private boolean wordsAreRegex;
private String[] originalBadWords;
private String[] currentBadWords;
private List<String> originalBadWords;
private List<String> currentBadWords;
// FIXME need some better defaults (or none?)
private static final String[] BAD_WORDS = new String[] { "idiot", "jerk" };
private static final String[] BAD_WORDS = {"idiot", "jerk" };
public static final BooleanProperty WORDS_ARE_REGEX_DESCRIPTOR = new BooleanProperty("wordsAreRegex",
"Use regular expressions", false, 1.0f);
@ -72,19 +71,21 @@ public class CommentContentRule extends AbstractCommentRule {
if (caseSensitive) {
currentBadWords = originalBadWords;
} else {
currentBadWords = new String[originalBadWords.length];
for (int i = 0; i < currentBadWords.length; i++) {
currentBadWords[i] = originalBadWords[i].toUpperCase();
currentBadWords = new ArrayList<>();
for (String badWord : originalBadWords) {
currentBadWords.add(badWord.toUpperCase());
}
}
}
@Override
public Set<PropertyDescriptor<?>> ignoredProperties() {
return getProperty(WORDS_ARE_REGEX_DESCRIPTOR) ? NON_REGEX_PROPERTIES : Collections.EMPTY_SET;
return getProperty(WORDS_ARE_REGEX_DESCRIPTOR) ? NON_REGEX_PROPERTIES
: Collections.<PropertyDescriptor<?>>emptySet();
}
/**
* .
* @see Rule#end(RuleContext)
*/
@Override
@ -94,7 +95,7 @@ public class CommentContentRule extends AbstractCommentRule {
private List<String> illegalTermsIn(Comment comment) {
if (currentBadWords.length == 0) {
if (currentBadWords.isEmpty()) {
return Collections.emptyList();
}
@ -109,9 +110,9 @@ public class CommentContentRule extends AbstractCommentRule {
List<String> foundWords = new ArrayList<>();
for (int i = 0; i < currentBadWords.length; i++) {
if (commentText.indexOf(currentBadWords[i]) >= 0) {
foundWords.add(originalBadWords[i]);
for (int i = 0; i < currentBadWords.size(); i++) {
if (commentText.contains(currentBadWords.get(i))) {
foundWords.add(originalBadWords.get(i));
}
}
@ -154,8 +155,8 @@ public class CommentContentRule extends AbstractCommentRule {
}
public boolean hasDissallowedTerms() {
String[] terms = getProperty(DISSALLOWED_TERMS_DESCRIPTOR);
return CollectionUtil.isNotEmpty(terms);
List<String> terms = getProperty(DISSALLOWED_TERMS_DESCRIPTOR);
return !terms.isEmpty();
}
/**

View File

@ -43,31 +43,31 @@ public class CommentRequiredRule extends AbstractCommentRule {
public static final EnumeratedProperty<CommentRequirement> HEADER_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>(
"headerCommentRequirement",
"Header comments. Possible values: " + Arrays.toString(CommentRequirement.values()),
CommentRequirement.labels(), CommentRequirement.values(), 0, 1.0f);
CommentRequirement.labels(), CommentRequirement.values(), 0, CommentRequirement.class, 1.0f);
public static final EnumeratedProperty<CommentRequirement> FIELD_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>(
"fieldCommentRequirement",
"Field comments. Possible values: " + Arrays.toString(CommentRequirement.values()),
CommentRequirement.labels(), CommentRequirement.values(), 0, 2.0f);
CommentRequirement.labels(), CommentRequirement.values(), 0, CommentRequirement.class, 2.0f);
public static final EnumeratedProperty<CommentRequirement> PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>(
"publicMethodCommentRequirement",
"Public method and constructor comments. Possible values: " + Arrays.toString(CommentRequirement.values()),
CommentRequirement.labels(), CommentRequirement.values(), 0, 3.0f);
CommentRequirement.labels(), CommentRequirement.values(), 0, CommentRequirement.class, 3.0f);
public static final EnumeratedProperty<CommentRequirement> PROT_METHOD_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>(
"protectedMethodCommentRequirement",
"Protected method constructor comments. Possible values: " + Arrays.toString(CommentRequirement.values()),
CommentRequirement.labels(), CommentRequirement.values(), 0, 4.0f);
CommentRequirement.labels(), CommentRequirement.values(), 0, CommentRequirement.class, 4.0f);
public static final EnumeratedProperty<CommentRequirement> ENUM_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>(
"enumCommentRequirement", "Enum comments. Possible values: " + Arrays.toString(CommentRequirement.values()),
CommentRequirement.labels(), CommentRequirement.values(), 0, 5.0f);
CommentRequirement.labels(), CommentRequirement.values(), 0, CommentRequirement.class, 5.0f);
public static final EnumeratedProperty<CommentRequirement> SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<CommentRequirement>(
"serialVersionUIDCommentRequired",
"serial version UID commts. Possible values: " + Arrays.toString(CommentRequirement.values()),
CommentRequirement.labels(), CommentRequirement.values(), 1, 6.0f);
public static final EnumeratedProperty<CommentRequirement> SERIAL_VERSION_UID_CMT_REQUIREMENT_DESCRIPTOR = new EnumeratedProperty<>(
"serialVersionUIDCommentRequired",
"serial version UID commts. Possible values: " + Arrays.toString(CommentRequirement.values()),
CommentRequirement.labels(), CommentRequirement.values(), 1, CommentRequirement.class, 6.0f);
public CommentRequiredRule() {
definePropertyDescriptor(HEADER_CMT_REQUIREMENT_DESCRIPTOR);

View File

@ -48,7 +48,7 @@ public class HeaderCommentsRule extends AbstractCommentRule {
public static final EnumeratedProperty<RequiredHeaderPlacement> HEADER_PLACEMENT_DESCRIPTOR = new EnumeratedProperty<>(
"headerPlacement", "Placement of the header comment", RequiredHeaderPlacement.labels(),
RequiredHeaderPlacement.values(), 0, 3.0f);
RequiredHeaderPlacement.values(), 0, RequiredHeaderPlacement.class, 3.0f);
public HeaderCommentsRule() {
definePropertyDescriptor(REQUIRED_TERMS_DESCRIPTOR);

View File

@ -5,7 +5,6 @@
package net.sourceforge.pmd.lang.java.rule.coupling;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@ -15,7 +14,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTPackageDeclaration;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty;
import net.sourceforge.pmd.util.CollectionUtil;
/**
* The loose package coupling Rule can be used to ensure coupling outside of a
@ -65,7 +63,7 @@ public class LoosePackageCouplingRule extends AbstractJavaRule {
// Sort the restricted packages in reverse order. This will ensure the
// child packages are in the list before their parent packages.
this.restrictedPackages = new ArrayList<>(Arrays.asList(super.getProperty(PACKAGES_DESCRIPTOR)));
this.restrictedPackages = new ArrayList<>(super.getProperty(PACKAGES_DESCRIPTOR));
Collections.sort(restrictedPackages, Collections.reverseOrder());
return data;
@ -132,8 +130,7 @@ public class LoosePackageCouplingRule extends AbstractJavaRule {
public boolean checksNothing() {
return CollectionUtil.isEmpty(getProperty(PACKAGES_DESCRIPTOR))
&& CollectionUtil.isEmpty(getProperty(CLASSES_DESCRIPTOR));
return getProperty(PACKAGES_DESCRIPTOR).isEmpty() && getProperty(CLASSES_DESCRIPTOR).isEmpty();
}
/**

View File

@ -5,7 +5,6 @@
package net.sourceforge.pmd.lang.java.rule.design;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -77,13 +76,13 @@ public class CloseResourceRule extends AbstractJavaRule {
@Override
public Object visit(ASTCompilationUnit node, Object data) {
if (closeTargets.isEmpty() && getProperty(CLOSE_TARGETS_DESCRIPTOR) != null) {
closeTargets.addAll(Arrays.asList(getProperty(CLOSE_TARGETS_DESCRIPTOR)));
closeTargets.addAll(getProperty(CLOSE_TARGETS_DESCRIPTOR));
}
if (getProperty(USE_CLOSE_AS_DEFAULT_TARGET) && !closeTargets.contains("close")) {
closeTargets.add("close");
}
if (types.isEmpty() && getProperty(TYPES_DESCRIPTOR) != null) {
types.addAll(Arrays.asList(getProperty(TYPES_DESCRIPTOR)));
types.addAll(getProperty(TYPES_DESCRIPTOR));
}
if (simpleTypes.isEmpty() && getProperty(TYPES_DESCRIPTOR) != null) {
for (String type : getProperty(TYPES_DESCRIPTOR)) {

View File

@ -84,22 +84,13 @@ public class GenericClassCounterRule extends AbstractJavaRule {
definePropertyDescriptor(THRESHOLD_DESCRIPTOR);
}
private List<String> arrayAsList(String[] array) {
List<String> list = new ArrayList<>(array.length);
int nbItem = 0;
while (nbItem < array.length) {
list.add(array[nbItem++]);
}
return list;
}
protected void init() {
// Creating the attribute name for the rule context
counterLabel = this.getClass().getSimpleName() + ".number of match";
// Constructing the request from the input parameters
this.namesMatch = RegexHelper.compilePatternsFromList(arrayAsList(getProperty(NAME_MATCH_DESCRIPTOR)));
this.namesMatch = RegexHelper.compilePatternsFromList(getProperty(NAME_MATCH_DESCRIPTOR));
this.operand = getProperty(OPERAND_DESCRIPTOR);
this.typesMatch = RegexHelper.compilePatternsFromList(arrayAsList(getProperty(TYPE_MATCH_DESCRIPTOR)));
this.typesMatch = RegexHelper.compilePatternsFromList(getProperty(TYPE_MATCH_DESCRIPTOR));
String thresholdAsString = getProperty(THRESHOLD_DESCRIPTOR);
this.threshold = Integer.valueOf(thresholdAsString);
// Initializing list of match

View File

@ -29,8 +29,8 @@ public class GuardLogStatementJavaUtilRule extends GuardLogStatementRule {
return data;
}
String[] logLevels = getProperty(LOG_LEVELS);
String[] guardMethods = getProperty(GUARD_METHODS);
String[] logLevels = getProperty(LOG_LEVELS).toArray(new String[0]); // TODO:cf convert to list
String[] guardMethods = getProperty(GUARD_METHODS).toArray(new String[0]);
if (super.guardStmtByLogLevel.isEmpty() && logLevels.length > 0 && guardMethods.length > 0) {
configureGuards(logLevels, guardMethods);

View File

@ -5,7 +5,6 @@
package net.sourceforge.pmd.lang.java.rule.logging;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -96,8 +95,8 @@ public class GuardLogStatementRule extends AbstractOptimizationRule implements R
protected void extractProperties() {
if (guardStmtByLogLevel.isEmpty()) {
List<String> logLevels = new ArrayList<>(Arrays.asList(super.getProperty(LOG_LEVELS)));
List<String> guardMethods = new ArrayList<>(Arrays.asList(super.getProperty(GUARD_METHODS)));
List<String> logLevels = new ArrayList<>(super.getProperty(LOG_LEVELS));
List<String> guardMethods = new ArrayList<>(super.getProperty(GUARD_METHODS));
if (guardMethods.isEmpty() && !logLevels.isEmpty()) {
throw new IllegalArgumentException("Can't specify guardMethods without specifiying logLevels.");

View File

@ -4,6 +4,8 @@
package net.sourceforge.pmd.lang.java.rule.naming;
import java.util.List;
import net.sourceforge.pmd.PropertyDescriptor;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration;
@ -19,7 +21,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.rule.properties.BooleanProperty;
import net.sourceforge.pmd.lang.rule.properties.StringMultiProperty;
import net.sourceforge.pmd.util.CollectionUtil;
public class VariableNamingConventionsRule extends AbstractJavaRule {
@ -27,14 +28,14 @@ public class VariableNamingConventionsRule extends AbstractJavaRule {
private boolean checkLocals;
private boolean checkParameters;
private boolean checkNativeMethodParameters;
private String[] staticPrefixes;
private String[] staticSuffixes;
private String[] memberPrefixes;
private String[] memberSuffixes;
private String[] localPrefixes;
private String[] localSuffixes;
private String[] parameterPrefixes;
private String[] parameterSuffixes;
private List<String> staticPrefixes;
private List<String> staticSuffixes;
private List<String> memberPrefixes;
private List<String> memberSuffixes;
private List<String> localPrefixes;
private List<String> localSuffixes;
private List<String> parameterPrefixes;
private List<String> parameterSuffixes;
private static final BooleanProperty CHECK_MEMBERS_DESCRIPTOR = new BooleanProperty("checkMembers",
"Check member variables", true, 1.0f);
@ -152,7 +153,7 @@ public class VariableNamingConventionsRule extends AbstractJavaRule {
return data;
}
private Object checkVariableDeclarators(String[] prefixes, String[] suffixes, Node root, boolean isStatic,
private Object checkVariableDeclarators(List<String> prefixes, List<String> suffixes, Node root, boolean isStatic,
boolean isFinal, Object data) {
for (ASTVariableDeclarator variableDeclarator : root.findChildrenOfType(ASTVariableDeclarator.class)) {
for (ASTVariableDeclaratorId variableDeclaratorId : variableDeclarator
@ -163,7 +164,7 @@ public class VariableNamingConventionsRule extends AbstractJavaRule {
return data;
}
private Object checkVariableDeclaratorId(String[] prefixes, String[] suffixes, Node root, boolean isStatic,
private Object checkVariableDeclaratorId(List<String> prefixes, List<String> suffixes, Node root, boolean isStatic,
boolean isFinal, ASTVariableDeclaratorId variableDeclaratorId, Object data) {
// Get the variable name
@ -199,15 +200,15 @@ public class VariableNamingConventionsRule extends AbstractJavaRule {
return data;
}
private String normalizeVariableName(String varName, String[] prefixes, String[] suffixes) {
private String normalizeVariableName(String varName, List<String> prefixes, List<String> suffixes) {
return stripSuffix(stripPrefix(varName, prefixes), suffixes);
}
private String stripSuffix(String varName, String[] suffixes) {
private String stripSuffix(String varName, List<String> suffixes) {
if (suffixes != null) {
for (int i = 0; i < suffixes.length; i++) {
if (varName.endsWith(suffixes[i])) {
varName = varName.substring(0, varName.length() - suffixes[i].length());
for (String suffix : suffixes) {
if (varName.endsWith(suffix)) {
varName = varName.substring(0, varName.length() - suffix.length());
break;
}
}
@ -215,11 +216,11 @@ public class VariableNamingConventionsRule extends AbstractJavaRule {
return varName;
}
private String stripPrefix(String varName, String[] prefixes) {
private String stripPrefix(String varName, List<String> prefixes) {
if (prefixes != null) {
for (int i = 0; i < prefixes.length; i++) {
if (varName.startsWith(prefixes[i])) {
return varName.substring(prefixes[i].length());
for (String prefix : prefixes) {
if (varName.startsWith(prefix)) {
return varName.substring(prefix.length());
}
}
}
@ -230,8 +231,8 @@ public class VariableNamingConventionsRule extends AbstractJavaRule {
for (PropertyDescriptor<?> desc : getPropertyDescriptors()) {
if (desc instanceof StringMultiProperty) {
String[] values = getProperty((StringMultiProperty) desc);
if (CollectionUtil.isNotEmpty(values)) {
List<String> values = getProperty((StringMultiProperty) desc);
if (!values.isEmpty()) {
return true;
}
}

View File

@ -4,10 +4,11 @@
package net.sourceforge.pmd.lang.java.typeresolution;
import static net.sourceforge.pmd.lang.java.typeresolution.MethodTypeResolution.getApplicableMethods;
import static net.sourceforge.pmd.lang.java.typeresolution.MethodTypeResolution.getBestMethodReturnType;
import static net.sourceforge.pmd.lang.java.typeresolution.MethodTypeResolution.isMemberVisibleFromClass;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -84,6 +85,7 @@ import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefin
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
import net.sourceforge.pmd.lang.symboltable.Scope;
//
// Helpful reading:
// http://www.janeg.ca/scjp/oper/promotions.html
@ -404,19 +406,11 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
return super.visit(node, data);
}
public JavaTypeDefinition getBestMethodReturnType(List<MethodType> methods, ASTArgumentList arguments,
List<JavaTypeDefinition> typeArgs) {
// TODO: add overload resolution
if (methods.size() == 1) {
return methods.get(0).getReturnType();
} else {
return null;
}
}
/**
* Search outwards from a node the enclosing type declarations. Searching them and their supertypes
* for method
* This method looks for method invocations be simple name.
* It searches outwards class declarations and their supertypes and in the end, static method imports.
* Compiles a list of potentially applicable methods.
* https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.1
*/
private List<MethodType> getLocalApplicableMethods(TypeNode node, String methodName,
List<JavaTypeDefinition> typeArguments,
@ -441,91 +435,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
return foundMethods;
}
public List<MethodType> getApplicableMethods(JavaTypeDefinition context,
String methodName,
List<JavaTypeDefinition> typeArguments,
int argArity,
Class<?> accessingClass) {
List<MethodType> result = new ArrayList<>();
if (context == null) {
return result;
}
// TODO: shadowing, overriding
// TODO: add multiple upper bounds
Class<?> contextClass = context.getType();
// search the class
for (Method method : contextClass.getDeclaredMethods()) {
if (isMethodApplicable(method, methodName, argArity, accessingClass, typeArguments)) {
if (isGeneric(method)) {
// TODO: do generic methods
// this disables invocations which could match generic methods
result.clear();
return result;
}
result.add(getTypeDefOfMethod(context, method));
}
}
// search it's supertype
if (!contextClass.equals(Object.class)) {
result.addAll(getApplicableMethods(context.resolveTypeDefinition(contextClass.getGenericSuperclass()),
methodName, typeArguments, argArity, accessingClass));
}
// search it's interfaces
for (Type interfaceType : contextClass.getGenericInterfaces()) {
result.addAll(getApplicableMethods(context.resolveTypeDefinition(interfaceType),
methodName, typeArguments, argArity, accessingClass));
}
return result;
}
public boolean isMethodApplicable(Method method, String methodName, int argArity,
Class<?> accessingClass, List<JavaTypeDefinition> typeArguments) {
if (method.getName().equals(methodName) // name matches
// is visible
&& isMemberVisibleFromClass(method.getDeclaringClass(), method.getModifiers(), accessingClass)
// if method is vararg with arity n, then the invocation's arity >= n - 1
&& (!method.isVarArgs() || (argArity >= getArity(method) - 1))
// if the method isn't vararg, then arity matches
&& (method.isVarArgs() || (argArity == getArity(method)))
// isn't generic or arity of type arguments matches that of parameters
&& (!isGeneric(method) || typeArguments == null
|| method.getTypeParameters().length == typeArguments.size())) {
return true;
}
return false;
}
private MethodType getTypeDefOfMethod(JavaTypeDefinition context, Method method) {
JavaTypeDefinition returnType = context.resolveTypeDefinition(method.getGenericReturnType());
List<JavaTypeDefinition> argTypes = new ArrayList<>();
// search typeArgs vs
for (Type argType : method.getGenericParameterTypes()) {
argTypes.add(context.resolveTypeDefinition(argType));
}
return new MethodType(returnType, argTypes, method);
}
private boolean isGeneric(Method method) {
return method.getTypeParameters().length != 0;
}
private int getArity(Method method) {
return method.getParameterTypes().length;
}
/**
* This method can be called on a prefix
*/
private ASTArguments getSuffixMethodArgs(Node node) {
Node prefix = node.jjtGetParent();
@ -636,51 +549,6 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
return null;
}
/**
* Given a class, the modifiers of on of it's member and the class that is trying to access that member,
* returns true is the member is accessible from the accessingClass Class.
*
* @param classWithMember The Class with the member.
* @param modifiers The modifiers of that member.
* @param accessingClass The Class trying to access the member.
* @return True if the member is visible from the accessingClass Class.
*/
private boolean isMemberVisibleFromClass(Class<?> classWithMember, int modifiers, Class<?> accessingClass) {
if (accessingClass == null) {
return false;
}
// public members
if (Modifier.isPublic(modifiers)) {
return true;
}
boolean areInTheSamePackage;
if (accessingClass.getPackage() != null) {
areInTheSamePackage = accessingClass.getPackage().getName().startsWith(
classWithMember.getPackage().getName());
} else {
return false; // if the package information is null, we can't do nothin'
}
// protected members
if (Modifier.isProtected(modifiers)) {
if (areInTheSamePackage || classWithMember.isAssignableFrom(accessingClass)) {
return true;
}
// private members
} else if (Modifier.isPrivate(modifiers)) {
if (classWithMember.equals(accessingClass)) {
return true;
}
// package private members
} else if (areInTheSamePackage) {
return true;
}
return false;
}
@Override
public Object visit(ASTFieldDeclaration node, Object data) {
@ -961,6 +829,10 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
return data;
}
/**
* The reason arguments are not visited here, is because they will be visited once the method
* to which they are arguments to is resolved.
*/
@Override
public Object visit(ASTArguments node, Object data) {
return data;

View File

@ -5,6 +5,7 @@
package net.sourceforge.pmd.lang.java.typeresolution;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.List;
@ -29,11 +30,35 @@ public class MethodType {
return returnType;
}
public List<JavaTypeDefinition> getArgTypes() {
public List<JavaTypeDefinition> getParameterTypes() {
return argTypes;
}
public Method getMethod() {
return method;
}
public boolean isVararg() {
return method.isVarArgs();
}
public JavaTypeDefinition getVarargComponentType() {
if (!isVararg()) {
throw new IllegalStateException("Method is not vararg: " + method.toString() + "!");
}
return argTypes.get(argTypes.size() - 1).getComponentType();
}
public boolean isAbstract() {
return Modifier.isAbstract(method.getModifiers());
}
public JavaTypeDefinition getArgTypeIncludingVararg(int index) {
if (index < argTypes.size() - 1) {
return argTypes.get(index);
} else {
return getVarargComponentType();
}
}
}

View File

@ -21,7 +21,7 @@ public class JavaTypeDefinition implements TypeDefinition {
private final Class<?> clazz;
private final List<JavaTypeDefinition> genericArgs;
private final boolean isGeneric;
private JavaTypeDefinition(final Class<?> clazz) {
this.clazz = clazz;
@ -29,7 +29,7 @@ public class JavaTypeDefinition implements TypeDefinition {
// the anonymous class can't have generics, but we may be binding generics from super classes
if (clazz.isAnonymousClass()) {
// is this an anonymous class based on an interface or a class?
if (clazz.getSuperclass() == Object.class) {
if (clazz.getInterfaces().length != 0) {
typeParameters = clazz.getInterfaces()[0].getTypeParameters();
} else {
typeParameters = clazz.getSuperclass().getTypeParameters();
@ -37,7 +37,7 @@ public class JavaTypeDefinition implements TypeDefinition {
} else {
typeParameters = clazz.getTypeParameters();
}
isGeneric = typeParameters.length != 0;
if (isGeneric) {
// Generics will be lazily loaded
@ -46,48 +46,48 @@ public class JavaTypeDefinition implements TypeDefinition {
this.genericArgs = Collections.emptyList();
}
}
public static JavaTypeDefinition forClass(final Class<?> clazz) {
if (clazz == null) {
return null;
}
final JavaTypeDefinition typeDef = CLASS_TYPE_DEF_CACHE.get(clazz);
if (typeDef != null) {
return typeDef;
}
final JavaTypeDefinition newDef = new JavaTypeDefinition(clazz);
// We can only cache types without generics, since their values are context-based
if (!newDef.isGeneric) {
CLASS_TYPE_DEF_CACHE.put(clazz, newDef);
}
return newDef;
}
public static JavaTypeDefinition forClass(final Class<?> clazz, final JavaTypeDefinition... boundGenerics) {
if (clazz == null) {
return null;
}
// With generics there is no cache
final JavaTypeDefinition typeDef = new JavaTypeDefinition(clazz);
for (final JavaTypeDefinition generic : boundGenerics) {
typeDef.genericArgs.add(generic);
}
return typeDef;
}
@Override
public Class<?> getType() {
return clazz;
}
public boolean isGeneric() {
return !genericArgs.isEmpty();
}
@ -99,9 +99,9 @@ public class JavaTypeDefinition implements TypeDefinition {
return getGenericType(i);
}
}
throw new IllegalArgumentException("No generic parameter by name " + parameterName
+ " on class " + clazz.getSimpleName());
+ " on class " + clazz.getSimpleName());
}
public JavaTypeDefinition getGenericType(final int index) {
@ -112,7 +112,7 @@ public class JavaTypeDefinition implements TypeDefinition {
return cachedDefinition;
}
}
// Force the list to have enough elements
for (int i = genericArgs.size(); i <= index; i++) {
genericArgs.add(null);
@ -123,10 +123,10 @@ public class JavaTypeDefinition implements TypeDefinition {
* Object.class is a right answer in those scenarios
*/
genericArgs.set(index, forClass(Object.class));
final TypeVariable<?> typeVariable = clazz.getTypeParameters()[index];
final JavaTypeDefinition typeDefinition = resolveTypeDefinition(typeVariable.getBounds()[0]);
// cache result
genericArgs.set(index, typeDefinition);
return typeDefinition;
@ -149,7 +149,7 @@ public class JavaTypeDefinition implements TypeDefinition {
for (int i = 0; i < typeArguments.length; i++) {
genericBounds[i] = resolveTypeDefinition(typeArguments[i]);
}
// TODO : is this cast safe?
return forClass((Class<?>) parameterizedType.getRawType(), genericBounds);
} else if (type instanceof TypeVariable) {
@ -166,4 +166,14 @@ public class JavaTypeDefinition implements TypeDefinition {
// TODO : Shall we throw here?
return forClass(Object.class);
}
public JavaTypeDefinition getComponentType() {
Class<?> componentType = getType().getComponentType();
if (componentType == null) {
throw new IllegalStateException(getType().getSimpleName() + " is not an array type!");
}
return forClass(componentType);
}
}

View File

@ -4,12 +4,14 @@
package net.sourceforge.pmd.lang.java.oom.metrics;
import java.util.HashMap;
import java.util.Map;
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
import net.sourceforge.pmd.lang.java.oom.Metrics;
import net.sourceforge.pmd.lang.java.oom.api.ClassMetricKey;
import net.sourceforge.pmd.lang.java.oom.api.Metric;
import net.sourceforge.pmd.lang.java.oom.api.Metric.Version;
import net.sourceforge.pmd.lang.java.oom.api.MetricVersion;
import net.sourceforge.pmd.lang.java.oom.api.OperationMetricKey;
@ -29,7 +31,7 @@ public abstract class AbstractMetricTestRule extends AbstractJavaMetricsRule {
private final EnumeratedProperty<MetricVersion> versionDescriptor = new EnumeratedProperty<>(
"metricVersion", "Choose a variant of the metric or the standard",
versionLabels(), versionValues(), 0, 3.0f);
versionMappings(), Version.STANDARD, MetricVersion.class, 3.0f);
private final BooleanProperty reportClassesDescriptor = new BooleanProperty(
"reportClasses", "Add class violations to the report", isReportClasses(), 2.0f);
private final BooleanProperty reportMethodsDescriptor = new BooleanProperty(
@ -48,10 +50,6 @@ public abstract class AbstractMetricTestRule extends AbstractJavaMetricsRule {
classKey = getClassKey();
opKey = getOpKey();
if (versionValues()[0] != Version.STANDARD) {
throw new RuntimeException("The versions array must begin with the standard version");
}
definePropertyDescriptor(reportClassesDescriptor);
definePropertyDescriptor(reportMethodsDescriptor);
definePropertyDescriptor(reportLevelDescriptor);
@ -75,22 +73,12 @@ public abstract class AbstractMetricTestRule extends AbstractJavaMetricsRule {
protected abstract OperationMetricKey getOpKey();
/**
* Values of the version.
*
* @return Array of the ordered values
*/
protected MetricVersion[] versionValues() {
return new MetricVersion[] {Version.STANDARD}; // TODO simplify that after #479
}
@Override
public Object visit(ASTCompilationUnit node, Object data) {
reportClasses = getProperty(reportClassesDescriptor);
reportMethods = getProperty(reportMethodsDescriptor);
reportLevel = getProperty(reportLevelDescriptor);
Object version = getProperty(versionDescriptor);
metricVersion = version instanceof MetricVersion ? (MetricVersion) version : Metric.Version.STANDARD;
metricVersion = getProperty(versionDescriptor);
return super.visit(node, data);
}
@ -117,12 +105,14 @@ public abstract class AbstractMetricTestRule extends AbstractJavaMetricsRule {
/**
* Labels of the versions.
* Mappings of labels to versions for use in the version property.
*
* @return Array of the ordered labels
* @return A map of labels to versions
*/
protected String[] versionLabels() {
return new String[] {"standard"};
protected Map<String, MetricVersion> versionMappings() {
Map<String, MetricVersion> mappings = new HashMap<>();
mappings.put("standard", Version.STANDARD);
return mappings;
}

View File

@ -4,8 +4,9 @@
package net.sourceforge.pmd.lang.java.oom.metrics;
import java.util.Map;
import net.sourceforge.pmd.lang.java.oom.api.ClassMetricKey;
import net.sourceforge.pmd.lang.java.oom.api.Metric;
import net.sourceforge.pmd.lang.java.oom.api.MetricVersion;
import net.sourceforge.pmd.lang.java.oom.api.OperationMetricKey;
import net.sourceforge.pmd.lang.java.oom.metrics.CycloMetric.CycloVersion;
@ -30,13 +31,9 @@ public class CycloTestRule extends AbstractMetricTestRule {
@Override
protected String[] versionLabels() {
return new String[] {"standard", "ignoreBooleanPaths"};
}
@Override
protected MetricVersion[] versionValues() {
return new MetricVersion[] {Metric.Version.STANDARD, CycloVersion.IGNORE_BOOLEAN_PATHS};
protected Map<String, MetricVersion> versionMappings() {
Map<String, MetricVersion> mappings = super.versionMappings();
mappings.put("ignoreBooleanPaths", CycloVersion.IGNORE_BOOLEAN_PATHS);
return mappings;
}
}

View File

@ -4,11 +4,12 @@
package net.sourceforge.pmd.lang.java.oom.metrics;
import java.util.Map;
import net.sourceforge.pmd.lang.java.oom.api.ClassMetricKey;
import net.sourceforge.pmd.lang.java.oom.api.Metric;
import net.sourceforge.pmd.lang.java.oom.api.MetricVersion;
import net.sourceforge.pmd.lang.java.oom.api.OperationMetricKey;
import net.sourceforge.pmd.lang.java.oom.metrics.NcssMetric.Version;
import net.sourceforge.pmd.lang.java.oom.metrics.NcssMetric.NcssVersion;
/**
* @author Clément Fournier
@ -34,13 +35,9 @@ public class NcssTestRule extends AbstractMetricTestRule {
@Override
protected String[] versionLabels() {
return new String[] {"standard", "javaNcss"};
}
@Override
protected MetricVersion[] versionValues() {
return new MetricVersion[] {Metric.Version.STANDARD, Version.JAVANCSS};
protected Map<String, MetricVersion> versionMappings() {
Map<String, MetricVersion> mappings = super.versionMappings();
mappings.put("javaNcss", NcssVersion.JAVANCSS);
return mappings;
}
}

View File

@ -52,6 +52,7 @@ import net.sourceforge.pmd.lang.java.typeresolution.ClassTypeResolver;
import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition;
import net.sourceforge.pmd.typeresolution.testdata.AnonymousClassFromInterface;
import net.sourceforge.pmd.typeresolution.testdata.AnonymousInnerClass;
import net.sourceforge.pmd.typeresolution.testdata.AnoymousExtendingObject;
import net.sourceforge.pmd.typeresolution.testdata.ArrayListFound;
import net.sourceforge.pmd.typeresolution.testdata.DefaultJavaLangImport;
import net.sourceforge.pmd.typeresolution.testdata.EnumWithAnonymousInnerClass;
@ -68,7 +69,11 @@ import net.sourceforge.pmd.typeresolution.testdata.FieldAccessSuper;
import net.sourceforge.pmd.typeresolution.testdata.InnerClass;
import net.sourceforge.pmd.typeresolution.testdata.Literals;
import net.sourceforge.pmd.typeresolution.testdata.MethodAccessibility;
import net.sourceforge.pmd.typeresolution.testdata.MethodFirstPhase;
import net.sourceforge.pmd.typeresolution.testdata.MethodMostSpecific;
import net.sourceforge.pmd.typeresolution.testdata.MethodPotentialApplicability;
import net.sourceforge.pmd.typeresolution.testdata.MethodSecondPhase;
import net.sourceforge.pmd.typeresolution.testdata.MethodThirdPhase;
import net.sourceforge.pmd.typeresolution.testdata.NestedAnonymousClass;
import net.sourceforge.pmd.typeresolution.testdata.Operators;
import net.sourceforge.pmd.typeresolution.testdata.Promotion;
@ -195,6 +200,14 @@ public class ClassTypeResolverTest {
Assert.assertTrue(Converter.class.isAssignableFrom(child.getType()));
Assert.assertSame(String.class, child.getTypeDefinition().getGenericType(0).getType());
}
@Test
public void testAnoymousExtendingObject() throws Exception {
Node acu = parseAndTypeResolveForClass(AnoymousExtendingObject.class, "1.8");
ASTAllocationExpression allocationExpression = acu.getFirstDescendantOfType(ASTAllocationExpression.class);
TypeNode child = (TypeNode) allocationExpression.jjtGetChild(0);
Assert.assertTrue(Object.class.isAssignableFrom(child.getType()));
}
@Test
public void testAnonymousInnerClass() throws ClassNotFoundException {
@ -1183,7 +1196,6 @@ public class ClassTypeResolverTest {
@Test
public void testMethodAccessibility() throws JaxenException {
// ASTCompilationUnit acu = parseAndTypeResolveForClass15(Dummy.class);
ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodAccessibility.class);
List<AbstractJavaTypeNode> expressions = convertList(
@ -1206,6 +1218,134 @@ public class ClassTypeResolverTest {
assertEquals("All expressions not tested", index, expressions.size());
}
@Test
public void testMethodFirstPhase() throws JaxenException {
ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodFirstPhase.class);
List<AbstractJavaTypeNode> expressions = convertList(
acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression"),
AbstractJavaTypeNode.class);
int index = 0;
// int a = subtype(10, 'a', null, new Integer[0]);
assertEquals(int.class, expressions.get(index).getType());
assertEquals(int.class, getChildType(expressions.get(index), 0));
assertEquals(int.class, getChildType(expressions.get(index++), 1));
// Exception b = vararg((Object) null);
assertEquals(Exception.class, expressions.get(index).getType());
assertEquals(Exception.class, getChildType(expressions.get(index), 0));
assertEquals(Exception.class, getChildType(expressions.get(index++), 1));
// Make sure we got them all
assertEquals("All expressions not tested", index, expressions.size());
}
@Test
public void testMethodMostSpecific() throws JaxenException {
ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodMostSpecific.class);
List<AbstractJavaTypeNode> expressions = convertList(
acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression"),
AbstractJavaTypeNode.class);
int index = 0;
// String a = moreSpecific((Number) null, (AbstractCollection) null);
assertEquals(String.class, expressions.get(index).getType());
assertEquals(String.class, getChildType(expressions.get(index), 0));
assertEquals(String.class, getChildType(expressions.get(index++), 1));
// Exception b = moreSpecific((Integer) null, (AbstractList) null);
assertEquals(Exception.class, expressions.get(index).getType());
assertEquals(Exception.class, getChildType(expressions.get(index), 0));
assertEquals(Exception.class, getChildType(expressions.get(index++), 1));
// int c = moreSpecific((Double) null, (RoleList) null);
assertEquals(int.class, expressions.get(index).getType());
assertEquals(int.class, getChildType(expressions.get(index), 0));
assertEquals(int.class, getChildType(expressions.get(index++), 1));
// Make sure we got them all
assertEquals("All expressions not tested", index, expressions.size());
}
@Test
public void testMethodSecondPhase() throws JaxenException {
ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodSecondPhase.class);
List<AbstractJavaTypeNode> expressions = convertList(
acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression"),
AbstractJavaTypeNode.class);
int index = 0;
// String a = boxing(10, "");
assertEquals(String.class, expressions.get(index).getType());
assertEquals(String.class, getChildType(expressions.get(index), 0));
assertEquals(String.class, getChildType(expressions.get(index++), 1));
// Exception b = boxing('a', "");
assertEquals(Exception.class, expressions.get(index).getType());
assertEquals(Exception.class, getChildType(expressions.get(index), 0));
assertEquals(Exception.class, getChildType(expressions.get(index++), 1));
// int c = boxing(10L, "");
assertEquals(int.class, expressions.get(index).getType());
assertEquals(int.class, getChildType(expressions.get(index), 0));
assertEquals(int.class, getChildType(expressions.get(index++), 1));
// String d = unboxing("", (Integer) null);
assertEquals(String.class, expressions.get(index).getType());
assertEquals(String.class, getChildType(expressions.get(index), 0));
assertEquals(String.class, getChildType(expressions.get(index++), 1));
// Exception e = unboxing("", (Character) null);
assertEquals(Exception.class, expressions.get(index).getType());
assertEquals(Exception.class, getChildType(expressions.get(index), 0));
assertEquals(Exception.class, getChildType(expressions.get(index++), 1));
// int f = unboxing("", (Byte) null);
assertEquals(int.class, expressions.get(index).getType());
assertEquals(int.class, getChildType(expressions.get(index), 0));
assertEquals(int.class, getChildType(expressions.get(index++), 1));
// Make sure we got them all
assertEquals("All expressions not tested", index, expressions.size());
}
@Test
public void testMethodThirdPhase() throws JaxenException {
ASTCompilationUnit acu = parseAndTypeResolveForClass15(MethodThirdPhase.class);
List<AbstractJavaTypeNode> expressions = convertList(
acu.findChildNodesWithXPath("//VariableInitializer/Expression/PrimaryExpression"),
AbstractJavaTypeNode.class);
int index = 0;
// Exception a = vararg(10, (Number) null, (Number) null);
assertEquals(Exception.class, expressions.get(index).getType());
assertEquals(Exception.class, getChildType(expressions.get(index), 0));
assertEquals(Exception.class, getChildType(expressions.get(index++), 1));
// Exception b = vararg(10);
assertEquals(Exception.class, expressions.get(index).getType());
assertEquals(Exception.class, getChildType(expressions.get(index), 0));
assertEquals(Exception.class, getChildType(expressions.get(index++), 1));
// int c = vararg(10, "", "", "");
assertEquals(int.class, expressions.get(index).getType());
assertEquals(int.class, getChildType(expressions.get(index), 0));
assertEquals(int.class, getChildType(expressions.get(index++), 1));
// String d = mostSpecific(10, 10, 10);
assertEquals(String.class, expressions.get(index).getType());
assertEquals(String.class, getChildType(expressions.get(index), 0));
assertEquals(String.class, getChildType(expressions.get(index++), 1));
// Make sure we got them all
assertEquals("All expressions not tested", index, expressions.size());
}
private Class<?> getChildType(Node node, int childIndex) {
return ((TypeNode) node.jjtGetChild(childIndex)).getType();
}

View File

@ -0,0 +1,17 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
public class AnoymousExtendingObject {
public void foo() {
System.out.println(new Object() {
@Override
public String toString() {
return "Suprise!";
}
});
}
}

View File

@ -0,0 +1,36 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
public class MethodFirstPhase {
void test() {
// primitive, char, simple
int a = subtype(10, 'a', "");
// TODO: add null, array types
Exception b = vararg((Number) null);
}
String vararg(Number... a) {
return null;
}
Exception vararg(Number a) {
return null;
}
Exception subtype(short a, int b, String c) {
return null;
}
int subtype(long a, int b, String c) {
return 0;
}
Exception subtype(long a, byte b, String c) {
return null;
}
}

View File

@ -0,0 +1,33 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.ArrayList;
import javax.management.relation.RoleList;
public abstract class MethodMostSpecific {
void test() {
// Hiararchy: Object, AbstractCollection, AbstractList, ArrayList, RoleList
String a = moreSpecific((Number) null, (AbstractCollection) null);
Exception b = moreSpecific((Integer) null, (AbstractList) null);
int c = moreSpecific((Double) null, (RoleList) null);
}
String moreSpecific(Number a, AbstractCollection b) {
return null;
}
Exception moreSpecific(Integer a, AbstractList b) {
return null;
}
int moreSpecific(Number a, ArrayList b) {
return 0;
}
}

View File

@ -0,0 +1,46 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
public class MethodSecondPhase {
void test() {
// boxing and widening conversion
String a = boxing(10, "");
// boxing
Exception b = boxing('a', "");
// boxing and most specific
int c = boxing(10L, "");
// unboxing and widening conversion
String d = unboxing("", (Integer) null);
Exception e = unboxing("", (Character) null);
int f = unboxing("", (Byte) null);
}
String boxing(Number a, String b) {
return null;
}
Exception boxing(Character a, String b) {
return null;
}
int boxing(Long a, String b) {
return 0;
}
String unboxing(String b, long a) {
return null;
}
Exception unboxing(String b, char a) {
return null;
}
int unboxing(String b, short a) {
return 0;
}
}

View File

@ -0,0 +1,37 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.typeresolution.testdata;
public class MethodThirdPhase {
void test() {
// more args than parameters
Exception a = vararg(10, (Number) null, (Number) null);
// less args than parameters
Exception b = vararg(10);
// component type determined properly
int c = vararg(10, "", "", "");
// most specific vararg method
String d = mostSpecific(10, 10, 10);
}
Exception mostSpecific(Number... b) {
return null;
}
String mostSpecific(Integer... b) {
return null;
}
Exception vararg(int a, Number... b) {
return null;
}
int vararg(int a, String c, String... b) {
return 0;
}
}