Merge branch 'pmd/7.0.x' into pmd7-issue-3366-support-jdk-17

This commit is contained in:
Andreas Dangel committed 2021-07-30 11:33:25 +02:00
commit f104af4b01
32 files changed
+2385 -75

No files matched your search

+3
View File
@@ -42,9 +42,11 @@
<rule ref="category/java/bestpractices.xml/MissingOverride"/>
<rule ref="category/java/bestpractices.xml/OneDeclarationPerLine"/>
<rule ref="category/java/bestpractices.xml/PreserveStackTrace"/>
<!-- <rule ref="category/java/bestpractices.xml/PrimitiveWrapperInstantiation"/> -->
<rule ref="category/java/bestpractices.xml/ReplaceEnumerationWithIterator"/>
<rule ref="category/java/bestpractices.xml/ReplaceHashtableWithMap"/>
<rule ref="category/java/bestpractices.xml/ReplaceVectorWithList"/>
<!-- <rule ref="category/java/bestpractices.xml/SimplifiableTestAssertion" /> -->
<rule ref="category/java/bestpractices.xml/SwitchStmtsShouldHaveDefault"/>
<rule ref="category/java/bestpractices.xml/SystemPrintln"/>
<rule ref="category/java/bestpractices.xml/UnusedAssignment"/>
@@ -106,6 +108,7 @@
<rule ref="category/java/codestyle.xml/UnnecessaryAnnotationValueElement"/>
<rule ref="category/java/codestyle.xml/UnnecessaryCast"/>
<rule ref="category/java/codestyle.xml/UnnecessaryConstructor"/>
<rule ref="category/java/codestyle.xml/UnnecessaryBoxing"/>
<rule ref="category/java/codestyle.xml/UnnecessaryFullyQualifiedName"/>
<!-- <rule ref="category/java/codestyle.xml/UnnecessaryImport"/> -->
<rule ref="category/java/codestyle.xml/UnnecessaryLocalBeforeReturn"/>
+7
View File
@@ -74,8 +74,15 @@ The default version is always ES6.
#### New Rules
##### Apex
* The Apex rule {% rule "apex/design/UnusedMethod" %} finds unused methods in your code.
##### Java
* {% rule "java/codestyle/UnnecessaryBoxing" %} reports boxing and unboxing
conversions that may be made implicit.
#### Changed Rules
##### Java
+58 -4
View File
@@ -35,7 +35,25 @@ Note: Support for Java 15 preview language features have been removed. The versi
#### New rules
This release ships with 1 new Java rule.
This release ships with 3 new Java rules.
* {% rule java/bestpractices/PrimitiveWrapperInstantiation %} reports usages of primitive wrapper
constructors. They are deprecated since Java 9 and should not be used.
```xml
<rule ref="category/java/bestpractices.xml/PrimitiveWrapperInstantiation" />
```
The rule is part of the quickstart.xml ruleset.
* {% rule java/bestpractices/SimplifiableTestAssertion %} suggests rewriting
some test assertions to be more readable.
```xml
<rule ref="category/java/bestpractices.xml/SimplifiableTestAssertion" />
```
The rule is part of the quickstart.xml ruleset.
* {% rule java/errorprone/ReturnEmptyCollectionRatherThanNull %} suggests returning empty collections / arrays
instead of null.
@@ -57,9 +75,33 @@ This release ships with 1 new Java rule.
#### Deprecated rules
The rule {% rule java/errorprone/ReturnEmptyArrayRatherThanNull %} is deprecated and removed from
the quickstart ruleset, as the new rule {% rule java/errorprone/ReturnEmptyCollectionRatherThanNull %}
supersedes it.
* The following Java rules are deprecated and removed from the quickstart ruleset,
as the new rule {% rule java/bestpractices/SimplifiableTestAssertion %} merges
their functionality:
* {% rule java/bestpractices/UseAssertEqualsInsteadOfAssertTrue %}
* {% rule java/bestpractices/UseAssertNullInsteadOfAssertTrue %}
* {% rule java/bestpractices/UseAssertSameInsteadOfAssertTrue %}
* {% rule java/bestpractices/UseAssertTrueInsteadOfAssertEquals %}
* {% rule java/design/SimplifyBooleanAssertion %}
* The Java rule {% rule java/errorprone/ReturnEmptyArrayRatherThanNull %} is deprecated and removed from
the quickstart ruleset, as the new rule {% rule java/errorprone/ReturnEmptyCollectionRatherThanNull %}
supersedes it.
* The following Java rules are deprecated and removed from the quickstart ruleset,
as the new rule {% rule java/bestpractices/PrimitiveWrapperInstantiation %} merges
their functionality:
* {% rule java/performance/BooleanInstantiation %}
* {% rule java/performance/ByteInstantiation %}
* {% rule java/performance/IntegerInstantiation %}
* {% rule java/performance/LongInstantiation %}
* {% rule java/performance/ShortInstantiation %}
* The Java rule {% rule java/performance/UnnecessaryWrapperObjectCreation %} is deprecated
with no planned replacement before PMD 7. In it's current state, the rule is not useful
as it finds only contrived cases of creating a primitive wrapper and unboxing it explicitly
in the same expression. In PMD 7 this and more cases will be covered by a
new rule `UnnecessaryBoxing`.
### Fixed Issues
@@ -67,8 +109,12 @@ supersedes it.
* [#3201](https://github.com/pmd/pmd/issues/3201): \[apex] ApexCRUDViolation doesn't report Database class DMLs, inline no-arg object instantiations and inline list initialization
* [#3329](https://github.com/pmd/pmd/issues/3329): \[apex] ApexCRUDViolation doesn't report SOQL for loops
* core
* [#1603](https://github.com/pmd/pmd/issues/1603): \[core] Language version comparison
* [#3377](https://github.com/pmd/pmd/issues/3377): \[core] NPE when specifying report file in current directory in PMD CLI
* [#3387](https://github.com/pmd/pmd/issues/3387): \[core] CPD should avoid unnecessary copies when running with --skip-lexical-errors
* java-bestpractices
* [#2908](https://github.com/pmd/pmd/issues/2908): \[java] Merge Junit assertion simplification rules
* [#3235](https://github.com/pmd/pmd/issues/3235): \[java] UseTryWithResources false positive when closeable is provided as a method argument or class field
* java-errorprone
* [#3361](https://github.com/pmd/pmd/issues/3361): \[java] Rename rule MissingBreakInSwitch to ImplicitSwitchFallThrough
* [#3382](https://github.com/pmd/pmd/pull/3382): \[java] New rule ReturnEmptyCollectionRatherThanNull
@@ -83,6 +129,14 @@ supersedes it.
{% jdoc !!java::lang.java.ast.ASTClassOrInterfaceDeclaration#getPermittedSubclasses() %}
* {% jdoc java::lang.java.ast.ASTPermitsList %}
#### Internal API
Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
You can identify them with the `@InternalApi` annotation. You'll also get a deprecation warning.
* The inner class {% jdoc !!core::cpd.TokenEntry.State %} is considered to be internal API.
It will probably be moved away with PMD 7.
### External Contributions
* [#3367](https://github.com/pmd/pmd/pull/3367): \[apex] Check SOQL CRUD on for loops - [Jonathan Wiesel](https://github.com/jonathanwiesel)
@@ -147,12 +147,12 @@ public class CPD {
}
private void addAndSkipLexicalErrors(SourceCode sourceCode) throws IOException {
final TokenEntry.State savedState = tokens.snapshot();
final TokenEntry.State savedState = new TokenEntry.State();
try {
addAndThrowLexicalError(sourceCode);
} catch (TokenMgrError e) {
System.err.println("Skipping " + sourceCode.getFileName() + ". Reason: " + e.getMessage());
tokens.restore(savedState);
savedState.restore(tokens);
}
}
@@ -10,6 +10,8 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import net.sourceforge.pmd.annotation.InternalApi;
public class TokenEntry implements Comparable<TokenEntry> {
public static final TokenEntry EOF = new TokenEntry();
@@ -92,7 +94,11 @@ public class TokenEntry implements Comparable<TokenEntry> {
/**
* Helper class to preserve and restore the current state of the token
* entries.
*
* @deprecated This is internal API.
*/
@InternalApi
@Deprecated
public static class State {
private final int tokenCount;
private final int tokensMapSize;
@@ -102,7 +108,8 @@ public class TokenEntry implements Comparable<TokenEntry> {
this.tokensMapSize = TokenEntry.TOKENS.get().size();
}
public void restore(final List<TokenEntry> entries) {
public void restore(Tokens tokens) {
final List<TokenEntry> entries = tokens.getTokens();
TokenEntry.TOKEN_COUNT.get().set(tokenCount);
final Iterator<Map.Entry<String, Integer>> it = TOKENS.get().entrySet().iterator();
while (it.hasNext()) {
@@ -8,8 +8,6 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.sourceforge.pmd.cpd.TokenEntry.State;
public class Tokens {
private List<TokenEntry> tokens = new ArrayList<>();
@@ -45,13 +43,4 @@ public class Tokens {
public List<TokenEntry> getTokens() {
return tokens;
}
public State snapshot() {
return new State();
}
public void restore(final State savedState) {
savedState.restore(tokens);
}
}
@@ -4,6 +4,8 @@
package net.sourceforge.pmd.lang;
import java.util.List;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.annotation.InternalApi;
@@ -120,27 +122,10 @@ public class LanguageVersion implements Comparable<LanguageVersion> {
@Override
public int compareTo(LanguageVersion o) {
if (o == null) {
return 1;
}
int comp = getName().compareTo(o.getName());
if (comp != 0) {
return comp;
}
String[] vals1 = getName().split("\\.");
String[] vals2 = o.getName().split("\\.");
int i = 0;
while (i < vals1.length && i < vals2.length && vals1[i].equals(vals2[i])) {
i++;
}
if (i < vals1.length && i < vals2.length) {
int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i]));
return Integer.signum(diff);
} else {
return Integer.signum(vals1.length - vals2.length);
}
List<LanguageVersion> versions = language.getVersions();
int thisPosition = versions.indexOf(this);
int otherPosition = versions.indexOf(o);
return Integer.compare(thisPosition, otherPosition);
}
@Override
@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<ruleset name="6370"
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
<description>
This ruleset contains links to rules that are new in PMD v6.37.0
</description>
<rule ref="category/java/bestpractices.xml/PrimitiveWrapperInstantiation" />
<rule ref="category/java/bestpractices.xml/SimplifiableTestAssertion" />
<rule ref="category/java/errorprone.xml/ReturnEmptyCollectionRatherThanNull" />
</ruleset>
@@ -10,5 +10,7 @@ This ruleset contains links to rules that are new in PMD v7.0.0
<rule ref="category/apex/design.xml/UnusedMethod"/>
<rule ref="category/java/codestyle.xml/UnnecessaryBoxing"/>
</ruleset>
@@ -0,0 +1,152 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.bestpractices;
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
import net.sourceforge.pmd.lang.java.ast.ASTArguments;
import net.sourceforge.pmd.lang.java.ast.ASTArrayDimsAndInits;
import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
import net.sourceforge.pmd.lang.java.ast.JavaNode;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.java.types.TypeTestUtil;
public class PrimitiveWrapperInstantiationRule extends AbstractJavaRule {
public PrimitiveWrapperInstantiationRule() {
addRuleChainVisit(ASTAllocationExpression.class);
addRuleChainVisit(ASTPrimaryExpression.class);
}
@Override
public Object visit(ASTAllocationExpression node, Object data) {
if (node.getFirstChildOfType(ASTArrayDimsAndInits.class) != null) {
return data;
}
ASTClassOrInterfaceType type = node.getFirstChildOfType(ASTClassOrInterfaceType.class);
if (type == null) {
return data;
}
if (TypeTestUtil.isA(Double.class, type)
|| TypeTestUtil.isA(Float.class, type)
|| TypeTestUtil.isA(Long.class, type)
|| TypeTestUtil.isA(Integer.class, type)
|| TypeTestUtil.isA(Short.class, type)
|| TypeTestUtil.isA(Byte.class, type)
|| TypeTestUtil.isA(Character.class, type)) {
addViolation(data, node, type.getImage());
} else if (TypeTestUtil.isA(Boolean.class, type)) {
checkArguments(node.getFirstChildOfType(ASTArguments.class), node, data);
}
return data;
}
/**
* Finds calls of "Boolean.valueOf".
*/
@Override
public Object visit(ASTPrimaryExpression node, Object data) {
if (!TypeTestUtil.isA(Boolean.class, node)) {
return data;
}
if (node.getNumChildren() >= 2 && node.getChild(0).getNumChildren() > 0
&& node.getChild(0).getChild(0) instanceof ASTName
&& node.getChild(0).getChild(0).hasImageEqualTo("Boolean.valueOf")) {
ASTPrimarySuffix suffix = (ASTPrimarySuffix) node.getChild(1);
checkArguments(suffix.getFirstChildOfType(ASTArguments.class), node, data);
}
return data;
}
private void checkArguments(ASTArguments arguments, JavaNode node, Object data) {
if (arguments == null || arguments.size() != 1) {
return;
}
String messagePart = node instanceof ASTAllocationExpression
? "Do not use `new Boolean"
: "Do not use `Boolean.valueOf";
ASTLiteral stringLiteral = getFirstArgStringLiteralOrNull(arguments);
ASTBooleanLiteral boolLiteral = getFirstArgBooleanLiteralOrNull(arguments);
if (stringLiteral != null) {
if (stringLiteral.hasImageEqualTo("\"true\"")) {
addViolationWithMessage(data, node, messagePart + "(\"true\")`, prefer `Boolean.TRUE`");
} else if (stringLiteral.hasImageEqualTo("\"false\"")) {
addViolationWithMessage(data, node, messagePart + "(\"false\")`, prefer `Boolean.FALSE`");
}
} else if (boolLiteral != null) {
if (boolLiteral.isTrue()) {
addViolationWithMessage(data, node, messagePart + "(true)`, prefer `Boolean.TRUE`");
} else {
addViolationWithMessage(data, node, messagePart + "(false)`, prefer `Boolean.FALSE`");
}
}
}
/**
* <pre>
* └─ Arguments
* └─ ArgumentList
* └─ Expression
* └─ PrimaryExpression
* └─ PrimaryPrefix
* └─ Literal
* </pre>
*/
private static ASTLiteral getFirstArgStringLiteralOrNull(ASTArguments arguments) {
if (arguments.size() == 1) {
ASTExpression expr = arguments.getFirstDescendantOfType(ASTExpression.class);
ASTPrimaryExpression primaryExpr = getSingleChildOf(expr, ASTPrimaryExpression.class);
ASTPrimaryPrefix prefix = getSingleChildOf(primaryExpr, ASTPrimaryPrefix.class);
ASTLiteral literal = getSingleChildOf(prefix, ASTLiteral.class);
if (literal != null && literal.isStringLiteral()) {
return literal;
}
}
return null;
}
/**
* <pre>
* └─ Arguments
* └─ ArgumentList
* └─ Expression
* └─ PrimaryExpression
* └─ PrimaryPrefix
* └─ Literal
* └─ BooleanLiteral
* </pre>
*/
private static ASTBooleanLiteral getFirstArgBooleanLiteralOrNull(ASTArguments arguments) {
if (arguments.size() == 1) {
ASTExpression expr = arguments.getFirstDescendantOfType(ASTExpression.class);
ASTPrimaryExpression primaryExpr = getSingleChildOf(expr, ASTPrimaryExpression.class);
ASTPrimaryPrefix prefix = getSingleChildOf(primaryExpr, ASTPrimaryPrefix.class);
ASTLiteral literal = getSingleChildOf(prefix, ASTLiteral.class);
return getSingleChildOf(literal, ASTBooleanLiteral.class);
}
return null;
}
private static <N extends JavaNode> N getSingleChildOf(JavaNode node, Class<N> type) {
if (node == null || node.getNumChildren() != 1
|| type != node.getChild(0).getClass()) {
return null;
}
@SuppressWarnings("unchecked")
N result = (N) node.getChild(0);
return result;
}
}
@@ -0,0 +1,63 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.bestpractices;
import static net.sourceforge.pmd.properties.PropertyFactory.stringListProperty;
import java.util.List;
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
import net.sourceforge.pmd.lang.java.ast.ASTFinallyClause;
import net.sourceforge.pmd.lang.java.ast.ASTMethodCall;
import net.sourceforge.pmd.lang.java.ast.ASTTryStatement;
import net.sourceforge.pmd.lang.java.ast.ASTTypeExpression;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil;
import net.sourceforge.pmd.lang.java.types.TypeTestUtil;
import net.sourceforge.pmd.properties.PropertyDescriptor;
public final class UseTryWithResourcesRule extends AbstractJavaRulechainRule {
private static final PropertyDescriptor<List<String>> CLOSE_METHODS =
stringListProperty("closeMethods")
.desc("Method names in finally block, which trigger this rule")
.defaultValues("close", "closeQuietly")
.delim(',')
.build();
public UseTryWithResourcesRule() {
super(ASTTryStatement.class);
definePropertyDescriptor(CLOSE_METHODS);
}
@Override
public Object visit(ASTTryStatement node, Object data) {
boolean isJava9OrLater = node.getAstInfo().getLanguageVersion().compareToVersion("9") >= 0;
ASTFinallyClause finallyClause = node.getFinallyClause();
if (finallyClause != null) {
List<ASTMethodCall> methods = finallyClause.descendants(ASTMethodCall.class)
.filter(m -> getProperty(CLOSE_METHODS).contains(m.getMethodName()))
.toList();
for (ASTMethodCall method : methods) {
ASTExpression closeTarget = method.getQualifier();
if (!(closeTarget instanceof ASTTypeExpression) // ignore static method calls
&& TypeTestUtil.isA(AutoCloseable.class, closeTarget)
&& (isJava9OrLater || JavaRuleUtil.isReferenceToLocal(closeTarget))
|| hasAutoClosableArguments(method)) {
addViolation(data, node);
break; // only report the first closeable
}
}
}
return data;
}
private boolean hasAutoClosableArguments(ASTMethodCall method) {
return method.getArguments().children()
.filter(e -> TypeTestUtil.isA(AutoCloseable.class, e))
.nonEmpty();
}
}
@@ -0,0 +1,168 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.codestyle;
import static net.sourceforge.pmd.util.CollectionUtil.setOf;
import java.util.Set;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall;
import net.sourceforge.pmd.lang.java.ast.ASTExpression;
import net.sourceforge.pmd.lang.java.ast.ASTList;
import net.sourceforge.pmd.lang.java.ast.ASTMethodCall;
import net.sourceforge.pmd.lang.java.ast.InvocationNode;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
import net.sourceforge.pmd.lang.java.types.JMethodSig;
import net.sourceforge.pmd.lang.java.types.JTypeMirror;
import net.sourceforge.pmd.lang.java.types.OverloadSelectionResult;
import net.sourceforge.pmd.lang.java.types.TypePrettyPrint;
import net.sourceforge.pmd.lang.java.types.ast.ExprContext;
/**
*
*/
public class UnnecessaryBoxingRule extends AbstractJavaRulechainRule {
private static final Set<String> INTERESTING_NAMES = setOf(
"valueOf",
"booleanValue",
"charValue",
"byteValue",
"shortValue",
"intValue",
"longValue",
"floatValue",
"doubleValue"
);
public UnnecessaryBoxingRule() {
super(ASTMethodCall.class, ASTConstructorCall.class);
}
@Override
public Object visit(ASTConstructorCall node, Object data) {
if (node.getTypeMirror().isBoxedPrimitive()) {
ASTExpression arg = ASTList.singleOrNull(node.getArguments());
if (arg == null) {
return null;
}
JTypeMirror argT = arg.getTypeMirror();
if (argT.isPrimitive()) {
checkBox((RuleContext) data, "boxing", node, arg, node.getMethodType().getFormalParameters().get(0));
}
}
return null;
}
@Override
public Object visit(ASTMethodCall node, Object data) {
if (INTERESTING_NAMES.contains(node.getMethodName())) {
OverloadSelectionResult overload = node.getOverloadSelectionInfo();
if (overload.isFailed()) {
return null;
}
JMethodSig m = overload.getMethodType();
boolean isValueOf = "valueOf".equals(node.getMethodName());
ASTExpression qualifier = node.getQualifier();
if (isValueOf && isWrapperValueOf(m)) {
checkBox((RuleContext) data, "boxing", node, node.getArguments().get(0), m.getFormalParameters().get(0));
} else if (!isValueOf && isUnboxingCall(m) && qualifier != null) {
checkBox((RuleContext) data, "unboxing", node, qualifier, qualifier.getTypeMirror());
}
}
return null;
}
private boolean isUnboxingCall(JMethodSig m) {
return !m.isStatic() && m.getDeclaringType().isBoxedPrimitive() && m.getArity() == 0;
}
private boolean isWrapperValueOf(JMethodSig m) {
return m.isStatic()
&& m.getArity() == 1
&& m.getDeclaringType().isBoxedPrimitive()
&& m.getFormalParameters().get(0).isPrimitive();
}
private void checkBox(
RuleContext rctx,
String opKind,
ASTExpression conversionExpr,
ASTExpression convertedExpr,
JTypeMirror conversionInput
) {
// the conversion looks like
// CTX _ = conversion(sourceExpr)
// we have the following data flow:
// sourceExpr -> convInput -> convOutput -> ctx
// 1 2 3
// where 1 and 3 are implicit conversions which we assume are
// valid because the code should compile.
// we want to report a violation if this is equivalent to
// sourceExpr -> ctx
// which basically means testing that convInput -> convOutput
// may be performed implicitly.
// We cannot just test compatibility of the source to the ctx,
// because of situations like
// int i = integer.byteValue()
// where the conversion actually truncates the input value.
JTypeMirror sourceType = convertedExpr.getTypeMirror();
JTypeMirror conversionOutput = conversionExpr.getTypeMirror();
ExprContext ctx = conversionExpr.getConversionContext();
JTypeMirror ctxType = ctx.getTargetType();
if (ctxType == null && conversionExpr instanceof InvocationNode) {
ctxType = conversionOutput;
}
if (ctxType != null) {
if (isImplicitlyConvertible(conversionInput, conversionOutput)) {
boolean simpleConv = isReferenceSubtype(sourceType, conversionInput);
final String reason;
if (simpleConv && conversionInput.unbox().equals(conversionOutput)) {
reason = "explicit unboxing";
} else if (simpleConv && conversionInput.box().equals(conversionOutput)) {
reason = "explicit boxing";
} else if (sourceType.equals(conversionOutput)) {
reason = "boxing of boxed value";
} else {
if (sourceType.equals(ctxType)) {
reason = opKind;
} else {
reason = "explicit conversion from " + TypePrettyPrint.prettyPrintWithSimpleNames(sourceType) + " to " + TypePrettyPrint.prettyPrintWithSimpleNames(ctxType);
}
}
addViolation(rctx, conversionExpr, reason);
}
}
}
private boolean isImplicitlyConvertible(JTypeMirror i, JTypeMirror o) {
return i.box().isSubtypeOf(o.box())
|| i.unbox().isSubtypeOf(o.unbox());
}
/**
* Whether {@code S <: T}, but ignoring primitive widening.
* {@code isReferenceSubtype(int, double) == false} even though
* {@code int.isSubtypeOf(double)}.
*/
private static boolean isReferenceSubtype(JTypeMirror s, JTypeMirror t) {
return s.isPrimitive() ? t.equals(s)
: s.isSubtypeOf(t);
}
}
@@ -75,6 +75,7 @@ import net.sourceforge.pmd.lang.java.ast.TypeNode;
import net.sourceforge.pmd.lang.java.ast.UnaryOp;
import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol;
import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol;
import net.sourceforge.pmd.lang.java.symbols.internal.ast.AstLocalVarSym;
import net.sourceforge.pmd.lang.java.types.InvocationMatcher;
import net.sourceforge.pmd.lang.java.types.InvocationMatcher.CompoundInvocationMatcher;
import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind;
@@ -806,8 +807,7 @@ public final class JavaRuleUtil {
*/
public static boolean isReferenceToLocal(ASTExpression expr) {
if (expr instanceof ASTVariableAccess) {
JVariableSymbol sym = ((ASTVariableAccess) expr).getReferencedSym();
return sym != null && !sym.isField();
return ((ASTVariableAccess) expr).getReferencedSym() instanceof AstLocalVarSym;
}
return false;
}
@@ -31,7 +31,6 @@ public class BigIntegerInstantiationRule extends AbstractJavaRulechainRule {
super(ASTConstructorCall.class);
}
@Override
public Object visit(ASTConstructorCall node, Object data) {
LanguageVersion languageVersion = node.getAstInfo().getLanguageVersion();
@@ -8,9 +8,7 @@ import static net.sourceforge.pmd.util.CollectionUtil.setOf;
import java.util.Set;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.JavaLanguageModule;
import net.sourceforge.pmd.lang.java.ast.ASTName;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
@@ -36,8 +34,7 @@ public class UnnecessaryWrapperObjectCreationRule extends AbstractJavaRule {
image = image.substring(10);
}
boolean checkBoolean = node.getAstInfo().getLanguageVersion()
.compareTo(LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("1.5")) >= 0;
boolean checkBoolean = node.getAstInfo().getLanguageVersion().compareToVersion("1.5") >= 0;
if (PREFIX_SET.contains(image) || checkBoolean && "Boolean.valueOf".equals(image)) {
ASTPrimaryExpression parent = (ASTPrimaryExpression) node.getParent();
@@ -14,7 +14,7 @@ import net.sourceforge.pmd.lang.java.types.Substitution;
/**
* @author Clément Fournier
*/
final class AstLocalVarSym extends AbstractAstVariableSym implements JLocalVariableSymbol {
public final class AstLocalVarSym extends AbstractAstVariableSym implements JLocalVariableSymbol {
AstLocalVarSym(ASTVariableDeclaratorId node, AstSymFactory factory) {
super(node, factory);
@@ -31,6 +31,10 @@ public final class TypePrettyPrint {
return prettyPrint(t, new TypePrettyPrinter());
}
public static @NonNull String prettyPrintWithSimpleNames(@NonNull JTypeVisitable t) {
return prettyPrint(t, new TypePrettyPrinter().useSimpleNames(true));
}
public static String prettyPrint(@NonNull JTypeVisitable t, TypePrettyPrinter prettyPrinter) {
t.acceptVisitor(PrettyPrintVisitor.INSTANCE, prettyPrinter);
return prettyPrinter.consumeResult();
@@ -802,7 +802,6 @@ public class MyTest {
since="6.35.0"
message="JUnit 5 tests should be package-private."
class="net.sourceforge.pmd.lang.rule.XPathRule"
typeResolution="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#junit5testshouldbepackageprivate">
<description><![CDATA[
Reports JUnit 5 test classes and methods that are not package-private.
@@ -1197,6 +1196,36 @@ public class Foo {
</example>
</rule>
<rule name="PrimitiveWrapperInstantiation"
language="java"
since="6.37.0"
message="Do not use `new {0}(...)`, prefer `{0}.valueOf(...)`"
class="net.sourceforge.pmd.lang.java.rule.bestpractices.PrimitiveWrapperInstantiationRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#primitivewrapperinstantiation">
<description>
Reports usages of primitive wrapper constructors. They are deprecated
since Java 9 and should not be used. Even before Java 9, they can
be replaced with usage of the corresponding static `valueOf` factory method
(which may be automatically inserted by the compiler since Java 1.5).
This has the advantage that it may reuse common instances instead of creating
a new instance each time.
Note that for `Boolean`, the named constants `Boolean.TRUE` and `Boolean.FALSE`
are preferred instead of `Boolean.valueOf`.
</description>
<priority>3</priority>
<example>
<![CDATA[
public class Foo {
private Integer ZERO = new Integer(0); // violation
private Integer ZERO1 = Integer.valueOf(0); // better
private Integer ZERO1 = 0; // even better
}
]]>
</example>
</rule>
<rule name="ReplaceEnumerationWithIterator"
language="java"
since="3.4"
@@ -1287,6 +1316,49 @@ public class Foo {
</example>
</rule>
<rule name="SimplifiableTestAssertion"
language="java"
since="6.37.0"
message="Assertion may be simplified using {0}"
class="net.sourceforge.pmd.lang.java.rule.bestpractices.SimplifiableTestAssertionRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#simplifiabletestassertion">
<description>
Reports test assertions that may be simplified using a more specific
assertion method. This enables better error messages, and makes the
assertions more readable.
The rule only applies within test classes for the moment. It replaces
the deprecated rules {% rule UseAssertEqualsInsteadOfAssertTrue %},
{% rule UseAssertNullInsteadOfAssertTrue %}, {% rule UseAssertSameInsteadOfAssertTrue %},
{% rule UseAssertTrueInsteadOfAssertEquals %}, and {% rule java/design/SimplifyBooleanAssertion %}.
</description>
<priority>3</priority>
<example>
<![CDATA[
import org.junit.Test;
import static org.junit.Assert.*;
class SomeTestClass {
Object a,b;
@Test
void testMethod() {
assertTrue(a.equals(b)); // could be assertEquals(a, b);
assertTrue(!a.equals(b)); // could be assertNotEquals(a, b);
assertTrue(!something); // could be assertFalse(something);
assertFalse(!something); // could be assertTrue(something);
assertTrue(a == b); // could be assertSame(a, b);
assertTrue(a != b); // could be assertNotSame(a, b);
assertTrue(a == null); // could be assertNull(a);
assertTrue(a != null); // could be assertNotNull(a);
}
}
]]>
</example>
</rule>
<rule name="SwitchStmtsShouldHaveDefault"
language="java"
since="1.0"
@@ -1580,9 +1652,12 @@ public class Something {
since="3.1"
message="Use assertEquals(x, y) instead of assertTrue(x.equals(y))"
class="net.sourceforge.pmd.lang.rule.XPathRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#useassertequalsinsteadofasserttrue">
<description>
This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
Deprecated since PMD 6.37.0, use {% rule SimplifiableTestAssertion %} instead.
</description>
<priority>3</priority>
<properties>
@@ -1615,10 +1690,13 @@ public class FooTest extends TestCase {
since="3.5"
message="Use assertNull(x) instead of assertTrue(x==null), or assertNotNull(x) vs assertFalse(x==null)"
class="net.sourceforge.pmd.lang.rule.XPathRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#useassertnullinsteadofasserttrue">
<description>
This rule detects JUnit assertions in object references equality. These assertions should be made by
more specific methods, like assertNull, assertNotNull.
Deprecated since PMD 6.37.0, use {% rule SimplifiableTestAssertion %} instead.
</description>
<priority>3</priority>
<properties>
@@ -1655,10 +1733,13 @@ public class FooTest extends TestCase {
since="3.1"
message="Use assertSame(x, y) instead of assertTrue(x==y), or assertNotSame(x,y) vs assertFalse(x==y)"
class="net.sourceforge.pmd.lang.rule.XPathRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#useassertsameinsteadofasserttrue">
<description>
This rule detects JUnit assertions in object references equality. These assertions should be made
by more specific methods, like assertSame, assertNotSame.
Deprecated since PMD 6.37.0, use {% rule SimplifiableTestAssertion %} instead.
</description>
<priority>3</priority>
<properties>
@@ -1693,9 +1774,12 @@ public class FooTest extends TestCase {
since="5.0"
message="Use assertTrue(x)/assertFalse(x) instead of assertEquals(true, x)/assertEquals(false, x) or assertEquals(Boolean.TRUE, x)/assertEquals(Boolean.FALSE, x)."
class="net.sourceforge.pmd.lang.rule.XPathRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#useasserttrueinsteadofassertequals">
<description>
When asserting a value is the same as a literal or Boxed boolean, use assertTrue/assertFalse, instead of assertEquals.
Deprecated since PMD 6.37.0, use {% rule SimplifiableTestAssertion %} instead.
</description>
<priority>3</priority>
<properties>
@@ -1816,7 +1900,7 @@ public class UseStandardCharsets {
minimumLanguageVersion="1.7"
since="6.12.0"
message="Consider using a try-with-resources statement instead of explicitly closing the resource"
class="net.sourceforge.pmd.lang.rule.XPathRule"
class="net.sourceforge.pmd.lang.java.rule.bestpractices.UseTryWithResourcesRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#usetrywithresources">
<description>
Java 7 introduced the try-with-resources statement. This statement ensures that each resource is closed at the end
@@ -1826,21 +1910,6 @@ the try block was suppressed. With the `try`-with-resources statement, the excep
preserved.
</description>
<priority>3</priority>
<properties>
<property name="closeMethods" type="List[String]" delimiter="," description="Method names in finally block, which trigger this rule" value="close,closeQuietly"/>
<property name="xpath">
<value>
<![CDATA[
//TryStatement[FinallyClause//ExpressionStatement/MethodCall[@MethodName = $closeMethods][
(: vvvvvvvvvvvvvvvvvvvvvvvvv This is to rule out static method call :)
*[1][not(self::TypeExpression) and pmd-java:typeIs('java.lang.AutoCloseable')]
or
ArgumentList/*[pmd-java:typeIs('java.lang.AutoCloseable')]
]]
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
public class TryWithResources {
@@ -1477,6 +1477,36 @@ public class Foo {
</example>
</rule>
<rule name="UnnecessaryBoxing"
language="java"
since="7.0.0"
minimumLanguageVersion="1.5"
message="Unnecessary {0}"
class="net.sourceforge.pmd.lang.java.rule.codestyle.UnnecessaryBoxingRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#unnecessaryboxing">
<description>
Reports explicit boxing and unboxing conversions that may safely be removed,
either because they would be inserted by the compiler automatically,
or because they're semantically a noop (eg unboxing a value to rebox it immediately).
Note that this only handles boxing and unboxing conversions occurring through
calls to `valueOf` or one of the `intValue`, `byteValue`, etc. methods. Casts
that command a conversion are reported by {% rule UnnecessaryCast %} instead.
</description>
<priority>3</priority>
<example><![CDATA[
{
// Instead of
Integer integer = Integer.valueOf(2);
// you may just write
Integer integer = 2;
int i = integer.intValue(); // similarly for unboxing
}
]]>
</example>
</rule>
<!-- This is only restricted to java 5+ because the rule doesn't support
the type system pre-java5, where there were no autoboxing conversions. -->
<rule name="UnnecessaryCast"
@@ -1169,6 +1169,7 @@ public class Foo {
since="3.6"
message="assertTrue(!expr) can be replaced by assertFalse(expr)"
class="net.sourceforge.pmd.lang.rule.XPathRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#simplifybooleanassertion">
<description>
Avoid negation in an assertTrue or assertFalse test.
@@ -1181,6 +1182,7 @@ as:
assertFalse(expr);
Deprecated since PMD 6.37.0, use {% rule java/bestpractices/SimplifiableTestAssertion %} instead.
</description>
<priority>3</priority>
<properties>
@@ -341,10 +341,13 @@ BigDecimal bd3 = new BigDecimal(10); // reference BigDecimal.TEN instead
since="1.2"
message="Avoid instantiating Boolean objects; reference Boolean.TRUE or Boolean.FALSE or call Boolean.valueOf() instead."
class="net.sourceforge.pmd.lang.java.rule.performance.BooleanInstantiationRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#booleaninstantiation">
<description>
Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boolean.valueOf() instead.
Note that new Boolean() is deprecated since JDK 9 for that reason.
Deprecated since PMD 6.37.0, use {% rule java/bestpractices/PrimitiveWrapperInstantiation %} instead.
</description>
<priority>2</priority>
<example>
@@ -360,11 +363,14 @@ Boolean buz = Boolean.valueOf(false); // ...., just reference Boolean.FALSE;
since="4.0"
message="Avoid instantiating Byte objects. Call Byte.valueOf() instead"
class="net.sourceforge.pmd.lang.rule.XPathRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#byteinstantiation">
<description>
Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf().
It makes use of an internal cache that recycles earlier instances making it more memory efficient.
Note that new Byte() is deprecated since JDK 9 for that reason.
Deprecated since PMD 6.37.0, use {% rule java/bestpractices/PrimitiveWrapperInstantiation %} instead.
</description>
<priority>2</priority>
<properties>
@@ -534,11 +540,14 @@ good.append("This is a long string, which is pre-sized");
since="3.5"
message="Avoid instantiating Integer objects. Call Integer.valueOf() instead."
class="net.sourceforge.pmd.lang.rule.XPathRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#integerinstantiation">
<description>
Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf().
It makes use of an internal cache that recycles earlier instances making it more memory efficient.
Note that new Integer() is deprecated since JDK 9 for that reason.
Deprecated since PMD 6.37.0, use {% rule java/bestpractices/PrimitiveWrapperInstantiation %} instead.
</description>
<priority>2</priority>
<properties>
@@ -564,11 +573,14 @@ public class Foo {
since="4.0"
message="Avoid instantiating Long objects.Call Long.valueOf() instead"
class="net.sourceforge.pmd.lang.rule.XPathRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#longinstantiation">
<description>
Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf().
It makes use of an internal cache that recycles earlier instances making it more memory efficient.
Note that new Long() is deprecated since JDK 9 for that reason.
Deprecated since PMD 6.37.0, use {% rule java/bestpractices/PrimitiveWrapperInstantiation %} instead.
</description>
<priority>2</priority>
<properties>
@@ -717,11 +729,14 @@ public class Foo {
since="4.0"
message="Avoid instantiating Short objects. Call Short.valueOf() instead"
class="net.sourceforge.pmd.lang.rule.XPathRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#shortinstantiation">
<description>
Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf().
It makes use of an internal cache that recycles earlier instances making it more memory efficient.
Note that new Short() is deprecated since JDK 9 for that reason.
Deprecated since PMD 6.37.0, use {% rule java/bestpractices/PrimitiveWrapperInstantiation %} instead.
</description>
<priority>2</priority>
<properties>
@@ -831,11 +846,14 @@ public class Foo {
since="3.8"
message="Unnecessary wrapper object creation"
class="net.sourceforge.pmd.lang.java.rule.performance.UnnecessaryWrapperObjectCreationRule"
deprecated="true"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_performance.html#unnecessarywrapperobjectcreation">
<description>
Most wrapper classes provide static conversion methods that avoid the need to create intermediate objects
just to create the primitive forms. Using these avoids the cost of creating objects that also need to be
garbage-collected later.
Deprecated since PMD 6.37.0. The planned replacement is not expected before PMD 7.0.0.
</description>
<priority>3</priority>
<example>
@@ -37,10 +37,12 @@
<!-- <rule ref="category/java/bestpractices.xml/MethodReturnsInternalArray" /> -->
<rule ref="category/java/bestpractices.xml/MissingOverride"/>
<rule ref="category/java/bestpractices.xml/OneDeclarationPerLine"/>
<rule ref="category/java/bestpractices.xml/PrimitiveWrapperInstantiation"/>
<rule ref="category/java/bestpractices.xml/PreserveStackTrace"/>
<!-- <rule ref="category/java/bestpractices.xml/ReplaceEnumerationWithIterator" /> -->
<!-- <rule ref="category/java/bestpractices.xml/ReplaceHashtableWithMap" /> -->
<!-- <rule ref="category/java/bestpractices.xml/ReplaceVectorWithList" /> -->
<rule ref="category/java/bestpractices.xml/SimplifiableTestAssertion"/>
<rule ref="category/java/bestpractices.xml/SwitchStmtsShouldHaveDefault"/>
<!-- <rule ref="category/java/bestpractices.xml/SystemPrintln" /> -->
<!-- <rule ref="category/java/bestpractices.xml/UnusedAssignment"/> -->
@@ -48,10 +50,6 @@
<rule ref="category/java/bestpractices.xml/UnusedLocalVariable"/>
<rule ref="category/java/bestpractices.xml/UnusedPrivateField"/>
<rule ref="category/java/bestpractices.xml/UnusedPrivateMethod"/>
<rule ref="category/java/bestpractices.xml/UseAssertEqualsInsteadOfAssertTrue"/>
<rule ref="category/java/bestpractices.xml/UseAssertNullInsteadOfAssertTrue"/>
<rule ref="category/java/bestpractices.xml/UseAssertSameInsteadOfAssertTrue"/>
<rule ref="category/java/bestpractices.xml/UseAssertTrueInsteadOfAssertEquals"/>
<rule ref="category/java/bestpractices.xml/UseCollectionIsEmpty"/>
<rule ref="category/java/bestpractices.xml/UseStandardCharsets" />
<!-- <rule ref="category/java/bestpractices.xml/UseTryWithResources" /> -->
@@ -104,6 +102,7 @@
<!-- <rule ref="category/java/codestyle.xml/PrematureDeclaration" /> -->
<!-- <rule ref="category/java/codestyle.xml/TooManyStaticImports" /> -->
<rule ref="category/java/codestyle.xml/UnnecessaryAnnotationValueElement"/>
<!-- <rule ref="category/java/codestyle.xml/UnnecessaryBoxing" /> -->
<!-- <rule ref="category/java/codestyle.xml/UnnecessaryCast" /> -->
<rule ref="category/java/codestyle.xml/UnnecessaryConstructor"/>
<rule ref="category/java/codestyle.xml/UnnecessaryFullyQualifiedName"/>
@@ -153,7 +152,6 @@
<!-- <rule ref="category/java/design.xml/NPathComplexity" /> -->
<!-- <rule ref="category/java/design.xml/SignatureDeclareThrowsException" /> -->
<rule ref="category/java/design.xml/SimplifiedTernary"/>
<!-- <rule ref="category/java/design.xml/SimplifyBooleanAssertion" /> -->
<!-- <rule ref="category/java/design.xml/SimplifyBooleanExpressions" /> -->
<rule ref="category/java/design.xml/SimplifyBooleanReturns"/>
<rule ref="category/java/design.xml/SimplifyConditional"/>
@@ -299,23 +297,17 @@
<!-- <rule ref="category/java/performance.xml/AvoidInstantiatingObjectsInLoops" /> -->
<!-- <rule ref="category/java/performance.xml/AvoidUsingShortType"/> -->
<rule ref="category/java/performance.xml/BigIntegerInstantiation"/>
<rule ref="category/java/performance.xml/BooleanInstantiation"/>
<!-- <rule ref="category/java/performance.xml/ByteInstantiation" /> -->
<!-- <rule ref="category/java/performance.xml/ConsecutiveAppendsShouldReuse" /> -->
<!-- <rule ref="category/java/performance.xml/ConsecutiveLiteralAppends" /> -->
<!-- <rule ref="category/java/performance.xml/InefficientEmptyStringCheck" /> -->
<!-- <rule ref="category/java/performance.xml/InefficientStringBuffering" /> -->
<!-- <rule ref="category/java/performance.xml/InsufficientStringBufferDeclaration" /> -->
<!-- <rule ref="category/java/performance.xml/IntegerInstantiation" /> -->
<!-- <rule ref="category/java/performance.xml/LongInstantiation" /> -->
<rule ref="category/java/performance.xml/OptimizableToArrayCall"/>
<!--<rule ref="category/java/performance.xml/RedundantFieldInitializer"/>-->
<!-- <rule ref="category/java/performance.xml/SimplifyStartsWith" /> -->
<!-- <rule ref="category/java/performance.xml/ShortInstantiation" /> -->
<!-- <rule ref="category/java/performance.xml/StringInstantiation" /> -->
<!-- <rule ref="category/java/performance.xml/StringToString" /> -->
<!--<rule ref="category/java/performance.xml/TooFewBranchesForASwitchStatement"/>-->
<!-- <rule ref="category/java/performance.xml/UnnecessaryWrapperObjectCreation" /> -->
<!-- <rule ref="category/java/performance.xml/UseArrayListInsteadOfVector" /> -->
<!-- <rule ref="category/java/performance.xml/UseArraysAsList" /> -->
<!-- <rule ref="category/java/performance.xml/UseIndexOfChar" /> -->
@@ -0,0 +1,51 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.LanguageVersion;
public class JavaLanguageModuleTest {
private Language javaLanguage = LanguageRegistry.getLanguage(JavaLanguageModule.NAME);
@Test
public void java9IsSmallerThanJava10() {
LanguageVersion java9 = javaLanguage.getVersion("9");
LanguageVersion java10 = javaLanguage.getVersion("10");
Assert.assertTrue("java9 should be smaller than java10", java9.compareTo(java10) < 0);
}
@Test
public void previewVersionShouldBeGreaterThanNonPreview() {
LanguageVersion java16 = javaLanguage.getVersion("16");
LanguageVersion java16p = javaLanguage.getVersion("16-preview");
Assert.assertTrue("java16-preview should be greater than java16", java16p.compareTo(java16) > 0);
}
@Test
public void testCompareToVersion() {
LanguageVersion java9 = javaLanguage.getVersion("9");
Assert.assertTrue("java9 should be smaller than java10", java9.compareToVersion("10") < 0);
}
@Test
public void allVersions() {
List<LanguageVersion> versions = javaLanguage.getVersions();
for (int i = 1; i < versions.size(); i++) {
LanguageVersion previous = versions.get(i - 1);
LanguageVersion current = versions.get(i);
Assert.assertTrue("Version " + previous + " should be smaller than " + current,
previous.compareTo(current) < 0);
}
}
}
@@ -0,0 +1,12 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.bestpractices;
import net.sourceforge.pmd.testframework.PmdRuleTst;
@org.junit.Ignore("Rule has not been updated yet")
public class PrimitiveWrapperInstantiationTest extends PmdRuleTst {
// no additional unit tests
}
@@ -0,0 +1,12 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.bestpractices;
import net.sourceforge.pmd.testframework.PmdRuleTst;
@org.junit.Ignore("Rule has not been updated yet")
public class SimplifiableTestAssertionTest extends PmdRuleTst {
// no additional unit tests
}
@@ -0,0 +1,11 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.codestyle;
import net.sourceforge.pmd.testframework.PmdRuleTst;
public class UnnecessaryBoxingTest extends PmdRuleTst {
// no additional unit tests
}
@@ -219,6 +219,7 @@ public class TryWithResources {
}
]]></code>
</test-code>
<test-code>
<description>[java] UseTryWithResources - false negative for explicit close #2882</description>
<expected-problems>1</expected-problems>
@@ -276,4 +277,118 @@ public class TryWithResources {
}
]]></code>
</test-code>
<code-fragment id="issue-3235"><![CDATA[
import java.io.IOException;
import java.io.Reader;
class Scratch {
public static int count(AutoCloseable iterator) {
int count = 0;
try {
count++;
} finally {
iterator.close();
}
return count;
}
}
class Holder implements AutoCloseable {
private Reader reader;
public void close() throws IOException {
try {
someOtherActivity();
} finally {
reader.close();
}
}
private void someOtherActivity() throws IOException {
// do stuff
}
}
]]></code-fragment>
<test-code>
<description>[java] UseTryWithResources false positive when closeable is provided as a method argument or class field #3235 before java 9</description>
<expected-problems>0</expected-problems>
<code-ref id="issue-3235"/>
<source-type>java 1.8</source-type>
</test-code>
<test-code>
<description>[java] UseTryWithResources false positive when closeable is provided as a method argument or class field #3235</description>
<expected-problems>2</expected-problems>
<expected-linenumbers>7,19</expected-linenumbers>
<code-ref id="issue-3235"/>
</test-code>
<code-fragment id="issue-3235-with-local-var"><![CDATA[
import java.io.IOException;
import java.io.Reader;
class Scratch {
public static int count() {
AutoCloseable iterator;
int count = 0;
try {
count++;
} finally {
iterator.close();
}
return count;
}
}
class Holder implements AutoCloseable {
public void close() throws IOException {
Reader reader;
try {
someOtherActivity();
} finally {
reader.close();
}
}
private void someOtherActivity() throws IOException {
// do stuff
}
}
]]></code-fragment>
<test-code>
<description>[java] UseTryWithResources with local var and before java 9 #3235</description>
<expected-problems>2</expected-problems>
<expected-linenumbers>8,20</expected-linenumbers>
<code-ref id="issue-3235-with-local-var"/>
<source-type>java 1.8</source-type>
</test-code>
<test-code>
<description>[java] UseTryWithResources with local var and latest java #3235</description>
<expected-problems>2</expected-problems>
<expected-linenumbers>8,20</expected-linenumbers>
<code-ref id="issue-3235-with-local-var"/>
</test-code>
<test-code>
<description>NPE when determining closeTarget</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>6</expected-linenumbers>
<code><![CDATA[
import java.io.InputStream;
import java.io.IOException;
public class UseTryWithResources {
public void read(InputStream is, boolean close) throws IOException {
try {
is.read();
} finally {
if (close) {
is.close();
}
}
}
}
]]></code>
</test-code>
</test-data>
Loaded 30 of 32 files, more files were not shown because too many files have changed in this diff. Show more