Merge branch '7.0.x' into java-more-rules-2-sunsecure

This commit is contained in:
Clément Fournier committed 2021-03-05 15:15:03 +01:00
commit d9afc4995e
68 files changed
+632 -262

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@ repository: pmd/pmd
pmd:
version: 7.0.0-SNAPSHOT
previous_version: 6.31.0
previous_version: 6.32.0
date: ??-?????-2021
release_type: major
+26
View File
@@ -246,6 +246,32 @@ the breaking API changes will be performed in 7.0.0.
an API is tagged as `@Deprecated` or not in the latest minor release. During the development of 7.0.0,
we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %}
#### 6.32.0
##### Experimental APIs
* The experimental class `ASTTypeTestPattern` has been renamed to {% jdoc java::lang.java.ast.ASTTypePattern %}
in order to align the naming to the JLS.
* The experimental class `ASTRecordConstructorDeclaration` has been renamed to {% jdoc java::lang.java.ast.ASTCompactConstructorDeclaration %}
in order to align the naming to the JLS.
* The AST types and APIs around Pattern Matching and Records are not experimental anymore:
* {% jdoc !!java::lang.java.ast.ASTVariableDeclaratorId#isPatternBinding() %}
* {% jdoc java::lang.java.ast.ASTPattern %}
* {% jdoc java::lang.java.ast.ASTTypePattern %}
* {% jdoc java::lang.java.ast.ASTRecordDeclaration %}
* {% jdoc java::lang.java.ast.ASTRecordComponentList %}
* {% jdoc java::lang.java.ast.ASTRecordComponent %}
* {% jdoc java::lang.java.ast.ASTRecordBody %}
* {% jdoc java::lang.java.ast.ASTCompactConstructorDeclaration %}
##### 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 protected or public member of the Java rule {% jdoc java::lang.java.rule.bestpractices.AvoidUsingHardCodedIPRule %}
are deprecated and considered to be internal API. They will be removed with PMD 7.
#### 6.31.0
##### Deprecated API
@@ -26,6 +26,8 @@ author: Tom Copeland <tom@infoether.org>
### PMD in general and other Language Modules
* February 2021 - Artem Krosheninnikov's talk about Quality Assurance Automation: [Artem Krosheninnikov, Wrike - How static analysis can help in QAA processes](https://www.youtube.com/watch?v=L42zH5ne074)
* May 2019 - [Code quality assurance with PMD An extensible static code analyser for Java and other languages](https://www.datarespons.com/code-quality-assurance-with-pmd/)
* February 2012 - Romain Pelisse's lightning talk at FOSDEM 2012 about "PMD5: What can it do for you?".
+2 -2
View File
@@ -60,8 +60,8 @@ All property assignments must be enclosed in a `properties` element, which is it
Some properties take multiple values (a list), in which case you can provide them all by delimiting them with a delimiter character. It is usually a pipe ('\|'), or a comma (',') for numeric properties, e.g.
```xml
<property name="legalCollectionTypes"
value="java.util.ArrayList|java.util.Vector|java.util.HashMap"/>
<property name="legalCollectionTypes"
value="java.util.ArrayList|java.util.Vector|java.util.HashMap"/>
```
These properties are referred to as **multivalued properties** in this documentation.
+31 -31
View File
@@ -253,14 +253,14 @@ For details, see [CPD Report Formats](pmd_userdocs_cpd_report_formats.html).
Andy Glover wrote an Ant task for CPD; here's how to use it:
```xml
<target name="cpd">
<taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask" />
<cpd minimumTokenCount="100" outputFile="/home/tom/cpd.txt">
<fileset dir="/home/tom/tmp/ant">
<include name="**/*.java"/>
</fileset>
</cpd>
</target>
<target name="cpd">
<taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask" />
<cpd minimumTokenCount="100" outputFile="/home/tom/cpd.txt">
<fileset dir="/home/tom/tmp/ant">
<include name="**/*.java"/>
</fileset>
</cpd>
</target>
```
<!-- TODO avoid duplicating the descriptions! -->
@@ -352,7 +352,7 @@ Also, you can get an HTML report from CPD by using the XSLT script in pmd/etc/xs
the CPD task as usual and right after it invoke the Ant XSLT script like this:
```xml
<xslt in="cpd.xml" style="etc/xslt/cpdhtml.xslt" out="cpd.html" />
<xslt in="cpd.xml" style="etc/xslt/cpdhtml.xslt" out="cpd.html" />
```
## GUI
@@ -378,23 +378,23 @@ Arbitrary blocks of code can be ignored through comments on **Java**, **C/C++**,
**Kotlin**, **Lua**, **Matlab**, **Objective-C**, **PL/SQL**, **Python**, **Scala**, **Swift** and **C#** by including the keywords `CPD-OFF` and `CPD-ON`.
```java
public Object someParameterizedFactoryMethod(int x) throws Exception {
// some unignored code
public Object someParameterizedFactoryMethod(int x) throws Exception {
// some unignored code
// tell cpd to start ignoring code - CPD-OFF
// tell cpd to start ignoring code - CPD-OFF
// mission critical code, manually loop unroll
goDoSomethingAwesome(x + x / 2);
goDoSomethingAwesome(x + x / 2);
goDoSomethingAwesome(x + x / 2);
goDoSomethingAwesome(x + x / 2);
goDoSomethingAwesome(x + x / 2);
goDoSomethingAwesome(x + x / 2);
// mission critical code, manually loop unroll
goDoSomethingAwesome(x + x / 2);
goDoSomethingAwesome(x + x / 2);
goDoSomethingAwesome(x + x / 2);
goDoSomethingAwesome(x + x / 2);
goDoSomethingAwesome(x + x / 2);
goDoSomethingAwesome(x + x / 2);
// resume CPD analysis - CPD-ON
// resume CPD analysis - CPD-ON
// further code will *not* be ignored
}
// further code will *not* be ignored
}
```
Additionally, **Java** allows to toggle suppression by adding the annotations
@@ -405,15 +405,15 @@ This approach however, is limited to the locations were `@SuppressWarnings` is a
It's legacy and the new comment's based approach should be favored.
```java
//enable suppression
@SuppressWarnings("CPD-START")
public Object someParameterizedFactoryMethod(int x) throws Exception {
// any code here will be ignored for the duplication detection
}
//disable suppression
@SuppressWarnings("CPD-END)
public void nextMethod() {
}
//enable suppression
@SuppressWarnings("CPD-START")
public Object someParameterizedFactoryMethod(int x) throws Exception {
// any code here will be ignored for the duplication detection
}
//disable suppression
@SuppressWarnings("CPD-END)
public void nextMethod() {
}
```
Other languages currently have no support to suppress CPD reports. In the future,
+49 -49
View File
@@ -26,17 +26,17 @@ report additionally in `<reporting><plugins/></reporting>` elements. Here's an e
section:
```xml
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>{{ page.mpmd_version }}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>{{ page.mpmd_version }}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
```
When defining the version in the pluginManagment section, then it doesn't need to be specified in the normal plugins
@@ -123,22 +123,22 @@ To specify a ruleset, simply edit the previous configuration:
``` xml
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>{{ page.mpmd_version }}</version>
<configuration>
<rulesets>
<ruleset>/rulesets/java/quickstart.xml</ruleset>
<ruleset>d:\rulesets\my-ruleset.xml</ruleset>
<ruleset>http://localhost/design.xml</ruleset>
</rulesets>
</configuration>
</plugin>
</plugins>
</reporting>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>{{ page.mpmd_version }}</version>
<configuration>
<rulesets>
<ruleset>/rulesets/java/quickstart.xml</ruleset>
<ruleset>d:\rulesets\my-ruleset.xml</ruleset>
<ruleset>http://localhost/design.xml</ruleset>
</rulesets>
</configuration>
</plugin>
</plugins>
</reporting>
```
The value of the 'ruleset' element can either be a relative address, an absolute address or even an url.
@@ -156,17 +156,17 @@ When using the Maven PMD plugin 3.8 or later along with PMD 5.6.0 or later, you
speed up PMD's execution while retaining the quality of the analysis. You can additionally customize where the cache is stored::
```xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>{{ page.mpmd_version }}</version> <!-- or use version from pluginManagement -->
<configuration>
<!-- enable incremental analysis -->
<analysisCache>true</analysisCache>
<!-- analysisCacheLocation: optional - points to the following location by default -->
<analysisCacheLocation>${project.build.directory}/pmd/pmd.cache</analysisCacheLocation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>{{ page.mpmd_version }}</version> <!-- or use version from pluginManagement -->
<configuration>
<!-- enable incremental analysis -->
<analysisCache>true</analysisCache>
<!-- analysisCacheLocation: optional - points to the following location by default -->
<analysisCacheLocation>${project.build.directory}/pmd/pmd.cache</analysisCacheLocation>
</configuration>
</plugin>
```
#### Other configurations
@@ -175,17 +175,17 @@ The Maven PMD plugin allows you to configure CPD, targetJDK, and the use of XRef
the report to html source files, and the file encoding:
```xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>{{ page.mpmd_version }}</version> <!-- or use version from pluginManagement -->
<configuration>
<linkXRef>true</linkXRef>
<sourceEncoding>ISO-8859-1</sourceEncoding>
<minimumTokens>30</minimumTokens>
<targetJdk>1.4</targetJdk>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>{{ page.mpmd_version }}</version> <!-- or use version from pluginManagement -->
<configuration>
<linkXRef>true</linkXRef>
<sourceEncoding>ISO-8859-1</sourceEncoding>
<minimumTokens>30</minimumTokens>
<targetJdk>1.4</targetJdk>
</configuration>
</plugin>
```
#### Upgrading the PMD version at runtime
+3 -45
View File
@@ -19,57 +19,15 @@ This is a {{ site.pmd.release_type }} release.
### New and noteworthy
#### Java 16 Support
This release of PMD brings support for Java 16. PMD supports [JEP 394: Pattern Matching for instanceof](https://openjdk.java.net/jeps/394) and [JEP 395: Records](https://openjdk.java.net/jeps/395). Both have been promoted
to be a standard language feature of Java 16.
PMD also supports [JEP 397: Sealed Classes (Second Preview)](https://openjdk.java.net/jeps/397) as a preview
language feature. In order to analyze a project with PMD that uses these language features, you'll need to enable
it via the environment variable `PMD_JAVA_OPTS` and select the new language version `16-preview`:
export PMD_JAVA_OPTS=--enable-preview
./run.sh pmd -language java -version 16-preview ...
Note: Support for Java 14 preview language features have been removed. The version "14-preview" is no longer available.
#### Modified Rules
* The Apex rule {% rule "apex/documentation/ApexDoc" %} has two new properties: `reportPrivate` and
`reportProtected`. Previously the rule only considered public and global classes, methods, and
properties. With these properties, you can verify the existence of ApexDoc comments for private
and protected methods as well. By default, these properties are disabled to preserve backwards
compatible behavior.
### Fixed Issues
* apex-documentation
* [#3075](https://github.com/pmd/pmd/issues/3075): \[apex] ApexDoc should support private access modifier
* plsql
* [#3106](https://github.com/pmd/pmd/issues/3106): \[plsql] ParseException while parsing EXECUTE IMMEDIATE 'drop database link ' || linkname;
* java
* [#3117](https://github.com/pmd/pmd/issues/3117): \[java] Infinite loop when parsing invalid code nested in lambdas
* [#3145](https://github.com/pmd/pmd/issues/3145): \[java] Parse exception when using "record" as variable name
### API Changes
#### pmd-java
* The experimental class `ASTTypeTestPattern` has been renamed to {% jdoc java::lang.java.ast.ASTTypePattern %}
in order to align the naming to the JLS.
* The experimental class `ASTRecordConstructorDeclaration` has been renamed to {% jdoc java::lang.java.ast.ASTCompactConstructorDeclaration %}
in order to align the naming to the JLS.
* The AST types and APIs around Pattern Matching and Records are not experimental anymore:
* {% jdoc !!java::lang.java.ast.ASTVariableDeclaratorId#isPatternBinding() %}
* {% jdoc java::lang.java.ast.ASTPattern %}
* {% jdoc java::lang.java.ast.ASTTypePattern %}
* {% jdoc java::lang.java.ast.ASTRecordDeclaration %}
* {% jdoc java::lang.java.ast.ASTRecordComponentList %}
* {% jdoc java::lang.java.ast.ASTRecordComponent %}
* {% jdoc java::lang.java.ast.ASTRecordBody %}
* {% jdoc java::lang.java.ast.ASTCompactConstructorDeclaration %}
### External Contributions
* [#3098](https://github.com/pmd/pmd/pull/3098): \[apex] ApexDoc optionally report private and protected - [Jonathan Wiesel](https://github.com/jonathanwiesel)
* [#3107](https://github.com/pmd/pmd/pull/3107): \[plsql] Fix ParseException for EXECUTE IMMEDIATE str1||str2; - [hvbtup](https://github.com/hvbtup)
{% endtocmaker %}
+94
View File
@@ -5,6 +5,100 @@ permalink: pmd_release_notes_old.html
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
## 27-February-2021 - 6.32.0
The PMD team is pleased to announce PMD 6.32.0.
This is a minor release.
### Table Of Contents
* [New and noteworthy](#new-and-noteworthy)
* [Java 16 Support](#java-16-support)
* [Modified Rules](#modified-rules)
* [Fixed Issues](#fixed-issues)
* [API Changes](#api-changes)
* [Experimental APIs](#experimental-apis)
* [Internal API](#internal-api)
* [External Contributions](#external-contributions)
* [Stats](#stats)
### New and noteworthy
#### Java 16 Support
This release of PMD brings support for Java 16. PMD supports [JEP 394: Pattern Matching for instanceof](https://openjdk.java.net/jeps/394) and [JEP 395: Records](https://openjdk.java.net/jeps/395). Both have been promoted
to be a standard language feature of Java 16.
PMD also supports [JEP 397: Sealed Classes (Second Preview)](https://openjdk.java.net/jeps/397) as a preview
language feature. In order to analyze a project with PMD that uses these language features, you'll need to enable
it via the environment variable `PMD_JAVA_OPTS` and select the new language version `16-preview`:
export PMD_JAVA_OPTS=--enable-preview
./run.sh pmd -language java -version 16-preview ...
Note: Support for Java 14 preview language features have been removed. The version "14-preview" is no longer available.
#### Modified Rules
* The Apex rule [`ApexDoc`](https://pmd.github.io/pmd-6.32.0/pmd_rules_apex_documentation.html#apexdoc) has two new properties: `reportPrivate` and
`reportProtected`. Previously the rule only considered public and global classes, methods, and
properties. With these properties, you can verify the existence of ApexDoc comments for private
and protected methods as well. By default, these properties are disabled to preserve backwards
compatible behavior.
### Fixed Issues
* apex-documentation
* [#3075](https://github.com/pmd/pmd/issues/3075): \[apex] ApexDoc should support private access modifier
* java
* [#3101](https://github.com/pmd/pmd/issues/3101): \[java] NullPointerException when running PMD under JRE 11
* java-bestpractices
* [#3132](https://github.com/pmd/pmd/issues/3132): \[java] UnusedImports with static imports on subclasses
* java-errorprone
* [#2716](https://github.com/pmd/pmd/issues/2716): \[java] CompareObjectsWithEqualsRule: False positive with Enums
* [#3089](https://github.com/pmd/pmd/issues/3089): \[java] CloseResource rule throws exception on spaces in property types
* [#3133](https://github.com/pmd/pmd/issues/3133): \[java] InvalidLogMessageFormat FP with StringFormattedMessage and ParameterizedMessage
* plsql
* [#3106](https://github.com/pmd/pmd/issues/3106): \[plsql] ParseException while parsing EXECUTE IMMEDIATE 'drop database link ' \|\| linkname;
### API Changes
#### Experimental APIs
* The experimental class `ASTTypeTestPattern` has been renamed to <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/ast/ASTTypePattern.html#"><code>ASTTypePattern</code></a>
in order to align the naming to the JLS.
* The experimental class `ASTRecordConstructorDeclaration` has been renamed to <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/ast/ASTCompactConstructorDeclaration.html#"><code>ASTCompactConstructorDeclaration</code></a>
in order to align the naming to the JLS.
* The AST types and APIs around Pattern Matching and Records are not experimental anymore:
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/ast/ASTVariableDeclaratorId.html#isPatternBinding()"><code>ASTVariableDeclaratorId#isPatternBinding</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/ast/ASTPattern.html#"><code>ASTPattern</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/ast/ASTTypePattern.html#"><code>ASTTypePattern</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/ast/ASTRecordDeclaration.html#"><code>ASTRecordDeclaration</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/ast/ASTRecordComponentList.html#"><code>ASTRecordComponentList</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/ast/ASTRecordComponent.html#"><code>ASTRecordComponent</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/ast/ASTRecordBody.html#"><code>ASTRecordBody</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/ast/ASTCompactConstructorDeclaration.html#"><code>ASTCompactConstructorDeclaration</code></a>
#### 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 protected or public member of the Java rule <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.32.0/net/sourceforge/pmd/lang/java/rule/bestpractices/AvoidUsingHardCodedIPRule.html#"><code>AvoidUsingHardCodedIPRule</code></a>
are deprecated and considered to be internal API. They will be removed with PMD 7.
### External Contributions
* [#3098](https://github.com/pmd/pmd/pull/3098): \[apex] ApexDoc optionally report private and protected - [Jonathan Wiesel](https://github.com/jonathanwiesel)
* [#3107](https://github.com/pmd/pmd/pull/3107): \[plsql] Fix ParseException for EXECUTE IMMEDIATE str1\|\|str2; - [hvbtup](https://github.com/hvbtup)
* [#3125](https://github.com/pmd/pmd/pull/3125): \[doc] Fix sample code indentation in documentation - [Artur Dryomov](https://github.com/arturdryomov)
### Stats
* 43 commits
* 21 closed tickets & PRs
* Days since last release: 27
## 30-January-2021 - 6.31.0
The PMD team is pleased to announce PMD 6.31.0.
@@ -74,7 +74,7 @@ public final class ASTLiteralExpression extends AbstractApexNode<LiteralExpressi
exprField.setAccessible(true);
Optional<NameValueParameter> parameter = parent.node.getParameters().stream().filter(p -> {
try {
return exprField.get(p) == this.node;
return this.node.equals(exprField.get(p));
} catch (IllegalArgumentException | IllegalAccessException e) {
return false;
}
@@ -315,7 +315,7 @@ final class ApexTreeBuilder extends AstVisitor<AdditionalPassScope> {
}
private void buildFormalComment(AstNode node) {
if (parents.peek() == node) {
if (node.equals(parents.peek())) {
assignApexDocTokenToNode(node, nodes.peek());
}
}
@@ -413,7 +413,7 @@ final class ApexTreeBuilder extends AstVisitor<AdditionalPassScope> {
}
private boolean visit(AstNode node) {
if (parents.peek() == node) {
if (node.equals(parents.peek())) {
return true;
} else {
build(node);
@@ -134,7 +134,7 @@ public class ApexOpenRedirectRule extends AbstractApexRule {
return;
}
if (node.getType().equalsIgnoreCase(PAGEREFERENCE)) {
if (PAGEREFERENCE.equalsIgnoreCase(node.getType())) {
getObjectValue(node, data);
}
}
@@ -216,7 +216,7 @@ public class RuleSet implements ChecksumAware {
// check for duplicates - adding more than one rule with the same name will
// be problematic - see #RuleSet.getRuleByName(String)
for (Rule rule : rules) {
if (rule.getName().equals(newRule.getName()) && rule.getLanguage() == newRule.getLanguage()) {
if (rule.getName().equals(newRule.getName()) && rule.getLanguage().equals(newRule.getLanguage())) {
LOG.warning("The rule with name " + newRule.getName() + " is duplicated. "
+ "Future versions of PMD will reject to load such rulesets.");
break;
@@ -234,7 +234,7 @@ public class RuleSet implements ChecksumAware {
*/
Rule getExistingRule(final Rule rule) {
for (Rule r : rules) {
if (r.getName().equals(rule.getName()) && r.getLanguage() == rule.getLanguage()) {
if (r.getName().equals(rule.getName()) && r.getLanguage().equals(rule.getLanguage())) {
return r;
}
}
@@ -269,7 +269,7 @@ public class RuleSet implements ChecksumAware {
for (final Iterator<Rule> it = rules.iterator(); it.hasNext();) {
final Rule r = it.next();
if (r.getName().equals(rule.getName()) && r.getLanguage() == rule.getLanguage()) {
if (r.getName().equals(rule.getName()) && r.getLanguage().equals(rule.getLanguage())) {
it.remove();
}
}
@@ -176,9 +176,9 @@ public class CPDTask extends Task {
}
private CPDRenderer createRenderer() {
if (format.equals(TEXT_FORMAT)) {
if (TEXT_FORMAT.equals(format)) {
return new SimpleRenderer();
} else if (format.equals(CSV_FORMAT)) {
} else if (CSV_FORMAT.equals(format)) {
return new CSVRenderer();
}
return new XMLRenderer();
@@ -94,7 +94,7 @@ public class MatchAlgorithm {
Map<TokenEntry, Object> markGroups = new HashMap<>(tokens.size());
for (int i = code.size() - 1; i >= 0; i--) {
TokenEntry token = code.get(i);
if (token != TokenEntry.EOF) {
if (!TokenEntry.EOF.equals(token)) {
int last = tokenAt(min, token).getIdentifier();
lastHash = MOD * lastHash + token.getIdentifier() - lastMod * last;
token.setHashCode(lastHash);
@@ -120,7 +120,7 @@ public class MatchAlgorithm {
for (int end = Math.max(0, i - min + 1); i > end; i--) {
token = code.get(i - 1);
lastHash = MOD * lastHash + token.getIdentifier();
if (token == TokenEntry.EOF) {
if (TokenEntry.EOF.equals(token)) {
break;
}
}
@@ -98,6 +98,8 @@ public class MatchCollector {
}
private boolean matchEnded(TokenEntry token1, TokenEntry token2) {
return token1.getIdentifier() != token2.getIdentifier() || token1 == TokenEntry.EOF || token2 == TokenEntry.EOF;
return token1.getIdentifier() != token2.getIdentifier()
|| TokenEntry.EOF.equals(token1)
|| TokenEntry.EOF.equals(token2);
}
}
@@ -155,8 +155,17 @@ public class TokenEntry implements Comparable<TokenEntry> {
this.hashCode = hashCode;
}
@SuppressWarnings("PMD.CompareObjectsWithEquals")
@Override
public boolean equals(Object o) {
// make sure to recognize EOF regardless of hashCode (hashCode is irrelevant for EOF)
if (this == EOF) {
return o == EOF;
}
if (o == EOF) {
return this == EOF;
}
// any token except EOF
if (!(o instanceof TokenEntry)) {
return false;
}
@@ -171,7 +180,7 @@ public class TokenEntry implements Comparable<TokenEntry> {
@Override
public String toString() {
if (this == EOF) {
if (EOF.equals(this)) {
return "EOF";
}
for (Map.Entry<String, Integer> e : TOKENS.get().entrySet()) {
@@ -34,7 +34,7 @@ public class Tokens {
public int getLineCount(TokenEntry mark, Match match) {
TokenEntry endTok = getEndToken(mark, match);
if (endTok == TokenEntry.EOF) {
if (TokenEntry.EOF.equals(endTok)) {
endTok = get(mark.getIndex() + match.getTokenCount() - 2);
}
return endTok.getBeginLine() - mark.getBeginLine() + 1;
@@ -9,6 +9,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -156,27 +157,28 @@ public abstract class BaseLanguageModule implements Language {
return "LanguageModule:" + name + '(' + this.getClass().getSimpleName() + ')';
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof BaseLanguageModule)) {
return false;
}
BaseLanguageModule other = (BaseLanguageModule) obj;
return name.equals(other.name);
}
@Override
public int compareTo(Language o) {
return getName().compareTo(o.getName());
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
BaseLanguageModule other = (BaseLanguageModule) obj;
return Objects.equals(name, other.name);
}
}
@@ -182,7 +182,7 @@ public final class JjtreeBuilder<N extends AbstractJjtreeNode<N, ?>> {
private void closeImpl(N n, JavaccToken lastToken) {
if (lastToken.getNext() == n.getFirstToken()) {
if (lastToken.getNext() == n.getFirstToken()) { // NOPMD CompareObjectsWithEquals
// this means, that the node has zero length.
// create an implicit token to represent this case.
JavaccToken implicit = JavaccToken.implicitBefore(lastToken.getNext());
@@ -119,7 +119,7 @@ public final class StreamImpl {
if (length == 0) {
return empty();
} else if (filtermap == Filtermap.NODE_IDENTITY) {
} else if (filtermap == Filtermap.NODE_IDENTITY) { // NOPMD CompareObjectsWithEquals
@SuppressWarnings("unchecked")
NodeStream<T> res = length == 1 ? (NodeStream<T>) singleton(parent.getChild(from))
: (NodeStream<T>) new ChildrenStream(parent, from, length);
@@ -144,7 +144,7 @@ public final class StreamImpl {
return empty();
}
if (target == Filtermap.NODE_IDENTITY) {
if (target == Filtermap.NODE_IDENTITY) { // NOPMD CompareObjectsWithEquals
return (NodeStream<T>) new AncestorOrSelfStream(node);
}
@@ -144,7 +144,7 @@ class LatticeRelation<K, @NonNull V, C> {
addSucc(preds, next, val);
}
if (preds.removeLast() != n) {
if (preds.removeLast() != n) { // NOPMD CompareObjectsWithEquals
throw new IllegalStateException("Unbalanced stack push/pop");
}
}
@@ -75,7 +75,7 @@ class AstDocumentNode extends BaseNodeInfo implements AstNodeOwner {
@Override
public int compareOrder(NodeInfo other) {
return other == this ? 0 : -1;
return other == this ? 0 : -1; // NOPMD CompareObjectsWithEquals - only a single root per tree
}
@Override
@@ -43,21 +43,21 @@ public final class ValueParserConstants {
static final ValueParser<String> STRING_PARSER = new ValueParser<String>() {
@Override
public String valueOf(String value) {
return value;
return StringUtils.trim(value);
}
};
/** Extracts integers. */
static final ValueParser<Integer> INTEGER_PARSER = new ValueParser<Integer>() {
@Override
public Integer valueOf(String value) {
return Integer.valueOf(value);
return Integer.valueOf(StringUtils.trim(value));
}
};
/** Extracts booleans. */
static final ValueParser<Boolean> BOOLEAN_PARSER = new ValueParser<Boolean>() {
@Override
public Boolean valueOf(String value) {
return Boolean.valueOf(value);
return Boolean.valueOf(StringUtils.trim(value));
}
};
/** Extracts floats. */
@@ -71,7 +71,7 @@ public final class ValueParserConstants {
static final ValueParser<Long> LONG_PARSER = new ValueParser<Long>() {
@Override
public Long valueOf(String value) {
return Long.valueOf(value);
return Long.valueOf(StringUtils.trim(value));
}
};
/** Extracts doubles. */
@@ -85,7 +85,7 @@ public final class ValueParserConstants {
static final ValueParser<File> FILE_PARSER = new ValueParser<File>() {
@Override
public File valueOf(String value) throws IllegalArgumentException {
return new File(value);
return new File(StringUtils.trim(value));
}
};
@@ -112,10 +112,11 @@ public final class ValueParserConstants {
return new ValueParser<T>() {
@Override
public T valueOf(String value) throws IllegalArgumentException {
if (!mappings.containsKey(value)) {
throw new IllegalArgumentException("Value was not in the set " + mappings.keySet());
String trimmedValue = StringUtils.trim(value);
if (!mappings.containsKey(trimmedValue)) {
throw new IllegalArgumentException("Value " + value + " was not in the set " + mappings.keySet());
}
return mappings.get(value);
return mappings.get(trimmedValue);
}
};
}
@@ -325,7 +325,7 @@ public final class CollectionUtil {
AssertionUtil.requireParamNotNull("values", to);
Validate.isTrue(from.size() == to.size(), "Mismatched list sizes %s to %s", from, to);
if (from.isEmpty()) {
if (from.isEmpty()) { //NOPMD: we really want to compare references here
return emptyMap();
}
@@ -95,22 +95,19 @@ public class AntLogHandler extends Handler {
// Map the log levels from java.util.logging to Ant
int antLevel;
Level level = logRecord.getLevel();
if (level == Level.FINEST) {
antLevel = Project.MSG_DEBUG; // Shown when -debug is supplied to
// Ant
} else if (level == Level.FINE || level == Level.FINER || level == Level.CONFIG) {
antLevel = Project.MSG_VERBOSE; // Shown when -verbose is supplied
// to Ant
} else if (level == Level.INFO) {
if (Level.FINEST.equals(level)) {
antLevel = Project.MSG_DEBUG; // Shown when -debug is supplied to Ant
} else if (Level.FINE.equals(level) || Level.FINER.equals(level) || Level.CONFIG.equals(level)) {
antLevel = Project.MSG_VERBOSE; // Shown when -verbose is supplied to Ant
} else if (Level.INFO.equals(level)) {
antLevel = Project.MSG_INFO; // Always shown
} else if (level == Level.WARNING) {
} else if (Level.WARNING.equals(level)) {
antLevel = Project.MSG_WARN; // Always shown
} else if (level == Level.SEVERE) {
} else if (Level.SEVERE.equals(level)) {
antLevel = Project.MSG_ERR; // Always shown
} else {
throw new IllegalStateException("Unknown logging level"); // shouldn't
// get ALL
// or NONE
// shouldn't get ALL or NONE
throw new IllegalStateException("Unknown logging level");
}
project.log(FORMATTER.format(logRecord), antLevel);
@@ -159,6 +159,7 @@ public class PropertyDescriptorTest {
assertEquals("hello", descriptor.description());
assertEquals(Integer.valueOf(1), descriptor.defaultValue());
assertEquals(Integer.valueOf(5), descriptor.valueFrom("5"));
assertEquals(Integer.valueOf(5), descriptor.valueFrom(" 5 "));
PropertyDescriptor<List<Integer>> listDescriptor = PropertyFactory.intListProperty("intListProp")
.desc("hello")
@@ -168,6 +169,7 @@ public class PropertyDescriptorTest {
assertEquals("hello", listDescriptor.description());
assertEquals(Arrays.asList(1, 2), listDescriptor.defaultValue());
assertEquals(Arrays.asList(5, 7), listDescriptor.valueFrom("5,7"));
assertEquals(Arrays.asList(5, 7), listDescriptor.valueFrom(" 5 , 7 "));
}
@Test
@@ -191,6 +193,7 @@ public class PropertyDescriptorTest {
assertEquals("hello", descriptor.description());
assertEquals(Double.valueOf(1.0), descriptor.defaultValue());
assertEquals(Double.valueOf(2.0), descriptor.valueFrom("2.0"));
assertEquals(Double.valueOf(2.0), descriptor.valueFrom(" 2.0 "));
PropertyDescriptor<List<Double>> listDescriptor = PropertyFactory.doubleListProperty("doubleListProp")
.desc("hello")
@@ -200,6 +203,7 @@ public class PropertyDescriptorTest {
assertEquals("hello", listDescriptor.description());
assertEquals(Arrays.asList(1.0, 2.0), listDescriptor.defaultValue());
assertEquals(Arrays.asList(2.0, 3.0), listDescriptor.valueFrom("2.0,3.0"));
assertEquals(Arrays.asList(2.0, 3.0), listDescriptor.valueFrom(" 2.0 , 3.0 "));
}
@Test
@@ -223,6 +227,7 @@ public class PropertyDescriptorTest {
assertEquals("hello", descriptor.description());
assertEquals("default value", descriptor.defaultValue());
assertEquals("foo", descriptor.valueFrom("foo"));
assertEquals("foo", descriptor.valueFrom(" foo "));
PropertyDescriptor<List<String>> listDescriptor = PropertyFactory.stringListProperty("stringListProp")
.desc("hello")
@@ -232,6 +237,7 @@ public class PropertyDescriptorTest {
assertEquals("hello", listDescriptor.description());
assertEquals(Arrays.asList("v1", "v2"), listDescriptor.defaultValue());
assertEquals(Arrays.asList("foo", "bar"), listDescriptor.valueFrom("foo|bar"));
assertEquals(Arrays.asList("foo", "bar"), listDescriptor.valueFrom(" foo | bar "));
}
private enum SampleEnum { A, B, C }
+13 -3
View File
@@ -1,4 +1,10 @@
/**
* Fix #3117 - infinite loop when parsing invalid code nested in lambdas
* Andreas Dangel 03/2021
*====================================================================
* Fix #3145 - parse exception with local records
* Clément Fournier 03/2021
*====================================================================
* Remove support for Java 14 preview language features
* JEP 397: Sealed Classes (Second Preview) for Java16 Preview
* JEP 395: Records for Java16
@@ -232,6 +238,11 @@ options {
VISITOR = true;
NODE_PACKAGE="net.sourceforge.pmd.lang.java.ast";
// disable the calculation of expected tokens when a parse error occurs
// depending on the possible allowed next tokens, this
// could be expensive (see https://github.com/pmd/pmd/issues/3117)
//ERROR_REPORTING = false;
//DEBUG_PARSER = true;
//DEBUG_LOOKAHEAD = true;
//DEBUG_TOKEN_MANAGER = true;
@@ -312,7 +323,7 @@ class JavaParserImpl {
}
private boolean isRecordStart() {
return isRecordTypeSupported() && isKeyword("record");
return isRecordTypeSupported() && isKeyword("record") && isToken(2, IDENTIFIER);
}
private boolean isEnumStart() {
@@ -381,8 +392,7 @@ class JavaParserImpl {
next.kind == INTERFACE
|| next.kind == AT && isToken(2, INTERFACE)
|| next.kind == IDENTIFIER && next.getImage().equals("enum")
||
next.kind == IDENTIFIER && next.image.equals("record")
|| next.kind == IDENTIFIER && next.getImage().equals("record") && isToken(2, IDENTIFIER)
);
}
@@ -156,7 +156,7 @@ final class LazyTypeResolver extends JavaVisitorBase<Void, @NonNull JTypeMirror>
ASTLambdaExpression lambda = (ASTLambdaExpression) node.getNthParent(3);
// force resolution of the enclosing lambda
JMethodSig mirror = lambda.getFunctionalMethod();
if (mirror == null || mirror == ts.UNRESOLVED_METHOD) {
if (isUnresolved(mirror)) {
return ts.UNKNOWN;
}
return mirror.getFormalParameters().get(param.getIndexInParent());
@@ -314,7 +314,11 @@ final class LazyTypeResolver extends JavaVisitorBase<Void, @NonNull JTypeMirror>
}
private boolean isUnresolved(JTypeMirror t) {
return t == ts.UNKNOWN;
return t == ts.UNKNOWN; // NOPMD CompareObjectsWithEquals
}
private boolean isUnresolved(JMethodSig m) {
return m == null || m == ts.UNRESOLVED_METHOD; // NOPMD CompareObjectsWithEquals
}
@Override
@@ -470,7 +474,7 @@ final class LazyTypeResolver extends JavaVisitorBase<Void, @NonNull JTypeMirror>
lambda.getTypeMirror();
JMethodSig m = lambda.getFunctionalMethod(); // this forces resolution of the lambda
if (m != getTypeSystem().UNRESOLVED_METHOD) {
if (!isUnresolved(m)) {
return m.getFormalParameters().get(node.getIndexInParent());
}
return ts.UNKNOWN;
@@ -479,7 +483,7 @@ final class LazyTypeResolver extends JavaVisitorBase<Void, @NonNull JTypeMirror>
@Override
public JTypeMirror visit(ASTFieldAccess node, Void data) {
JTypeMirror qualifierT = capture(node.getQualifier().getTypeMirror());
if (qualifierT == ts.UNKNOWN) {
if (isUnresolved(qualifierT)) {
return polyResolution.getContextTypeForStandaloneFallback(node);
}
@@ -505,7 +509,7 @@ final class LazyTypeResolver extends JavaVisitorBase<Void, @NonNull JTypeMirror>
JTypeMirror arrType = node.getQualifier().getTypeMirror();
if (arrType instanceof JArrayType) {
compType = ((JArrayType) arrType).getComponentType();
} else if (arrType == ts.UNKNOWN) {
} else if (isUnresolved(arrType)) {
compType = polyResolution.getContextTypeForStandaloneFallback(node);
} else {
compType = ts.ERROR;
@@ -70,17 +70,22 @@ public class ImportWrapper {
try {
Set<String> names = new HashSet<>();
// consider static fields, public and non-public
for (Field f : type.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())) {
names.add(f.getName());
while (type != null) {
// consider static fields, public and non-public
for (Field f : type.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())) {
names.add(f.getName());
}
}
}
// and methods, too
for (Method m : type.getDeclaredMethods()) {
if (Modifier.isStatic(m.getModifiers())) {
names.add(m.getName());
// and methods, too
for (Method m : type.getDeclaredMethods()) {
if (Modifier.isStatic(m.getModifiers())) {
names.add(m.getName());
}
}
// consider statics of super classes as well
type = type.getSuperclass();
}
return names;
} catch (LinkageError e) {
@@ -87,9 +87,9 @@ public final class JavaAstProcessor {
}
static TypeInferenceLogger defaultTypeInfLogger() {
if (INFERENCE_LOG_LEVEL == Level.FINEST) {
if (Level.FINEST.equals(INFERENCE_LOG_LEVEL)) {
return new VerboseLogger(System.err);
} else if (INFERENCE_LOG_LEVEL == Level.FINE) {
} else if (Level.FINE.equals(INFERENCE_LOG_LEVEL)) {
return new SimpleLogger(System.err);
} else {
return TypeInferenceLogger.noop();
Loaded 30 of 68 files, more files were not shown because too many files have changed in this diff. Show more