Merge branch master from upstream
This commit is contained in:
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.");
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
17
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/AnoymousExtendingObject.java
vendored
Normal file
17
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/AnoymousExtendingObject.java
vendored
Normal 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!";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
36
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java
vendored
Normal file
36
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodFirstPhase.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
33
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodMostSpecific.java
vendored
Normal file
33
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodMostSpecific.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
46
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodSecondPhase.java
vendored
Normal file
46
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodSecondPhase.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
37
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java
vendored
Normal file
37
pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/testdata/MethodThirdPhase.java
vendored
Normal 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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user