Merge branch 'master' into pmd/7.0.x
This commit is contained in:
@ -6529,6 +6529,15 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"code"
|
"code"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "gredler",
|
||||||
|
"name": "Daniel Gredler",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/178883?v=4",
|
||||||
|
"profile": "https://github.com/gredler",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7,
|
"contributorsPerLine": 7,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -57,8 +57,11 @@ not support all features of the latest EcmaScript standard.
|
|||||||
* [#3644](https://github.com/pmd/pmd/issues/3644): \[java] InvalidLogMessageFormat: false positives with logstash structured logging
|
* [#3644](https://github.com/pmd/pmd/issues/3644): \[java] InvalidLogMessageFormat: false positives with logstash structured logging
|
||||||
* [#3686](https://github.com/pmd/pmd/issues/3686): \[java] ReturnEmptyCollectionRatherThanNull - false negative with conditioned returns
|
* [#3686](https://github.com/pmd/pmd/issues/3686): \[java] ReturnEmptyCollectionRatherThanNull - false negative with conditioned returns
|
||||||
* [#3701](https://github.com/pmd/pmd/issues/3701): \[java] MissingStaticMethodInNonInstantiatableClass false positive with method inner classes
|
* [#3701](https://github.com/pmd/pmd/issues/3701): \[java] MissingStaticMethodInNonInstantiatableClass false positive with method inner classes
|
||||||
|
* [#3721](https://github.com/pmd/pmd/issues/3721): \[java] ReturnEmptyCollectionRatherThanNull - false positive with stream and lambda
|
||||||
* java-performance
|
* java-performance
|
||||||
* [#3492](https://github.com/pmd/pmd/issues/3492): \[java] UselessStringValueOf: False positive when there is no initial String to append to
|
* [#3492](https://github.com/pmd/pmd/issues/3492): \[java] UselessStringValueOf: False positive when there is no initial String to append to
|
||||||
|
* [#3639](https://github.com/pmd/pmd/issues/3639): \[java] UseStringBufferLength: false negative with empty string variable
|
||||||
|
* [#3712](https://github.com/pmd/pmd/issues/3712): \[java] InsufficientStringBufferDeclaration false positive with StringBuilder.setLength(0)
|
||||||
* javascript
|
* javascript
|
||||||
* [#3703](https://github.com/pmd/pmd/issues/3703): \[javascript] Error - no Node adapter class registered for XmlPropRef
|
* [#3703](https://github.com/pmd/pmd/issues/3703): \[javascript] Error - no Node adapter class registered for XmlPropRef
|
||||||
|
|
||||||
@ -74,9 +77,11 @@ not support all features of the latest EcmaScript standard.
|
|||||||
* [#3713](https://github.com/pmd/pmd/pull/3713): \[java] Enhance UnnecessaryModifier to support records - [Vincent Galloy](https://github.com/vgalloy)
|
* [#3713](https://github.com/pmd/pmd/pull/3713): \[java] Enhance UnnecessaryModifier to support records - [Vincent Galloy](https://github.com/vgalloy)
|
||||||
* [#3719](https://github.com/pmd/pmd/pull/3719): \[java] Upgrade log4j to 2.17.1 - [Daniel Paul Searles](https://github.com/squaresurf)
|
* [#3719](https://github.com/pmd/pmd/pull/3719): \[java] Upgrade log4j to 2.17.1 - [Daniel Paul Searles](https://github.com/squaresurf)
|
||||||
* [#3720](https://github.com/pmd/pmd/pull/3720): \[java] New rule: FinalParameterInAbstractMethod - [Vincent Galloy](https://github.com/vgalloy)
|
* [#3720](https://github.com/pmd/pmd/pull/3720): \[java] New rule: FinalParameterInAbstractMethod - [Vincent Galloy](https://github.com/vgalloy)
|
||||||
* [#3724](https://github.com/pmd/pmd/pull/3724): \[java] Fix for #3686 - fix FinalFieldCouldBeStatic - [Oleksii Dykov](https://github.com/dykov)
|
* [#3724](https://github.com/pmd/pmd/pull/3724): \[java] Fix for #3679 - fix FinalFieldCouldBeStatic - [Oleksii Dykov](https://github.com/dykov)
|
||||||
|
* [#3727](https://github.com/pmd/pmd/pull/3727): \[java] #3724 - fix FinalFieldCouldBeStatic: triggers only if the referenced name is static - [Oleksii Dykov](https://github.com/dykov)
|
||||||
* [#3742](https://github.com/pmd/pmd/pull/3742): \[java] Fix #3701 - fix MissingStaticMethodInNonInstantiatableClass for method local classes - [Oleksii Dykov](https://github.com/dykov)
|
* [#3742](https://github.com/pmd/pmd/pull/3742): \[java] Fix #3701 - fix MissingStaticMethodInNonInstantiatableClass for method local classes - [Oleksii Dykov](https://github.com/dykov)
|
||||||
* [#3744](https://github.com/pmd/pmd/pull/3744): \[core] Updated SaxonXPathRuleQueryTest.java - [Vyom Yadav](https://github.com/Vyom-Yadav)
|
* [#3744](https://github.com/pmd/pmd/pull/3744): \[core] Updated SaxonXPathRuleQueryTest.java - [Vyom Yadav](https://github.com/Vyom-Yadav)
|
||||||
|
* [#3745](https://github.com/pmd/pmd/pull/3745): \[java] Fix #3712: InsufficientStringBufferDeclaration setLength false positive - [Daniel Gredler](https://github.com/gredler)
|
||||||
|
|
||||||
{% endtocmaker %}
|
{% endtocmaker %}
|
||||||
|
|
||||||
|
@ -221,7 +221,6 @@ public class DeadLinksChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("PMD.ReturnEmptyCollectionRatherThanNull")
|
|
||||||
private Map<Path, List<String>> joinFutures(Map<Path, List<Future<String>>> map) {
|
private Map<Path, List<String>> joinFutures(Map<Path, List<Future<String>>> map) {
|
||||||
Map<Path, List<String>> joined = new HashMap<>();
|
Map<Path, List<String>> joined = new HashMap<>();
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ public class InsufficientStringBufferDeclarationRule extends AbstractJavaRulecha
|
|||||||
} else if (usage.getParent() instanceof ASTAssignmentExpression) {
|
} else if (usage.getParent() instanceof ASTAssignmentExpression) {
|
||||||
ASTAssignmentExpression assignment = (ASTAssignmentExpression) usage.getParent();
|
ASTAssignmentExpression assignment = (ASTAssignmentExpression) usage.getParent();
|
||||||
State newState = getConstructorCapacity(node, assignment.getRightOperand());
|
State newState = getConstructorCapacity(node, assignment.getRightOperand());
|
||||||
|
|
||||||
if (newState.rootNode != null) {
|
if (newState.rootNode != null) {
|
||||||
if (state.isInsufficient()) {
|
if (state.isInsufficient()) {
|
||||||
addViolation(data, state.rootNode, state.getParamsForViolation());
|
addViolation(data, state.rootNode, state.getParamsForViolation());
|
||||||
|
@ -783,7 +783,8 @@ in each object at runtime.
|
|||||||
[pmd-java:modifiers() = 'final']
|
[pmd-java:modifiers() = 'final']
|
||||||
[not(pmd-java:modifiers() = 'static')]
|
[not(pmd-java:modifiers() = 'static')]
|
||||||
[not(.//Annotation[pmd-java:typeIs('lombok.Builder.Default')])]
|
[not(.//Annotation[pmd-java:typeIs('lombok.Builder.Default')])]
|
||||||
/VariableDeclarator[NumericLiteral or StringLiteral or CharLiteral or BooleanLiteral or NullLiteral or VariableAccess or FieldAccess]
|
/VariableDeclarator[NumericLiteral or StringLiteral or CharLiteral or BooleanLiteral or NullLiteral
|
||||||
|
or VariableAccess or FieldAccess]
|
||||||
/VariableDeclaratorId
|
/VariableDeclaratorId
|
||||||
]]>
|
]]>
|
||||||
</value>
|
</value>
|
||||||
|
@ -2648,11 +2648,12 @@ See Effective Java, 3rd Edition, Item 54: Return empty collections or arrays ins
|
|||||||
<property name="xpath">
|
<property name="xpath">
|
||||||
<value>
|
<value>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
//MethodDeclaration
|
//ReturnStatement/NullLiteral
|
||||||
|
[ancestor::MethodDeclaration[1]
|
||||||
[ArrayType
|
[ArrayType
|
||||||
or ClassOrInterfaceType[pmd-java:typeIs('java.util.Collection')
|
or ClassOrInterfaceType[pmd-java:typeIs('java.util.Collection')
|
||||||
or pmd-java:typeIs('java.util.Map')]]
|
or pmd-java:typeIs('java.util.Map')]]
|
||||||
//ReturnStatement/NullLiteral
|
]
|
||||||
[not(./ancestor::LambdaExpression)]
|
[not(./ancestor::LambdaExpression)]
|
||||||
[not(./ancestor::AnonymousClassDeclaration)]
|
[not(./ancestor::AnonymousClassDeclaration)]
|
||||||
]]>
|
]]>
|
||||||
|
@ -175,6 +175,24 @@ class Clazz {
|
|||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
class Clazz {
|
class Clazz {
|
||||||
public final int a = getValue();
|
public final int a = getValue();
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>
|
||||||
|
#3724 - the rule should be triggered only if the referenced name is static
|
||||||
|
</description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>7</expected-linenumbers>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class Foo {
|
||||||
|
private int nonStaticPrivate = 1; //no violation cause non-final
|
||||||
|
private final int nonStatic = nonStaticPrivate; //no violation cause referenced name is non-static
|
||||||
|
|
||||||
|
//private static final int staticFinal = nonStatic; //noncompliant: Non-static field 'nonStatic' cannot be referenced from a static context
|
||||||
|
private static int staticNonFinal = 1; //no violation cause non-final
|
||||||
|
private final int nonStatic2 = staticNonFinal; //violation because it could be static
|
||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
@ -179,4 +179,55 @@ public class Foo {
|
|||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>[java] ReturnEmptyCollectionRatherThanNull - false positive with stream and lambda #3721</description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>37</expected-linenumbers>
|
||||||
|
<code><![CDATA[
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class Foo {
|
||||||
|
private Map<Path, List<String>> joinFutures(Map<String, List<Future<String>>> map) {
|
||||||
|
Map<String, List<String>> joined = new HashMap<>();
|
||||||
|
|
||||||
|
for (String p : map.keySet()) {
|
||||||
|
List<String> evaluatedResult = map.get(p).stream()
|
||||||
|
.map(f -> {
|
||||||
|
try {
|
||||||
|
return f.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null; // <----- false positive here
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.sorted(Comparator.naturalOrder())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!evaluatedResult.isEmpty()) {
|
||||||
|
joined.put(p, evaluatedResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checking basic lambdas and anonymous classes as well
|
||||||
|
Callable<Object> c = a -> { return null; }; // <----- false positive here
|
||||||
|
Callable<Object> c2 = new Callable<Object>() {
|
||||||
|
public Object call() {
|
||||||
|
return null; // <----- false positive here
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Callable<List<String>> c3 = new Callable<List<String>>() {
|
||||||
|
public List<String> call() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return joined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
</test-data>
|
</test-data>
|
||||||
|
@ -1220,13 +1220,14 @@ public class FalsePositive {
|
|||||||
|
|
||||||
<test-code>
|
<test-code>
|
||||||
<description>Calculated initial size in constructor</description>
|
<description>Calculated initial size in constructor</description>
|
||||||
<expected-problems>4</expected-problems>
|
<expected-problems>5</expected-problems>
|
||||||
<expected-linenumbers>10,34,44,61</expected-linenumbers>
|
<expected-linenumbers>10,34,44,61,88</expected-linenumbers>
|
||||||
<expected-messages>
|
<expected-messages>
|
||||||
<message>StringBuilder has been initialized with size 4, but has at least 5 characters appended.</message>
|
<message>StringBuilder has been initialized with size 4, but has at least 5 characters appended.</message>
|
||||||
<message>StringBuilder has been initialized with size 5, but has at least 6 characters appended.</message>
|
<message>StringBuilder has been initialized with size 5, but has at least 6 characters appended.</message>
|
||||||
<message>StringBuilder has been initialized with size 8, but has at least 10 characters appended.</message>
|
<message>StringBuilder has been initialized with size 8, but has at least 10 characters appended.</message>
|
||||||
<message>StringBuilder has been initialized with size 8, but has at least 9 characters appended.</message>
|
<message>StringBuilder has been initialized with size 8, but has at least 9 characters appended.</message>
|
||||||
|
<message>StringBuilder has been initialized with size 7, but has at least 8 characters appended.</message>
|
||||||
</expected-messages>
|
</expected-messages>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public class InsufficientStringBufferDeclaration {
|
public class InsufficientStringBufferDeclaration {
|
||||||
@ -1296,6 +1297,30 @@ public class InsufficientStringBufferDeclaration {
|
|||||||
sb.append('d'); // length is now 9
|
sb.append('d'); // length is now 9
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String case9_sufficient_setLength() {
|
||||||
|
StringBuilder sb = new StringBuilder(4);
|
||||||
|
sb.append("xxxx");
|
||||||
|
sb.setLength(0); // length is 0, capacity is still 4
|
||||||
|
sb.append("aaaa");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String case10_unknown_setLength(String in) {
|
||||||
|
StringBuilder sb = new StringBuilder(in.length()); // unknown
|
||||||
|
sb.append("xxxx");
|
||||||
|
sb.setLength(0); // length is 0, capacity is still unknown
|
||||||
|
sb.append("aaaa");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String case11_unknown_ensureCapacity(String in) {
|
||||||
|
StringBuilder sb = new StringBuilder(in.length()); // unknown
|
||||||
|
sb.append("xxxx"); // length is 4
|
||||||
|
sb.ensureCapacity(7); // line 88 - length is still 4, new capacity now at least 7 -> violation here
|
||||||
|
sb.append("aaaa"); // length is 8
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
@ -189,6 +189,28 @@ public class Ineffecient
|
|||||||
{
|
{
|
||||||
return "Ineffecient";
|
return "Ineffecient";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>[java] UseStringBufferLength: false negative with empty string variable #3639</description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>5</expected-linenumbers>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class Foo {
|
||||||
|
public void foo() {
|
||||||
|
StringBuffer sb = new StringBuffer("any_string");
|
||||||
|
final String nullStr = "";
|
||||||
|
if (sb.toString().equals(nullStr)) { // PMD should report a warning here
|
||||||
|
System.out.println("Buffer is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
// the preferred way
|
||||||
|
if (sb.length() == 0) {
|
||||||
|
System.out.println("Buffer is empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
Reference in New Issue
Block a user