Merge branch '7.0.x' into java-pattern-binding-scopes
This commit is contained in:
17 files changed
+314
-212
No files matched your search
@@ -129,7 +129,7 @@
|
||||
<rule ref="category/java/design.xml/ClassWithOnlyPrivateConstructorsShouldBeFinal"/>
|
||||
<rule ref="category/java/design.xml/CognitiveComplexity" />
|
||||
<rule ref="category/java/design.xml/CollapsibleIfStatements"/>
|
||||
<!-- <rule ref="category/java/design.xml/CouplingBetweenObjects"/> -->
|
||||
<rule ref="category/java/design.xml/CouplingBetweenObjects"/>
|
||||
<rule ref="category/java/design.xml/CyclomaticComplexity"/>
|
||||
<rule ref="category/java/design.xml/DataClass"/>
|
||||
<rule ref="category/java/design.xml/DoNotExtendJavaLangError"/>
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ repository: pmd/pmd
|
||||
|
||||
pmd:
|
||||
version: 7.0.0-SNAPSHOT
|
||||
previous_version: 6.41.0
|
||||
previous_version: 6.42.0
|
||||
date: ??-?????-2022
|
||||
release_type: major
|
||||
|
||||
|
||||
@@ -246,6 +246,10 @@ 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.42.0
|
||||
|
||||
No changes.
|
||||
|
||||
#### 6.41.0
|
||||
|
||||
##### Command Line Interface
|
||||
|
||||
@@ -19,70 +19,11 @@ This is a {{ site.pmd.release_type }} release.
|
||||
|
||||
### New and noteworthy
|
||||
|
||||
#### Javascript: Rhino updated to latest version 1.7.14
|
||||
|
||||
[Rhino](https://github.com/mozilla/rhino), the implementation of JavaScript we use
|
||||
for parsing JavaScript code, has been updated to the latest version 1.7.14.
|
||||
Now language features like template strings can be parsed. However Rhino does
|
||||
not support all features of the latest EcmaScript standard.
|
||||
|
||||
#### New rules
|
||||
|
||||
* The new Java rule {% rule "java/codestyle/FinalParameterInAbstractMethod" %} detects parameters that are
|
||||
declared as final in interfaces or abstract methods. Declaring the parameters as final is useless
|
||||
because the implementation may choose to not respect it.
|
||||
|
||||
```xml
|
||||
<rule ref="category/java/codestyle.xml/FinalParameterInAbstractMethod" />
|
||||
```
|
||||
|
||||
The rule is part of the quickstart.xml ruleset.
|
||||
|
||||
#### Modified rules
|
||||
|
||||
* The Apex rule {% rule "apex/documentation/ApexDoc" %} has a new property `reportProperty`.
|
||||
If set to `false` (default is `true` if unspecified) doesn't report missing ApexDoc comments on properties.
|
||||
It allows you to enforce ApexDoc comments for classes and methods without requiring them for properties.
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* java
|
||||
* [#3698](https://github.com/pmd/pmd/issues/3698): \[java] Error resolving Symbol Table
|
||||
* java-bestpractices
|
||||
* [#3209](https://github.com/pmd/pmd/issues/3209): \[java] UnusedPrivateMethod false positive with static method and cast expression
|
||||
* [#3468](https://github.com/pmd/pmd/issues/3468): \[java] UnusedPrivateMethod false positive when outer class calls private static method on inner class
|
||||
* java-design
|
||||
* [#3679](https://github.com/pmd/pmd/issues/3679): \[java] Make FinalFieldCouldBeStatic detect constant variable
|
||||
* java-errorprone
|
||||
* [#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
|
||||
* [#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
|
||||
* [#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
|
||||
* [#3703](https://github.com/pmd/pmd/issues/3703): \[javascript] Error - no Node adapter class registered for XmlPropRef
|
||||
|
||||
### API Changes
|
||||
|
||||
### External Contributions
|
||||
|
||||
* [#3631](https://github.com/pmd/pmd/pull/3631): \[java] Fixed False positive for UselessStringValueOf when there is no initial String to append to - [John Armgardt](https://github.com/johnra2)
|
||||
* [#3683](https://github.com/pmd/pmd/pull/3683): \[java] Fixed 3468 UnusedPrivateMethod false positive when outer class calls private static method on inner class - [John Armgardt](https://github.com/johnra2)
|
||||
* [#3688](https://github.com/pmd/pmd/pull/3688): \[java] Bump log4j to 2.16.0 - [Sergey Nuyanzin](https://github.com/snuyanzin)
|
||||
* [#3693](https://github.com/pmd/pmd/pull/3693): \[apex] ApexDoc: Add reportProperty property - [Steve Babula](https://github.com/babula)
|
||||
* [#3704](https://github.com/pmd/pmd/pull/3704): \[java] Fix for #3686 - Fix ReturnEmptyCollectionRatherThanNull - [Oleksii Dykov](https://github.com/dykov)
|
||||
* [#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)
|
||||
* [#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 #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)
|
||||
* [#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)
|
||||
* [#3747](https://github.com/pmd/pmd/pull/3747): \[visualforce] Updated DataType.java - [Vyom Yadav](https://github.com/Vyom-Yadav)
|
||||
|
||||
{% endtocmaker %}
|
||||
|
||||
@@ -5,6 +5,99 @@ permalink: pmd_release_notes_old.html
|
||||
|
||||
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
|
||||
|
||||
## 29-January-2022 - 6.42.0
|
||||
|
||||
The PMD team is pleased to announce PMD 6.42.0.
|
||||
|
||||
This is a minor release.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
* [New and noteworthy](#new-and-noteworthy)
|
||||
* [Javascript: Rhino updated to latest version 1.7.14](#javascript:-rhino-updated-to-latest-version-1.7.14)
|
||||
* [New rules](#new-rules)
|
||||
* [Modified rules](#modified-rules)
|
||||
* [Fixed Issues](#fixed-issues)
|
||||
* [API Changes](#api-changes)
|
||||
* [External Contributions](#external-contributions)
|
||||
* [Stats](#stats)
|
||||
|
||||
### New and noteworthy
|
||||
|
||||
#### Javascript: Rhino updated to latest version 1.7.14
|
||||
|
||||
[Rhino](https://github.com/mozilla/rhino), the implementation of JavaScript we use
|
||||
for parsing JavaScript code, has been updated to the latest version 1.7.14.
|
||||
Now language features like template strings can be parsed. However Rhino does
|
||||
not support all features of the latest EcmaScript standard.
|
||||
|
||||
#### New rules
|
||||
|
||||
* The new Java rule [`FinalParameterInAbstractMethod`](https://pmd.github.io/pmd-6.42.0/pmd_rules_java_codestyle.html#finalparameterinabstractmethod) detects parameters that are
|
||||
declared as final in interfaces or abstract methods. Declaring the parameters as final is useless
|
||||
because the implementation may choose to not respect it.
|
||||
|
||||
```xml
|
||||
<rule ref="category/java/codestyle.xml/FinalParameterInAbstractMethod" />
|
||||
```
|
||||
|
||||
The rule is part of the quickstart.xml ruleset.
|
||||
|
||||
#### Modified rules
|
||||
|
||||
* The Apex rule [`ApexDoc`](https://pmd.github.io/pmd-6.42.0/pmd_rules_apex_documentation.html#apexdoc) has a new property `reportProperty`.
|
||||
If set to `false` (default is `true` if unspecified) doesn't report missing ApexDoc comments on properties.
|
||||
It allows you to enforce ApexDoc comments for classes and methods without requiring them for properties.
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* core
|
||||
* [#3328](https://github.com/pmd/pmd/issues/3328): \[core] designer.bat errors when JAVAFX_HOME contains spaces
|
||||
* java
|
||||
* [#3698](https://github.com/pmd/pmd/issues/3698): \[java] Error resolving Symbol Table
|
||||
* java-bestpractices
|
||||
* [#3209](https://github.com/pmd/pmd/issues/3209): \[java] UnusedPrivateMethod false positive with static method and cast expression
|
||||
* [#3468](https://github.com/pmd/pmd/issues/3468): \[java] UnusedPrivateMethod false positive when outer class calls private static method on inner class
|
||||
* java-design
|
||||
* [#3679](https://github.com/pmd/pmd/issues/3679): \[java] Make FinalFieldCouldBeStatic detect constant variable
|
||||
* java-errorprone
|
||||
* [#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
|
||||
* [#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
|
||||
* [#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
|
||||
* [#3703](https://github.com/pmd/pmd/issues/3703): \[javascript] Error - no Node adapter class registered for XmlPropRef
|
||||
|
||||
### API Changes
|
||||
|
||||
No changes.
|
||||
|
||||
### External Contributions
|
||||
|
||||
* [#3631](https://github.com/pmd/pmd/pull/3631): \[java] Fixed False positive for UselessStringValueOf when there is no initial String to append to - [John Armgardt](https://github.com/johnra2)
|
||||
* [#3683](https://github.com/pmd/pmd/pull/3683): \[java] Fixed 3468 UnusedPrivateMethod false positive when outer class calls private static method on inner class - [John Armgardt](https://github.com/johnra2)
|
||||
* [#3688](https://github.com/pmd/pmd/pull/3688): \[java] Bump log4j to 2.16.0 - [Sergey Nuyanzin](https://github.com/snuyanzin)
|
||||
* [#3693](https://github.com/pmd/pmd/pull/3693): \[apex] ApexDoc: Add reportProperty property - [Steve Babula](https://github.com/babula)
|
||||
* [#3704](https://github.com/pmd/pmd/pull/3704): \[java] Fix for #3686 - Fix ReturnEmptyCollectionRatherThanNull - [Oleksii Dykov](https://github.com/dykov)
|
||||
* [#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)
|
||||
* [#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 #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)
|
||||
* [#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)
|
||||
* [#3747](https://github.com/pmd/pmd/pull/3747): \[visualforce] Updated DataType.java - [Vyom Yadav](https://github.com/Vyom-Yadav)
|
||||
|
||||
### Stats
|
||||
* 88 commits
|
||||
* 35 closed tickets & PRs
|
||||
* Days since last release: 62
|
||||
|
||||
## 27-November-2021 - 6.41.0
|
||||
|
||||
The PMD team is pleased to announce PMD 6.41.0.
|
||||
|
||||
Generated
+34
-26
@@ -9,9 +9,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz",
|
||||
"integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==",
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz",
|
||||
"integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
@@ -84,9 +84,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz",
|
||||
"integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==",
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
|
||||
"integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
@@ -306,13 +306,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/json-fixer": {
|
||||
"version": "1.6.12",
|
||||
"resolved": "https://registry.npmjs.org/json-fixer/-/json-fixer-1.6.12.tgz",
|
||||
"integrity": "sha512-BGO9HExf0ZUVYvuWsps71Re513Ss0il1Wp7wYWkir2NthzincvNJEUu82KagEfAkGdjOMsypj3t2JB7drBKWnA==",
|
||||
"version": "1.6.13",
|
||||
"resolved": "https://registry.npmjs.org/json-fixer/-/json-fixer-1.6.13.tgz",
|
||||
"integrity": "sha512-DKQ71M+0uwAG3QsUkeVgh6XREw/OkpnTfHfM+sdmxRjHvYZ8PlcMVF4ibsHQ1ckR63NROs68qUr1I0u6yPVePQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.14.6",
|
||||
"chalk": "^4.1.1",
|
||||
"chalk": "^4.1.2",
|
||||
"pegjs": "^0.10.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -353,15 +353,23 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.6",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
|
||||
"integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/onetime": {
|
||||
@@ -690,9 +698,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.16.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz",
|
||||
"integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==",
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz",
|
||||
"integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
@@ -741,9 +749,9 @@
|
||||
}
|
||||
},
|
||||
"async": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz",
|
||||
"integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==",
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
|
||||
"integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
|
||||
"dev": true
|
||||
},
|
||||
"camelcase": {
|
||||
@@ -912,13 +920,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"json-fixer": {
|
||||
"version": "1.6.12",
|
||||
"resolved": "https://registry.npmjs.org/json-fixer/-/json-fixer-1.6.12.tgz",
|
||||
"integrity": "sha512-BGO9HExf0ZUVYvuWsps71Re513Ss0il1Wp7wYWkir2NthzincvNJEUu82KagEfAkGdjOMsypj3t2JB7drBKWnA==",
|
||||
"version": "1.6.13",
|
||||
"resolved": "https://registry.npmjs.org/json-fixer/-/json-fixer-1.6.13.tgz",
|
||||
"integrity": "sha512-DKQ71M+0uwAG3QsUkeVgh6XREw/OkpnTfHfM+sdmxRjHvYZ8PlcMVF4ibsHQ1ckR63NROs68qUr1I0u6yPVePQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.14.6",
|
||||
"chalk": "^4.1.1",
|
||||
"chalk": "^4.1.2",
|
||||
"pegjs": "^0.10.0"
|
||||
}
|
||||
},
|
||||
@@ -950,9 +958,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.6",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
|
||||
"integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@echo off
|
||||
set TOPDIR=%~dp0..
|
||||
set TOPDIR="%~dp0.."
|
||||
set OPTS=
|
||||
set MAIN_CLASS=net.sourceforge.pmd.util.treeexport.TreeExportCli
|
||||
|
||||
java %PMD_JAVA_OPTS% -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %*
|
||||
java %PMD_JAVA_OPTS% -classpath %TOPDIR%\lib\* %OPTS% %MAIN_CLASS% %*
|
||||
@@ -1,6 +1,6 @@
|
||||
@echo off
|
||||
set TOPDIR=%~dp0..
|
||||
set TOPDIR="%~dp0.."
|
||||
set OPTS=
|
||||
set MAIN_CLASS=net.sourceforge.pmd.cpd.CPD
|
||||
|
||||
java %PMD_JAVA_OPTS% -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %*
|
||||
java %PMD_JAVA_OPTS% -classpath %TOPDIR%\lib\* %OPTS% %MAIN_CLASS% %*
|
||||
@@ -1,6 +1,6 @@
|
||||
@echo off
|
||||
set TOPDIR=%~dp0..
|
||||
set TOPDIR="%~dp0.."
|
||||
set OPTS=
|
||||
set MAIN_CLASS=net.sourceforge.pmd.cpd.GUI
|
||||
|
||||
java %PMD_JAVA_OPTS% -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %*
|
||||
java %PMD_JAVA_OPTS% -classpath %TOPDIR%\lib\* %OPTS% %MAIN_CLASS% %*
|
||||
@@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
set TOPDIR=%~dp0..
|
||||
set TOPDIR="%~dp0.."
|
||||
set OPTS=
|
||||
set MAIN_CLASS=net.sourceforge.pmd.util.fxdesigner.DesignerStarter
|
||||
|
||||
@@ -42,10 +42,10 @@ if %_needjfxlib% EQU 1 (
|
||||
pause
|
||||
exit
|
||||
)
|
||||
set "classpath=%TOPDIR%\lib\*;%JAVAFX_HOME%\lib\*"
|
||||
set classpath=%TOPDIR%\lib\*;%JAVAFX_HOME%\lib\*
|
||||
) else (
|
||||
set "classpath=%TOPDIR%\lib\*"
|
||||
set classpath=%TOPDIR%\lib\*
|
||||
)
|
||||
|
||||
|
||||
java %PMD_JAVA_OPTS% %jreopts% -classpath "%classpath%" %OPTS% %MAIN_CLASS% %*
|
||||
java %PMD_JAVA_OPTS% %jreopts% -classpath %classpath% %OPTS% %MAIN_CLASS% %*
|
||||
@@ -1,6 +1,6 @@
|
||||
@echo off
|
||||
set TOPDIR=%~dp0..
|
||||
set TOPDIR="%~dp0.."
|
||||
set OPTS=
|
||||
set MAIN_CLASS=net.sourceforge.pmd.PMD
|
||||
|
||||
java %PMD_JAVA_OPTS% -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %*
|
||||
java %PMD_JAVA_OPTS% -classpath %TOPDIR%\lib\* %OPTS% %MAIN_CLASS% %*
|
||||
+3
-2
@@ -9,6 +9,7 @@ import static net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility.V_PRIVATE;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.JModifier;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
|
||||
import net.sourceforge.pmd.lang.java.types.TypeTestUtil;
|
||||
|
||||
@@ -21,7 +22,7 @@ public class ClassWithOnlyPrivateConstructorsShouldBeFinalRule extends AbstractJ
|
||||
@Override
|
||||
public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
|
||||
if (node.isRegularClass()
|
||||
&& !node.isFinal()
|
||||
&& !node.hasModifiers(JModifier.FINAL)
|
||||
&& hasOnlyPrivateCtors(node)
|
||||
&& hasNoSubclasses(node)) {
|
||||
addViolation(data, node);
|
||||
@@ -37,7 +38,7 @@ public class ClassWithOnlyPrivateConstructorsShouldBeFinalRule extends AbstractJ
|
||||
}
|
||||
|
||||
private boolean doesExtend(ASTAnyTypeDeclaration sub, ASTClassOrInterfaceDeclaration superClass) {
|
||||
return sub != superClass && TypeTestUtil.isA(superClass.getTypeMirror(), sub);
|
||||
return sub != superClass && TypeTestUtil.isA(superClass.getTypeMirror().getErasure(), sub);
|
||||
}
|
||||
|
||||
private boolean hasOnlyPrivateCtors(ASTClassOrInterfaceDeclaration node) {
|
||||
|
||||
+50
-91
@@ -7,22 +7,19 @@ package net.sourceforge.pmd.lang.java.rule.design;
|
||||
import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTResultType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTType;
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaNode;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
||||
import net.sourceforge.pmd.lang.java.symboltable.ClassScope;
|
||||
import net.sourceforge.pmd.lang.java.symbols.JAccessibleElementSymbol;
|
||||
import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol;
|
||||
import net.sourceforge.pmd.lang.java.types.JTypeMirror;
|
||||
import net.sourceforge.pmd.properties.PropertyDescriptor;
|
||||
import net.sourceforge.pmd.properties.PropertyFactory;
|
||||
|
||||
@@ -38,13 +35,14 @@ import net.sourceforge.pmd.properties.PropertyFactory;
|
||||
*/
|
||||
public class CouplingBetweenObjectsRule extends AbstractJavaRule {
|
||||
|
||||
private int couplingCount;
|
||||
private Set<String> typesFoundSoFar;
|
||||
|
||||
private static final PropertyDescriptor<Integer> THRESHOLD_DESCRIPTOR
|
||||
= PropertyFactory.intProperty("threshold")
|
||||
.desc("Unique type reporting threshold")
|
||||
.require(positive()).defaultValue(20).build();
|
||||
= PropertyFactory.intProperty("threshold")
|
||||
.desc("Unique type reporting threshold")
|
||||
.require(positive()).defaultValue(20).build();
|
||||
|
||||
private int couplingCount;
|
||||
private boolean inInterface;
|
||||
private final Set<JTypeMirror> typesFoundSoFar = new HashSet<>();
|
||||
|
||||
public CouplingBetweenObjectsRule() {
|
||||
definePropertyDescriptor(THRESHOLD_DESCRIPTOR);
|
||||
@@ -52,104 +50,70 @@ public class CouplingBetweenObjectsRule extends AbstractJavaRule {
|
||||
|
||||
@Override
|
||||
public Object visit(ASTCompilationUnit cu, Object data) {
|
||||
typesFoundSoFar = new HashSet<>();
|
||||
couplingCount = 0;
|
||||
|
||||
Object returnObj = super.visit(cu, data);
|
||||
super.visit(cu, data);
|
||||
|
||||
if (couplingCount > getProperty(THRESHOLD_DESCRIPTOR)) {
|
||||
addViolation(data, cu,
|
||||
"A value of " + couplingCount + " may denote a high amount of coupling within the class");
|
||||
"A value of " + couplingCount + " may denote a high amount of coupling within the class");
|
||||
}
|
||||
|
||||
return returnObj;
|
||||
couplingCount = 0;
|
||||
typesFoundSoFar.clear();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTResultType node, Object data) {
|
||||
for (int x = 0; x < node.getNumChildren(); x++) {
|
||||
Node tNode = node.getChild(x);
|
||||
if (tNode instanceof ASTType) {
|
||||
Node reftypeNode = tNode.getChild(0);
|
||||
if (reftypeNode instanceof ASTReferenceType) {
|
||||
Node classOrIntType = reftypeNode.getChild(0);
|
||||
if (classOrIntType instanceof ASTClassOrInterfaceType) {
|
||||
Node nameNode = classOrIntType;
|
||||
this.checkVariableType(nameNode, nameNode.getImage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
|
||||
boolean prev = inInterface;
|
||||
inInterface = node.isInterface();
|
||||
super.visit(node, data);
|
||||
inInterface = prev;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTMethodDeclaration node, Object data) {
|
||||
ASTType type = node.getResultTypeNode();
|
||||
checkVariableType(type);
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTLocalVariableDeclaration node, Object data) {
|
||||
handleASTTypeChildren(node);
|
||||
ASTType type = node.getTypeNode();
|
||||
checkVariableType(type);
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTFormalParameter node, Object data) {
|
||||
handleASTTypeChildren(node);
|
||||
ASTType type = node.getTypeNode();
|
||||
checkVariableType(type);
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTFieldDeclaration node, Object data) {
|
||||
for (int x = 0; x < node.getNumChildren(); ++x) {
|
||||
Node firstStmt = node.getChild(x);
|
||||
if (firstStmt instanceof ASTType) {
|
||||
ASTType tp = (ASTType) firstStmt;
|
||||
Node nd = tp.getChild(0);
|
||||
checkVariableType(nd, nd.getImage());
|
||||
}
|
||||
}
|
||||
|
||||
ASTType type = node.getTypeNode();
|
||||
checkVariableType(type);
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to handle hierarchy. This is probably too much work and
|
||||
* will go away once I figure out the framework
|
||||
*/
|
||||
private void handleASTTypeChildren(Node node) {
|
||||
for (int x = 0; x < node.getNumChildren(); x++) {
|
||||
Node sNode = node.getChild(x);
|
||||
if (sNode instanceof ASTType) {
|
||||
Node nameNode = sNode.getChild(0);
|
||||
checkVariableType(nameNode, nameNode.getImage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* performs a check on the variable and updates the counter. Counter is
|
||||
* instance for a class and is reset upon new class scan.
|
||||
*
|
||||
* @param variableType
|
||||
* The variable type.
|
||||
* @param typeNode The variable type.
|
||||
*/
|
||||
private void checkVariableType(Node nameNode, String variableType) {
|
||||
List<ASTClassOrInterfaceDeclaration> parentTypes = nameNode.getParentsOfType(ASTClassOrInterfaceDeclaration.class);
|
||||
|
||||
// TODO - move this into the symbol table somehow?
|
||||
if (parentTypes.isEmpty()) {
|
||||
private void checkVariableType(ASTType typeNode) {
|
||||
if (inInterface || typeNode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// skip interfaces
|
||||
if (parentTypes.get(0).isInterface()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the field is of any type other than the class type
|
||||
// increment the count
|
||||
ClassScope clzScope = ((JavaNode) nameNode).getScope().getEnclosingScope(ClassScope.class);
|
||||
if (!clzScope.getClassName().equals(variableType) && !this.filterTypes(variableType)
|
||||
&& !this.typesFoundSoFar.contains(variableType)) {
|
||||
JTypeMirror t = typeNode.getTypeMirror();
|
||||
if (!this.ignoreType(typeNode, t) && this.typesFoundSoFar.add(t)) {
|
||||
couplingCount++;
|
||||
typesFoundSoFar.add(variableType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,24 +122,19 @@ public class CouplingBetweenObjectsRule extends AbstractJavaRule {
|
||||
* This needs more work. I'd like to filter out super types and perhaps
|
||||
* interfaces
|
||||
*
|
||||
* @param variableType
|
||||
* The variable type.
|
||||
* @param t The variable type.
|
||||
*
|
||||
* @return boolean true if variableType is not what we care about
|
||||
*/
|
||||
private boolean filterTypes(String variableType) {
|
||||
return variableType != null && (variableType.startsWith("java.lang.") || "String".equals(variableType)
|
||||
|| filterPrimitivesAndWrappers(variableType));
|
||||
private boolean ignoreType(ASTType typeNode, JTypeMirror t) {
|
||||
if (typeNode.getEnclosingType().getSymbol().equals(t.getSymbol())) {
|
||||
return true;
|
||||
}
|
||||
JTypeDeclSymbol symbol = t.getSymbol();
|
||||
return symbol == null
|
||||
|| symbol.getPackageName().equals(JAccessibleElementSymbol.PRIMITIVE_PACKAGE)
|
||||
|| t.isPrimitive()
|
||||
|| t.isBoxedPrimitive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param variableType
|
||||
* The variable type.
|
||||
* @return boolean true if variableType is a primitive or wrapper
|
||||
*/
|
||||
private boolean filterPrimitivesAndWrappers(String variableType) {
|
||||
return "int".equals(variableType) || "Integer".equals(variableType) || "char".equals(variableType)
|
||||
|| "Character".equals(variableType) || "double".equals(variableType) || "long".equals(variableType)
|
||||
|| "short".equals(variableType) || "float".equals(variableType) || "byte".equals(variableType)
|
||||
|| "boolean".equals(variableType);
|
||||
}
|
||||
}
|
||||
-1
@@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.design;
|
||||
|
||||
import net.sourceforge.pmd.testframework.PmdRuleTst;
|
||||
|
||||
@org.junit.Ignore("Rule has not been updated yet")
|
||||
public class CouplingBetweenObjectsTest extends PmdRuleTst {
|
||||
// no additional unit tests
|
||||
}
|
||||
+109
-16
@@ -7,6 +7,18 @@
|
||||
<test-code>
|
||||
<description>Simple violation</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>1</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
public class Foo {
|
||||
private Foo() { }
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>violation for abstract class</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>1</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
public class Foo {
|
||||
private Foo() { }
|
||||
@@ -35,6 +47,17 @@ public class Foo {
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>abstract class, one public constructor, not required to be final</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public abstract class Foo {
|
||||
private Foo() { }
|
||||
public Foo(String param) { }
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Ok, subclass using the private constructor</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
@@ -74,7 +97,7 @@ public class Foo {
|
||||
public class Foo {
|
||||
private Foo() { }
|
||||
}
|
||||
public class Bar extends Foo {
|
||||
class Bar extends Foo {
|
||||
public Bar() { }
|
||||
}
|
||||
]]></code>
|
||||
@@ -140,27 +163,55 @@ class ClassWithOnlyPrivateConstructorsShouldBeFinal {
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>2</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
public class Main209 {
|
||||
private static class InputBits {
|
||||
private InputBits(int number) { }
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
public class Main209 {
|
||||
private static class InputBits {
|
||||
private InputBits(int number) { }
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description>Private inner class with no ctor</description>
|
||||
<description>Inner class with only private constructor extended within compilation unit (#2536)</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class Main209 {
|
||||
private static class InputBits {
|
||||
private InputBits(int number) { }
|
||||
}
|
||||
public static final class Sub extends InputBits {
|
||||
private Sub() {
|
||||
super(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description>Private inner class with no ctor and no usage</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>2</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
public class Main209 {
|
||||
private static class InputBits {
|
||||
// default ctor is implicitly private
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
public class Main209 {
|
||||
private static class InputBits {
|
||||
// default ctor is implicitly private
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description>Private inner class with no ctor and usage</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class Main209 {
|
||||
private static class InputBits {
|
||||
// default ctor is implicitly private
|
||||
}
|
||||
public static final class Sub extends InputBits {}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code regressionTest="false">
|
||||
<test-code>
|
||||
<description>Private abstract classes with abstract methods should be ignored #3668</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
@@ -168,6 +219,32 @@ public class Outer {
|
||||
private abstract class Base {
|
||||
abstract void run();
|
||||
}
|
||||
public void someMethod() {
|
||||
Base b = new Base() {
|
||||
void run() {}
|
||||
};
|
||||
b.run();
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Private abstract generic classes with abstract methods should be ignored #3668</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
import java.util.Comparator;
|
||||
public class Outer {
|
||||
private abstract class Base<E> {
|
||||
abstract void run();
|
||||
abstract void sort(Comparator<E> comparator);
|
||||
}
|
||||
public void someMethod() {
|
||||
Base b = new Base<Object>() {
|
||||
void run() {}
|
||||
void sort(Comparator<Object> comparator) {}
|
||||
};
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
@@ -185,7 +262,7 @@ public class Outer {
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code regressionTest="false">
|
||||
<test-code>
|
||||
<description>Private abstract classes without abstract methods and subclasses #3668</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>2</expected-linenumbers>
|
||||
@@ -194,6 +271,22 @@ public class Outer {
|
||||
private abstract class Base {
|
||||
private void run() {}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Abstract outer classes should be flagged #3668</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>1</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
public abstract class FooUtils {
|
||||
private FooUtils() {
|
||||
// private constructor can't be called from sub classes,
|
||||
// so this class can't be extended
|
||||
}
|
||||
// note: this "abstract" class does not contain abstract methods
|
||||
// it was only declared as abstract to prevent instantiation
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
+4
@@ -34,6 +34,10 @@ public class Foo {
|
||||
<rule-property name="threshold">2</rule-property>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
public interface Foo {
|
||||
List foo();
|
||||
ArrayList foo();
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
</issueManagement>
|
||||
|
||||
<properties>
|
||||
<project.build.outputTimestamp>2021-11-27T10:21:16Z</project.build.outputTimestamp>
|
||||
<project.build.outputTimestamp>2022-01-29T08:53:37Z</project.build.outputTimestamp>
|
||||
|
||||
<java.version>8</java.version>
|
||||
|
||||
@@ -416,12 +416,12 @@
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd-core</artifactId>
|
||||
<version>6.41.0</version> <!-- pmd.dogfood.version -->
|
||||
<version>6.42.0</version> <!-- pmd.dogfood.version -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd-java</artifactId>
|
||||
<version>6.41.0</version> <!-- pmd.dogfood.version -->
|
||||
<version>6.42.0</version> <!-- pmd.dogfood.version -->
|
||||
</dependency>
|
||||
<!-- This contains the dogfood ruleset -->
|
||||
<dependency>
|
||||
|
||||
Reference in new issue
Block a user