From 9f406333d2b8c060a1c7f422e213a95c05bca51d Mon Sep 17 00:00:00 2001 From: Matias Fraga Date: Fri, 21 Jun 2019 16:13:01 -0300 Subject: [PATCH 001/104] Add antlr documentation --- .../adding_a_new_antlr_based_language.md | 83 +++++++++++++++++++ ... => adding_a_new_javacc_based_language.md} | 13 ++- 2 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md rename docs/pages/pmd/devdocs/major_contributions/{adding_new_language.md => adding_a_new_javacc_based_language.md} (93%) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md new file mode 100644 index 0000000000..2549f0c75d --- /dev/null +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -0,0 +1,83 @@ +--- +title: Adding PMD support for a new ANTLR grammar based language +short_title: Adding a new language with ANTLR +tags: [devdocs, extending] +summary: "How to add a new language to PMD using ANTLR grammar." +last_updated: July 21, 2019 +sidebar: pmd_sidebar +permalink: pmd_devdocs_major_adding_new_language.html +folder: pmd/devdocs +--- + + +## 1. Start with a new sub-module. +* See pmd-swift for examples. + +## 2. Implement an AST parser for your language +* ANTLR gives you this for free. + +## 3. Create AST node classes +* We provide an [AntlrBaseNode](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AntlrBaseNode.java). +* We override ANTLR auto-generated code to provide this for free, you need to add an ANT script similar to the [swift scrip](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/ant/antlr4.xml). +* You can extend AntlrBaseNode and override any method that you require, but on most cases you won't need to do anything. + +## 4. Compile your parser +* We override ANTLR auto-generated code to provide this for free, similar to the step before, you will need to use the ANT script. +* You should review the [swift pom](https://github.com/pmd/pmd/blob/master/pmd-swift/pom.xml). Don't forget to enable visitor generation property. + +## 5. Create a TokenManager +* We provide a default implementation using [AntlrTokenManager](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrTokenManager.java) that uses an [AntlrTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java). +* You must create your own AntlrTokenizer such as we do with [SwiftTokenizer](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftTokenizer.java). +* If you wish to filter specific tokens you can create your own implementation of [BaseTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) as we did with [SwiftTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). + +## 6. Create a PMD parser “adapter” +* We provide a [BaseParser](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrBaseParser.java) implementation that you need to extend to create your own adapter as we do with [SwiftParserAdapter](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftParserAdapter.java). + +## 7. Create a rule violation factory +* We provide a [AntlrRuleViolationFactory](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleViolationFactory.java) as base implementation, you can use that for most scenarios. +* The purpose of this class is to create a rule violation instance for your handler (spoiler). + +## 8. Create a version handler +* Now you need to create your version handler, as we did with [SwiftHandler](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftHandler.java). +* This class is sort of a gateway between PMD and all parsing logic specific to your language. It has 2 purposes: + * `getRuleViolationFactory` method returns an instance of your rule violation factory *(see step #7)* + * `getParser` returns an instance of your parser adapter *(see step #6)* + +## 9. Create a parser visitor adapter +* We provide an [AbstractAntlrVisitor](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AbstractAntlrVisitor.java) as default implementation, to be able to use this you should also add it to the ANT script we talked about on step #3 +* The purpose of this class is to serve as a pass-through `visitor` implementation, which, for all AST types in your language, just executes visit on the base AST type + +## 10. Create a rule chain visitor +* We provide an [AntlrRuleChainVisitor](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleChainVisitor.java), you can use that for most scenarios. +* If you wish to create your own, you should `implement` two `important` methods: + * `indexNodes` generates a map of "node type" to "list of nodes of that type". This is used to visit all applicable nodes when a rule is applied. + * `visit` method should evaluate what kind of rule is being applied, and execute appropriate logic. Usually it will just check if the rule is a "parser visitor" kind of rule specific to your language, then execute the visitor. If it’s an XPath rule, then we just need to execute evaluate on that. + +## 11. Make PMD recognize your language +* Create your own subclass of `net.sourceforge.pmd.lang.BaseLanguageModule`, see Swift as an example. +* You’ll need to refer the rule chain visitor created in step #10. +* Add for each version of your language a call to `addVersion` in your language module’s constructor. +* Create the service registration via the text file `src/main/resources/META-INF/services/net.sourceforge.pmd.lang.Language`. Add your fully qualified class name as a single line into it. + +## 12. Create an abstract rule class for the language +* You need to create your own `AbstractRule`, our AbstractAntlrVisitor implements this and makes the connection with ANTLR via our ANT script (see step #3). +* You will have an auto-generated XBaseVisitor class (similar to SwiftBaseVisitor) that you will have to extend as we did with [AbstractSwiftRule](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java). +* All other rules for your language should extend this class. The purpose of this class is to implement visit methods for all AST types to simply delegate to default behavior. This is useful because most rules care only about specific AST nodes, but PMD needs to know what to do with each node - so this just lets you use default behavior for nodes you don’t care about. + +## 13. Create rules +* Creating rules is already pretty well documented in PMD - and it’s no different for a new language, except you may have different AST nodes. +* PMD supports 2 types of rules, through visitors or XPath. +* To add a visitor rule: + * You need to extend the abstract rule you created on the previous step, you can use [this rule](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/rule/bestpractices/ProhibitedInterfaceBuilderRule.java) as an example. +* To add an XPath rule you can follow our [guide](https://pmd.github.io/pmd-6.15.0/pmd_userdocs_extending_writing_xpath_rules.html). + +## 14. Test the rules +* See BasicRulesTest for example +* You have to create a rule set for your language *(see vm/basic.xml for example)* +* For each rule in this set you want to test, call `addRule` method in setUp of the unit test + * This triggers the unit test to read the corresponding XML file with rule test data *(see `EmptyForeachStmtRule.xml` for example)* + * This test XML file contains sample pieces of code which should trigger a specified number of violations of this rule. The unit test will execute the rule on this piece of code, and verify that the number of violations matches +* To verify the validity of the created ruleset, create a subclass of `AbstractRuleSetFactoryTest` (*see `RuleSetFactoryTest` in pmd-vm for example)*. + This will load all rulesets and verify, that all required attributes are provided. + + *Note:* You'll need to add your ruleset to `rulesets.properties`, so that it can be found. diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_new_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md similarity index 93% rename from docs/pages/pmd/devdocs/major_contributions/adding_new_language.md rename to docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md index 394e7b151e..cab7fa34d4 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_new_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md @@ -1,9 +1,9 @@ --- -title: Adding PMD support for a new language -short_title: Adding a new language +title: Adding PMD support for a new JAVACC grammar based language +short_title: Adding a new language with JAVACC tags: [devdocs, extending] -summary: "How to add a new language to PMD." -last_updated: July 3, 2016 +summary: "How to add a new language to PMD using JAVACC grammar." +last_updated: July 21, 2019 sidebar: pmd_sidebar permalink: pmd_devdocs_major_adding_new_language.html folder: pmd/devdocs @@ -43,14 +43,13 @@ folder: pmd/devdocs ## 7. Create a rule violation factory * Extend `AbstractRuleViolationFactory` *(see VmRuleViolationFactory for example)* -* The purpose of this class is to createa rule violation instance specific to your language +* The purpose of this class is to create a rule violation instance specific to your language ## 8. Create a version handler * Extend `AbstractLanguageVersionHandler` *(see VmHandler for example)* -* This class is sort of a gateway between PMD and all parsing logic specific to your language. It has 3 purposes: +* This class is sort of a gateway between PMD and all parsing logic specific to your language. It has 2 purposes: * `getRuleViolationFactory` method returns an instance of your rule violation factory *(see step #7)* * `getParser` returns an instance of your parser adapter *(see step #6)* - * `getDumpFacade` returns a `VisitorStarter` that allows to dump a text representation of the AST into a writer *(likely for debugging purposes)* ## 9. Create a parser visitor adapter * If you use JJT to generate your parser, it should also generate an interface for a parser visitor *(see VmParserVisitor for example)* From 911937030288ab2dbad8f624037061c829ab3b8f Mon Sep 17 00:00:00 2001 From: Matias Fraga Date: Fri, 21 Jun 2019 18:59:45 -0300 Subject: [PATCH 002/104] Rerun CI From e70235824bfc573ff72e44be5b707a05222803d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:51:25 -0300 Subject: [PATCH 003/104] Update docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index 2549f0c75d..0f28f56173 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -18,7 +18,7 @@ folder: pmd/devdocs ## 3. Create AST node classes * We provide an [AntlrBaseNode](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AntlrBaseNode.java). -* We override ANTLR auto-generated code to provide this for free, you need to add an ANT script similar to the [swift scrip](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/ant/antlr4.xml). +* We override ANTLR auto-generated code to provide this for free, you need to add an ANT script similar to the [swift script](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/ant/antlr4.xml). * You can extend AntlrBaseNode and override any method that you require, but on most cases you won't need to do anything. ## 4. Compile your parser From d1c20008a09935df10c24b7120ea7c08ad78ab8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:51:34 -0300 Subject: [PATCH 004/104] Update docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index 0f28f56173..b1d5c72c33 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -17,7 +17,7 @@ folder: pmd/devdocs * ANTLR gives you this for free. ## 3. Create AST node classes -* We provide an [AntlrBaseNode](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AntlrBaseNode.java). +* We provide an [`AntlrBaseNode`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AntlrBaseNode.java). * We override ANTLR auto-generated code to provide this for free, you need to add an ANT script similar to the [swift script](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/ant/antlr4.xml). * You can extend AntlrBaseNode and override any method that you require, but on most cases you won't need to do anything. From 71ffdb829563db5e185e2cc8c993c798a83a32be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:51:43 -0300 Subject: [PATCH 005/104] Update docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index b1d5c72c33..2adee13bc4 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -19,7 +19,7 @@ folder: pmd/devdocs ## 3. Create AST node classes * We provide an [`AntlrBaseNode`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AntlrBaseNode.java). * We override ANTLR auto-generated code to provide this for free, you need to add an ANT script similar to the [swift script](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/ant/antlr4.xml). -* You can extend AntlrBaseNode and override any method that you require, but on most cases you won't need to do anything. +* You can extend `AntlrBaseNode` and override any method that you require, but on most cases you won't need to do anything. ## 4. Compile your parser * We override ANTLR auto-generated code to provide this for free, similar to the step before, you will need to use the ANT script. From e614bc2ab29cb2b701209b7f73d505505a0c9d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:51:50 -0300 Subject: [PATCH 006/104] Update docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index 2adee13bc4..b7473ab031 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -26,7 +26,7 @@ folder: pmd/devdocs * You should review the [swift pom](https://github.com/pmd/pmd/blob/master/pmd-swift/pom.xml). Don't forget to enable visitor generation property. ## 5. Create a TokenManager -* We provide a default implementation using [AntlrTokenManager](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrTokenManager.java) that uses an [AntlrTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java). +* We provide a default implementation using [`AntlrTokenManager`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrTokenManager.java) that uses an [`AntlrTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java). * You must create your own AntlrTokenizer such as we do with [SwiftTokenizer](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftTokenizer.java). * If you wish to filter specific tokens you can create your own implementation of [BaseTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) as we did with [SwiftTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). From 104954d611fb8bb3e08b59f9f469a2e9386ad830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:51:57 -0300 Subject: [PATCH 007/104] Update docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index b7473ab031..daa6bd6d56 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -27,7 +27,7 @@ folder: pmd/devdocs ## 5. Create a TokenManager * We provide a default implementation using [`AntlrTokenManager`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrTokenManager.java) that uses an [`AntlrTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java). -* You must create your own AntlrTokenizer such as we do with [SwiftTokenizer](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftTokenizer.java). +* You must create your own `AntlrTokenizer` such as we do with [`SwiftTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftTokenizer.java). * If you wish to filter specific tokens you can create your own implementation of [BaseTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) as we did with [SwiftTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). ## 6. Create a PMD parser “adapter” From 7ffe656eb5cb5b0373a0521da6508380b1981a92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:52:09 -0300 Subject: [PATCH 008/104] Update docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index daa6bd6d56..22210a13c8 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -28,7 +28,7 @@ folder: pmd/devdocs ## 5. Create a TokenManager * We provide a default implementation using [`AntlrTokenManager`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrTokenManager.java) that uses an [`AntlrTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java). * You must create your own `AntlrTokenizer` such as we do with [`SwiftTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftTokenizer.java). -* If you wish to filter specific tokens you can create your own implementation of [BaseTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) as we did with [SwiftTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). +* If you wish to filter specific tokens you can create your own implementation of [`BaseTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) as we did with [`SwiftTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). ## 6. Create a PMD parser “adapter” * We provide a [BaseParser](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrBaseParser.java) implementation that you need to extend to create your own adapter as we do with [SwiftParserAdapter](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftParserAdapter.java). From b9d4e3b2c56e98b63d18ae67f64236155e493a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:53:05 -0300 Subject: [PATCH 009/104] Update docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index 22210a13c8..74c7779e56 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -31,7 +31,7 @@ folder: pmd/devdocs * If you wish to filter specific tokens you can create your own implementation of [`BaseTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) as we did with [`SwiftTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). ## 6. Create a PMD parser “adapter” -* We provide a [BaseParser](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrBaseParser.java) implementation that you need to extend to create your own adapter as we do with [SwiftParserAdapter](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftParserAdapter.java). +* We provide a [`BaseParser`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrBaseParser.java) implementation that you need to extend to create your own adapter as we do with [`SwiftParserAdapter`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftParserAdapter.java). ## 7. Create a rule violation factory * We provide a [AntlrRuleViolationFactory](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleViolationFactory.java) as base implementation, you can use that for most scenarios. From c9123780a408ddcdd2fee0df4be77ba95895c3a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:53:13 -0300 Subject: [PATCH 010/104] Update docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index 74c7779e56..8c8de67015 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -48,7 +48,7 @@ folder: pmd/devdocs * The purpose of this class is to serve as a pass-through `visitor` implementation, which, for all AST types in your language, just executes visit on the base AST type ## 10. Create a rule chain visitor -* We provide an [AntlrRuleChainVisitor](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleChainVisitor.java), you can use that for most scenarios. +* We provide an [`AntlrRuleChainVisitor`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleChainVisitor.java), you can use that for most scenarios. * If you wish to create your own, you should `implement` two `important` methods: * `indexNodes` generates a map of "node type" to "list of nodes of that type". This is used to visit all applicable nodes when a rule is applied. * `visit` method should evaluate what kind of rule is being applied, and execute appropriate logic. Usually it will just check if the rule is a "parser visitor" kind of rule specific to your language, then execute the visitor. If it’s an XPath rule, then we just need to execute evaluate on that. From 0d701273a88b042683afc0037894d26567ee4474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:53:21 -0300 Subject: [PATCH 011/104] Update docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index 8c8de67015..71378bbb01 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -60,7 +60,7 @@ folder: pmd/devdocs * Create the service registration via the text file `src/main/resources/META-INF/services/net.sourceforge.pmd.lang.Language`. Add your fully qualified class name as a single line into it. ## 12. Create an abstract rule class for the language -* You need to create your own `AbstractRule`, our AbstractAntlrVisitor implements this and makes the connection with ANTLR via our ANT script (see step #3). +* You need to create your own `AbstractRule`, our `AbstractAntlrVisitor` implements this and makes the connection with ANTLR via our ANT script (see step #3). * You will have an auto-generated XBaseVisitor class (similar to SwiftBaseVisitor) that you will have to extend as we did with [AbstractSwiftRule](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java). * All other rules for your language should extend this class. The purpose of this class is to implement visit methods for all AST types to simply delegate to default behavior. This is useful because most rules care only about specific AST nodes, but PMD needs to know what to do with each node - so this just lets you use default behavior for nodes you don’t care about. From 83f5064769c11a943adaef1f9970873138a5e0c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:53:37 -0300 Subject: [PATCH 012/104] Update docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index 71378bbb01..599f3da4e0 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -61,7 +61,7 @@ folder: pmd/devdocs ## 12. Create an abstract rule class for the language * You need to create your own `AbstractRule`, our `AbstractAntlrVisitor` implements this and makes the connection with ANTLR via our ANT script (see step #3). -* You will have an auto-generated XBaseVisitor class (similar to SwiftBaseVisitor) that you will have to extend as we did with [AbstractSwiftRule](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java). +* You will have an auto-generated `XBaseVisitor` class (similar to `SwiftBaseVisitor`) that you will have to extend as we did with [`AbstractSwiftRule`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java). * All other rules for your language should extend this class. The purpose of this class is to implement visit methods for all AST types to simply delegate to default behavior. This is useful because most rules care only about specific AST nodes, but PMD needs to know what to do with each node - so this just lets you use default behavior for nodes you don’t care about. ## 13. Create rules From 738031d6a9b658dbb8780f3ed9835b70ec1cf914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:54:03 -0300 Subject: [PATCH 013/104] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Juan Martín Sotuyo Dodero --- .../adding_a_new_antlr_based_language.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index 599f3da4e0..6a0c856f8c 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -34,17 +34,17 @@ folder: pmd/devdocs * We provide a [`BaseParser`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrBaseParser.java) implementation that you need to extend to create your own adapter as we do with [`SwiftParserAdapter`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftParserAdapter.java). ## 7. Create a rule violation factory -* We provide a [AntlrRuleViolationFactory](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleViolationFactory.java) as base implementation, you can use that for most scenarios. +* We provide a [`AntlrRuleViolationFactory`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleViolationFactory.java) as base implementation, you can use that for most scenarios. * The purpose of this class is to create a rule violation instance for your handler (spoiler). ## 8. Create a version handler -* Now you need to create your version handler, as we did with [SwiftHandler](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftHandler.java). +* Now you need to create your version handler, as we did with [`SwiftHandler`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftHandler.java). * This class is sort of a gateway between PMD and all parsing logic specific to your language. It has 2 purposes: * `getRuleViolationFactory` method returns an instance of your rule violation factory *(see step #7)* * `getParser` returns an instance of your parser adapter *(see step #6)* ## 9. Create a parser visitor adapter -* We provide an [AbstractAntlrVisitor](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AbstractAntlrVisitor.java) as default implementation, to be able to use this you should also add it to the ANT script we talked about on step #3 +* We provide an [`AbstractAntlrVisitor`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AbstractAntlrVisitor.java) as default implementation, to be able to use this you should also add it to the ANT script we talked about on step #3 * The purpose of this class is to serve as a pass-through `visitor` implementation, which, for all AST types in your language, just executes visit on the base AST type ## 10. Create a rule chain visitor From e8ae35073b4d15dd45210bf22a4f8280db98bba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Sat, 3 Aug 2019 19:59:15 -0300 Subject: [PATCH 014/104] Update adding_a_new_antlr_based_language.md --- .../major_contributions/adding_a_new_antlr_based_language.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index 6a0c856f8c..cee98699b2 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -28,7 +28,7 @@ folder: pmd/devdocs ## 5. Create a TokenManager * We provide a default implementation using [`AntlrTokenManager`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrTokenManager.java) that uses an [`AntlrTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java). * You must create your own `AntlrTokenizer` such as we do with [`SwiftTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftTokenizer.java). -* If you wish to filter specific tokens you can create your own implementation of [`BaseTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) as we did with [`SwiftTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). +* If you wish to filter specific tokens you can create your own implementation of [`BaseTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) as we did with [`SwiftTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). If you don't need a custom token filter, you can return an instance of [`AntlrTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). ## 6. Create a PMD parser “adapter” * We provide a [`BaseParser`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrBaseParser.java) implementation that you need to extend to create your own adapter as we do with [`SwiftParserAdapter`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftParserAdapter.java). From 048f4c65f925e5cba8c9376e79ff7974cd477cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Mon, 5 Jul 2021 15:43:01 -0300 Subject: [PATCH 015/104] Update ReturnFromFinallyBlock --- pmd-java/src/main/resources/category/java/errorprone.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 22a568eede..79ac96bf48 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -2740,7 +2740,7 @@ Avoid returning from a finally block, this can discard exceptions. 3 - //FinallyStatement//ReturnStatement except //FinallyStatement//(MethodDeclaration|LambdaExpression)//ReturnStatement + //FinallyClause//ReturnStatement except //FinallyClause//(MethodDeclaration|LambdaExpression)//ReturnStatement From 323c5a82bcab4004bbd7d10778e705f49b65bf5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Mon, 5 Jul 2021 15:43:45 -0300 Subject: [PATCH 016/104] Reenable ReturnFromFinallyBlock regression testing --- .ci/files/all-java.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index b1005d2a2a..9b9f7a2122 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -248,7 +248,7 @@ - + From 74b75dc098a7cf151b2565dcfad9548999f3a72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Mon, 5 Jul 2021 16:19:05 -0300 Subject: [PATCH 017/104] Reenable unit test --- .../lang/java/rule/errorprone/ReturnFromFinallyBlockTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/ReturnFromFinallyBlockTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/ReturnFromFinallyBlockTest.java index 1d83115c71..5945a9133f 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/ReturnFromFinallyBlockTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/ReturnFromFinallyBlockTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class ReturnFromFinallyBlockTest extends PmdRuleTst { // no additional unit tests } From adb9182f70c374478e87bf0804448d349d63a738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Mon, 5 Jul 2021 20:31:46 -0300 Subject: [PATCH 018/104] Update NonStaticInitializer --- pmd-java/src/main/resources/category/java/errorprone.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 22a568eede..589164025e 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -2523,7 +2523,7 @@ confusing. From 61be284d2ffae67e9262bb24286c6bccfb64dd0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Mon, 5 Jul 2021 20:33:03 -0300 Subject: [PATCH 019/104] Reenable NonStaticInitializer --- .ci/files/all-java.xml | 2 +- .../pmd/lang/java/rule/errorprone/NonStaticInitializerTest.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index b1005d2a2a..0dad4890c2 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -242,7 +242,7 @@ - + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/NonStaticInitializerTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/NonStaticInitializerTest.java index 8f3c4fa311..f009ce5ab2 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/NonStaticInitializerTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/NonStaticInitializerTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class NonStaticInitializerTest extends PmdRuleTst { // no additional unit tests } From e3efb8c36e62e552a32d8a739da279ff25b9c7fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:24:42 -0300 Subject: [PATCH 020/104] Update MissingSerialVersionUID --- pmd-java/src/main/resources/category/java/errorprone.xml | 3 +-- .../lang/java/rule/errorprone/MissingSerialVersionUIDTest.java | 1 - .../lang/java/rule/errorprone/xml/MissingSerialVersionUID.xml | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 589164025e..7044e6e135 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -2341,8 +2341,7 @@ chain needs an own serialVersionUID field. See also [Should an abstract class ha diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/MissingSerialVersionUIDTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/MissingSerialVersionUIDTest.java index 608f84996c..b2437fbaf8 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/MissingSerialVersionUIDTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/MissingSerialVersionUIDTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class MissingSerialVersionUIDTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/MissingSerialVersionUID.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/MissingSerialVersionUID.xml index e88e57ea14..3da6fa9c53 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/MissingSerialVersionUID.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/MissingSerialVersionUID.xml @@ -17,6 +17,8 @@ public class Foo { Simple failure case 1 From f4c9cf2902d4a34913708eafc8b6cff71034c6f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:25:31 -0300 Subject: [PATCH 021/104] Reenable MissingSerialVersionUID --- .ci/files/all-java.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 0dad4890c2..bb93dd5799 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -238,7 +238,7 @@ - + From d54cf810f27a7d8341a5a20b685e2489bd9cffeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:37:38 -0300 Subject: [PATCH 022/104] Update InstantiationToGetClass --- pmd-java/src/main/resources/category/java/errorprone.xml | 9 +++------ .../rule/errorprone/InstantiationToGetClassTest.java | 1 - 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 7044e6e135..f5d99aaa8d 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -2067,12 +2067,9 @@ Avoid instantiating an object just to call getClass() on it; use the .class publ diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/InstantiationToGetClassTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/InstantiationToGetClassTest.java index 002a4b5e05..f27f820f6f 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/InstantiationToGetClassTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/InstantiationToGetClassTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class InstantiationToGetClassTest extends PmdRuleTst { // no additional unit tests } From 0b0e03f19259af0bf167e8e1470cd567a12d5654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:37:55 -0300 Subject: [PATCH 023/104] Reenable InstantiationToGetClass --- .ci/files/all-java.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index bb93dd5799..2d201478d1 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -230,7 +230,7 @@ - + From ab9499a1ec7ec55e5a5d0aad75e0662e44388c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:40:34 -0300 Subject: [PATCH 024/104] Update FinalizeShouldBeProtected --- pmd-java/src/main/resources/category/java/errorprone.xml | 2 +- .../java/rule/errorprone/FinalizeShouldBeProtectedTest.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index f5d99aaa8d..5871d46ac2 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -2017,7 +2017,7 @@ Note that Oracle has declared Object.finalize() as deprecated since JDK 9. diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeShouldBeProtectedTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeShouldBeProtectedTest.java index 5fb2be61f2..73b0ee58fc 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeShouldBeProtectedTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeShouldBeProtectedTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class FinalizeShouldBeProtectedTest extends PmdRuleTst { // no additional unit tests } From 46d3636889080f5ddfbf46664525cbb745217f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:40:57 -0300 Subject: [PATCH 025/104] eenable FinalizeShouldBeProtected --- .ci/files/all-java.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 2d201478d1..7e97aa7f55 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -228,7 +228,7 @@ - + From a8e25e03936ea9489e03a21e0ed69060b04c8a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:43:03 -0300 Subject: [PATCH 026/104] Reenable FinalizeOverloaded --- .ci/files/all-java.xml | 2 +- .../pmd/lang/java/rule/errorprone/FinalizeOverloadedTest.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 7e97aa7f55..b97835b819 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -227,7 +227,7 @@ - + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeOverloadedTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeOverloadedTest.java index 5efb414193..e123e98a1c 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeOverloadedTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeOverloadedTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class FinalizeOverloadedTest extends PmdRuleTst { // no additional unit tests } From d539f472c835e9e988dccb47f9b8d591c1aff61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:50:24 -0300 Subject: [PATCH 027/104] Update FinalizeOnlyCallsSuperFinalize --- pmd-java/src/main/resources/category/java/errorprone.xml | 7 +------ .../errorprone/FinalizeOnlyCallsSuperFinalizeTest.java | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 5871d46ac2..7ede418b21 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -1948,12 +1948,7 @@ If the finalize() is implemented, it should do something besides just calling su diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeOnlyCallsSuperFinalizeTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeOnlyCallsSuperFinalizeTest.java index 929b7ebe7b..af0ab11739 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeOnlyCallsSuperFinalizeTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeOnlyCallsSuperFinalizeTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class FinalizeOnlyCallsSuperFinalizeTest extends PmdRuleTst { // no additional unit tests } From 3b1b8a203d6fb1424e651e0efbee5ebf9d5b9b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:50:49 -0300 Subject: [PATCH 028/104] Reenable FinalizeOnlyCallsSuperFinalize --- .ci/files/all-java.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index b97835b819..b4660ed8df 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -226,7 +226,7 @@ - + From 25a3c01a99dc54d4732cb022b652ffff72dc650b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:59:24 -0300 Subject: [PATCH 029/104] Update FinalizeDoesNotCallSuperFinalize --- .../resources/category/java/errorprone.xml | 19 +++++-------------- .../FinalizeDoesNotCallSuperFinalizeTest.java | 1 - 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 7ede418b21..3176378850 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -1905,20 +1905,11 @@ If the finalize() is implemented, its last action should be to call super.finali diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeDoesNotCallSuperFinalizeTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeDoesNotCallSuperFinalizeTest.java index f74194a4d5..97017d2b87 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeDoesNotCallSuperFinalizeTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/FinalizeDoesNotCallSuperFinalizeTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class FinalizeDoesNotCallSuperFinalizeTest extends PmdRuleTst { // no additional unit tests } From b649efe685191459e2422b1afd8c84da4b9a56a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Tue, 6 Jul 2021 02:59:46 -0300 Subject: [PATCH 030/104] Reenable FinalizeDoesNotCallSuperFinalize --- .ci/files/all-java.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index b4660ed8df..03e1253c0d 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -225,7 +225,7 @@ - + From c2105d338531e3fa8ccd76e78474738dc87ce253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 12 Jul 2021 17:35:21 +0200 Subject: [PATCH 031/104] Update rule ClassWithOnlyPrivateConstructorsShouldBeFinal --- ...yPrivateConstructorsShouldBeFinalRule.java | 49 +++++++++++++++++++ .../pmd/lang/java/types/TypeTestUtil.java | 37 ++++++++------ .../main/resources/category/java/design.xml | 22 ++------- ...yPrivateConstructorsShouldBeFinalTest.java | 1 - 4 files changed, 77 insertions(+), 32 deletions(-) create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ClassWithOnlyPrivateConstructorsShouldBeFinalRule.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ClassWithOnlyPrivateConstructorsShouldBeFinalRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ClassWithOnlyPrivateConstructorsShouldBeFinalRule.java new file mode 100644 index 0000000000..85720dedc4 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ClassWithOnlyPrivateConstructorsShouldBeFinalRule.java @@ -0,0 +1,49 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.design; + +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.rule.AbstractJavaRulechainRule; +import net.sourceforge.pmd.lang.java.types.TypeTestUtil; + +public class ClassWithOnlyPrivateConstructorsShouldBeFinalRule extends AbstractJavaRulechainRule { + + public ClassWithOnlyPrivateConstructorsShouldBeFinalRule() { + super(ASTClassOrInterfaceDeclaration.class); + } + + @Override + public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { + if (node.isRegularClass() + && !node.isFinal() + && hasOnlyPrivateCtors(node) + && hasNoSubclasses(node)) { + addViolation(data, node); + } + return null; + } + + private boolean hasNoSubclasses(ASTClassOrInterfaceDeclaration klass) { + return klass.getRoot() + .descendants(ASTAnyTypeDeclaration.class) + .crossFindBoundaries() + .none(it -> doesExtend(it, klass)); + } + + private boolean doesExtend(ASTAnyTypeDeclaration sub, ASTClassOrInterfaceDeclaration superClass) { + return sub != superClass && TypeTestUtil.isA(superClass.getTypeMirror(), sub); + } + + private boolean hasOnlyPrivateCtors(ASTClassOrInterfaceDeclaration node) { + return node.getDeclarations(ASTConstructorDeclaration.class).all(it -> it.getVisibility() == V_PRIVATE) + && (node.getVisibility() == V_PRIVATE // then the default ctor is private + || node.getDeclarations(ASTConstructorDeclaration.class).nonEmpty()); + } + +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java index 4b7017df95..98150320be 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java @@ -95,7 +95,7 @@ public final class TypeTestUtil { return isExactlyA(clazz, type.getSymbol()); } - return isA(type, otherType); + return isA(otherType, type); } @@ -134,26 +134,35 @@ public final class TypeTestUtil { return isA(canonicalName, thisType, null); } + public static boolean isA(@NonNull JTypeMirror t1, @Nullable TypeNode t2) { + return t2 != null && isA(t1, t2.getTypeMirror()); + } + /** - * This is the subtyping routine we use, which prunes some behavior - * of isSubtypeOf that we don't want (eg, that unresolved types are - * subtypes of everything). + * Checks whether the first type is a subtype of the second. This + * removes some behavior of isSubtypeOf that we don't want (eg, that + * unresolved types are subtypes of everything). + * + * @param t1 A supertype + * @param t2 A type + * + * @return Whether t1 is a subtype of t2 */ - private static boolean isA(JTypeMirror t1, JTypeMirror t2) { - if (t1 == null || t2 == null) { + private static boolean isA(@Nullable JTypeMirror t1, @NonNull JTypeMirror t2) { + if (t1 == null) { return false; - } else if (t1.isPrimitive() || t2.isPrimitive()) { - return t1.equals(t2); // isSubtypeOf considers primitive widening like subtyping - } else if (TypeOps.isUnresolved(t1)) { + } else if (t2.isPrimitive() || t1.isPrimitive()) { + return t2.equals(t1); // isSubtypeOf considers primitive widening like subtyping + } else if (TypeOps.isUnresolved(t2)) { // we can't get any useful info from this, isSubtypeOf would return true return false; - } else if (t2.isClassOrInterface() && ((JClassType) t2).getSymbol().isAnonymousClass()) { + } else if (t1.isClassOrInterface() && ((JClassType) t1).getSymbol().isAnonymousClass()) { return false; // conventionally - } else if (t1 instanceof JTypeVar) { - return t2.isTop() || isA(((JTypeVar) t1).getUpperBound(), t2); + } else if (t2 instanceof JTypeVar) { + return t1.isTop() || isA(t1, ((JTypeVar) t2).getUpperBound()); } - return t1.isSubtypeOf(t2); + return t2.isSubtypeOf(t1); } private static boolean isA(@NonNull String canonicalName, @NonNull JTypeMirror thisType, @Nullable UnresolvedClassStore unresolvedStore) { @@ -173,7 +182,7 @@ public final class TypeTestUtil { TypeSystem ts = thisType.getTypeSystem(); @Nullable JTypeMirror otherType = TypesFromReflection.loadType(ts, canonicalName, unresolvedStore); - return isA(thisType, otherType); + return isA(otherType, thisType); } /** diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index bd2c103f3c..1484d29e24 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -314,27 +314,15 @@ public void foo() throws RuntimeException { -A class with only private constructors should be final, unless the private constructor -is invoked by a inner class. +Reports classes that may be made final because they cannot be extended from outside +their compilation unit anyway. This is because all their constructors are private, +so a subclass could not call the super constructor. 1 - - - - - - - Date: Mon, 12 Jul 2021 17:38:11 +0200 Subject: [PATCH 032/104] Add test case for #2536 --- .../ClassWithOnlyPrivateConstructorsShouldBeFinal.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml index 538aca8368..805f6a0822 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml @@ -135,4 +135,15 @@ class ClassWithOnlyPrivateConstructorsShouldBeFinal { } ]]> + + #2536 [java] ClassWithOnlyPrivateConstructorsShouldBeFinal can't detect inner class with only private constructor + 1 + + From 4b8e83d3d7e023f896b89fa7ad661f5b1c1a7920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 12 Jul 2021 17:40:58 +0200 Subject: [PATCH 033/104] Update ci file & release notes --- .ci/files/all-java.xml | 2 +- docs/pages/7_0_0_release_notes.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index b1005d2a2a..bef96d8e10 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -127,7 +127,7 @@ - + diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 65a0e56b07..10da7addc4 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -165,6 +165,8 @@ The following previously deprecated rules have been finally removed: * [#3218](https://github.com/pmd/pmd/pull/3218): \[java] Generalize UnnecessaryCast to flag all unnecessary casts * [#3221](https://github.com/pmd/pmd/issues/3221): \[java] PrematureDeclaration false positive for unused variables * [#3238](https://github.com/pmd/pmd/issues/3238): \[java] Improve ExprContext, fix FNs of UnnecessaryCast +* java-design + * [#2536](https://github.com/pmd/pmd/issues/2536): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal can't detect inner class * java-errorprone * [#659](https://github.com/pmd/pmd/issues/659): \[java] MissingBreakInSwitch - last default case does not contain a break * [#1005](https://github.com/pmd/pmd/issues/1005): \[java] CloneMethodMustImplementCloneable triggers for interfaces From 3734d293e8cf33b9fa02e6741a98666e158b72c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 13:58:55 +0200 Subject: [PATCH 034/104] Add an attribute to apex nodes to get filename from XPath Fix #3446 --- .../sourceforge/pmd/lang/apex/ApexParser.java | 2 +- .../pmd/lang/apex/ast/ApexParser.java | 13 +++++++++++-- .../pmd/lang/apex/ast/ApexRootNode.java | 18 ++++++++++++++++++ .../pmd/lang/apex/ast/ApexTreeDumpTest.java | 2 +- .../lang/apex/ast/SafeNavigationOperator.txt | 2 +- .../pmd/cpd/test/CpdTextComparisonTest.kt | 4 ++-- .../pmd/lang/ast/test/BaseParsingHelper.kt | 8 ++++++-- .../pmd/lang/ast/test/BaseTreeDumpTest.kt | 8 ++++++-- .../pmd/test/BaseTextComparisonTest.kt | 8 +++++--- 9 files changed, 51 insertions(+), 14 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexParser.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexParser.java index fdcedcd253..db09d87e61 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexParser.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexParser.java @@ -42,7 +42,7 @@ public class ApexParser extends AbstractParser { @Override public Node parse(String fileName, Reader source) throws ParseException { - return apexParser.parse(source); + return apexParser.parse(source, fileName); } @Override diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java index a6ff552503..d2e9bd2d6f 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.apex.ast; import java.io.IOException; import java.io.Reader; import java.util.Map; +import java.util.Objects; import org.apache.commons.io.IOUtils; @@ -48,7 +49,13 @@ public class ApexParser { return visitor.getTopLevel(); } + @Deprecated public ApexNode parse(final Reader reader) { + throw new UnsupportedOperationException("use the other overload, this class is internal API btw"); + } + + public ApexNode parse(final Reader reader, final String fileName) { + Objects.requireNonNull(fileName, "file name is null"); try { final String sourceCode = IOUtils.toString(reader); final Compilation astRoot = parseApex(sourceCode); @@ -59,7 +66,9 @@ public class ApexParser { throw new ParseException("Couldn't parse the source - there is not root node - Syntax Error??"); } - return treeBuilder.build(astRoot); + ApexRootNode root = (ApexRootNode) treeBuilder.build(astRoot); + root.setFileName(fileName); + return root; } catch (IOException | apex.jorje.services.exception.ParseException e) { throw new ParseException(e); } @@ -69,7 +78,7 @@ public class ApexParser { return suppressMap; } - private class TopLevelVisitor extends AstVisitor { + private static class TopLevelVisitor extends AstVisitor { Compilation topLevel; public Compilation getTopLevel() { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java index a14c241b44..be2a1857cc 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.apex.ast; +import java.nio.file.Paths; + import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.RootNode; import net.sourceforge.pmd.lang.ast.SourceCodePositioner; @@ -14,6 +16,9 @@ import apex.jorje.services.Version; @Deprecated @InternalApi public abstract class ApexRootNode extends AbstractApexNode implements RootNode { + + private String fileName; + @Deprecated @InternalApi public ApexRootNode(T node) { @@ -51,6 +56,19 @@ public abstract class ApexRootNode extends AbstractApexNode - val sourceCode = SourceCode(SourceCode.StringCodeLoader(sourceText, "$fileBaseName$extensionIncludingDot")) + super.doTest(fileBaseName, expectedSuffix) { fileData -> + val sourceCode = SourceCode(SourceCode.StringCodeLoader(fileData.fileText, fileData.fileName)) val tokens = Tokens().also { val tokenizer = newTokenizer(properties) tokenizer.tokenize(sourceCode, it) diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt index c209327c9f..57946ffeb2 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt @@ -111,12 +111,16 @@ abstract class BaseParsingHelper, T : RootNode * so. */ @JvmOverloads - open fun parse(sourceCode: String, version: String? = null): T { + open fun parse( + sourceCode: String, + version: String? = null, + fileName: String = "src/a/test-file-name.txt" + ): T { val lversion = if (version == null) defaultVersion else getVersion(version) val handler = lversion.languageVersionHandler val options = params.parserOptions ?: handler.defaultParserOptions val parser = handler.getParser(options) - val rootNode = rootClass.cast(parser.parse(null, StringReader(sourceCode))) + val rootNode = rootClass.cast(parser.parse(fileName, StringReader(sourceCode))) if (params.doProcess) { handler.getQualifiedNameResolutionFacade(javaClass.classLoader).start(rootNode) handler.getSymbolFacade(javaClass.classLoader).start(rootNode) diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseTreeDumpTest.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseTreeDumpTest.kt index 2a1614151c..7358c21c6b 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseTreeDumpTest.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseTreeDumpTest.kt @@ -31,9 +31,13 @@ abstract class BaseTreeDumpTest( * @see BaseTextComparisonTest.doTest */ fun doTest(fileBaseName: String) { - super.doTest(fileBaseName, "") { sourceText -> + super.doTest(fileBaseName, "") { fileData -> buildString { - printer.renderSubtree(parser.parse(sourceText), this) + val ast = parser.parse( + sourceCode = fileData.fileText, + fileName = fileData.fileName + ) + printer.renderSubtree(ast, this) } } } diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/BaseTextComparisonTest.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/BaseTextComparisonTest.kt index 04ec134b3e..e1b3b10942 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/BaseTextComparisonTest.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/test/BaseTextComparisonTest.kt @@ -27,6 +27,8 @@ abstract class BaseTextComparisonTest { /** Extension that the unparsed source file is supposed to have. */ protected abstract val extensionIncludingDot: String + data class FileData(val fileName:String, val fileText:String) + /** * Executes the test. The test files are looked up using the [parser]. * The reference test file must be named [fileBaseName] + [ExpectedExt]. @@ -37,7 +39,7 @@ abstract class BaseTextComparisonTest { */ internal fun doTest(fileBaseName: String, expectedSuffix: String = "", - transformTextContent: (String) -> String) { + transformTextContent: (FileData) -> String) { val expectedFile = findTestFile(resourceLoader, "${resourcePrefix}/$fileBaseName$expectedSuffix$ExpectedExt").toFile() val actual = transformTextContent(sourceText(fileBaseName)) @@ -52,7 +54,7 @@ abstract class BaseTextComparisonTest { assertEquals(expected.normalize(), actual.normalize(), "File comparison failed, see the reference: $expectedFile") } - protected fun sourceText(fileBaseName: String): String { + protected fun sourceText(fileBaseName: String): FileData { val sourceFile = findTestFile(resourceLoader, "${resourcePrefix}/$fileBaseName$extensionIncludingDot").toFile() assert(sourceFile.isFile) { @@ -60,7 +62,7 @@ abstract class BaseTextComparisonTest { } val sourceText = sourceFile.readText(Charsets.UTF_8).normalize() - return sourceText + return FileData(fileName = sourceFile.toString(), fileText = sourceText) } // Outputting a path makes for better error messages From e3a94a1b0440b3daae65e53a77de798aeb801b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 14:30:56 +0200 Subject: [PATCH 035/104] Port some stuff from pmd 7, add test --- .../pmd/lang/apex/ast/ApexParserTestBase.java | 4 ++ .../lang/apex/ast/ApexParserXPathTest.java | 33 ----------- .../pmd/lang/apex/rule/ApexXPathRuleTest.java | 48 +++++++++++++++ .../apex/{ast => rule}/BooleanExpressions.cls | 0 .../pmd/lang/ast/test/BaseParsingHelper.kt | 58 +++++++++++++++---- .../pmd/lang/ast/test/TestUtils.kt | 49 +++++++++++++++- 6 files changed, 147 insertions(+), 45 deletions(-) delete mode 100644 pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserXPathTest.java create mode 100644 pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRuleTest.java rename pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/{ast => rule}/BooleanExpressions.cls (100%) diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserTestBase.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserTestBase.java index 82966d4c34..4186c5d310 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserTestBase.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserTestBase.java @@ -15,6 +15,10 @@ public class ApexParserTestBase { return apex.parse(code); } + protected ApexNode parse(String code, String fileName) { + return apex.parse(code, null, fileName); + } + protected ApexNode parseResource(String code) { return apex.parseResource(code); } diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserXPathTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserXPathTest.java deleted file mode 100644 index ddb770c7a6..0000000000 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserXPathTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.apex.ast; - -import java.nio.charset.StandardCharsets; -import java.util.List; - -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Test; - -import net.sourceforge.pmd.lang.ast.Node; - -import apex.jorje.semantic.ast.compilation.Compilation; - -public class ApexParserXPathTest extends ApexParserTestBase { - - @Test - public void testBooleanExpressions() throws Exception { - ApexNode node = parse(IOUtils.toString(ApexParserXPathTest.class.getResourceAsStream("BooleanExpressions.cls"), - StandardCharsets.UTF_8)); - List booleanExpressions = node.findDescendantsOfType(ASTBooleanExpression.class); - Assert.assertEquals(2, booleanExpressions.size()); - Assert.assertEquals("&&", booleanExpressions.get(0).getOperator().toString()); - Assert.assertEquals("!=", booleanExpressions.get(1).getOperator().toString()); - - List xpathResult = node.findChildNodesWithXPath("//BooleanExpression[@Operator='&&']"); - Assert.assertEquals(1, xpathResult.size()); - Assert.assertSame(booleanExpressions.get(0), xpathResult.get(0)); - } -} diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRuleTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRuleTest.java new file mode 100644 index 0000000000..a8f1e3c730 --- /dev/null +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRuleTest.java @@ -0,0 +1,48 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex.rule; + +import static net.sourceforge.pmd.lang.ast.test.TestUtilsKt.assertSize; + +import org.junit.Test; + +import net.sourceforge.pmd.Report; +import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.lang.apex.ApexLanguageModule; +import net.sourceforge.pmd.lang.apex.ast.ApexParserTestBase; +import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; + +/** + * @author daniels + */ +public class ApexXPathRuleTest extends ApexParserTestBase { + + private XPathRule makeXPath(String expression) { + XPathRule rule = new XPathRule(XPathVersion.XPATH_2_0, expression); + rule.setLanguage(LanguageRegistry.getLanguage(ApexLanguageModule.NAME)); + rule.setMessage("XPath Rule Failed"); + return rule; + } + + + @Test + public void testFileNameInXpath() { + Report report = apex.executeRule(makeXPath("/UserClass[@FileName = 'Foo.cls']"), + "class Foo {}", + "src/Foo.cls"); + + assertSize(report, 1); + } + + @Test + public void testBooleanExpressions() { + Report report = apex.executeRuleOnResource(makeXPath("//BooleanExpression[@Operator='&&']"), + "BooleanExpressions.cls"); + assertSize(report, 1); + } + + +} diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/ast/BooleanExpressions.cls b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/BooleanExpressions.cls similarity index 100% rename from pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/ast/BooleanExpressions.cls rename to pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/BooleanExpressions.cls diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt index 57946ffeb2..de86bd92e9 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt @@ -3,13 +3,12 @@ */ package net.sourceforge.pmd.lang.ast.test -import net.sourceforge.pmd.lang.LanguageRegistry -import net.sourceforge.pmd.lang.LanguageVersion -import net.sourceforge.pmd.lang.LanguageVersionHandler -import net.sourceforge.pmd.lang.ParserOptions +import net.sourceforge.pmd.* +import net.sourceforge.pmd.lang.* import net.sourceforge.pmd.lang.ast.Node import net.sourceforge.pmd.lang.ast.RootNode import org.apache.commons.io.IOUtils +import java.io.File import java.io.InputStream import java.io.StringReader import java.nio.charset.StandardCharsets @@ -54,12 +53,17 @@ abstract class BaseParsingHelper, T : RootNode * defined by the language module). */ fun getVersion(version: String?): LanguageVersion { - val language = LanguageRegistry.getLanguage(langName) + val language = language return if (version == null) language.defaultVersion - else language.getVersion(version) ?: throw AssertionError("Unsupported version $version for language $language") + else language.getVersion(version) + ?: throw AssertionError("Unsupported version $version for language $language") } - val defaultVersion: LanguageVersion + val language: Language + get() = LanguageRegistry.getLanguage(langName) + ?: throw AssertionError("'$langName' is not a supported language (available ${LanguageRegistry.getLanguages()})") + + val defaultVersion: LanguageVersion get() = getVersion(params.defaultVerString) @@ -114,7 +118,7 @@ abstract class BaseParsingHelper, T : RootNode open fun parse( sourceCode: String, version: String? = null, - fileName: String = "src/a/test-file-name.txt" + fileName: String = "src/a/test-file-name.${language.extensions[0]}" ): T { val lversion = if (version == null) defaultVersion else getVersion(version) val handler = lversion.languageVersionHandler @@ -138,7 +142,7 @@ abstract class BaseParsingHelper, T : RootNode */ @JvmOverloads open fun parseResource(resource: String, version: String? = null): T = - parse(readResource(resource), version) + parse(readResource(resource), version, fileName = resource) /** * Fetches the source of the given [clazz]. @@ -176,10 +180,44 @@ abstract class BaseParsingHelper, T : RootNode sourceFile = sourceFile.substring(0, clazz.name.indexOf('$')) + ".java" } val input = javaClass.classLoader.getResourceAsStream(sourceFile) - ?: throw IllegalArgumentException("Unable to find source file $sourceFile for $clazz") + ?: throw IllegalArgumentException("Unable to find source file $sourceFile for $clazz") return consume(input) } + /** + * Execute the given [rule] on the [code]. Produce a report with the violations + * found by the rule. The language version of the piece of code is determined by the [params]. + */ + @JvmOverloads + fun executeRule( + rule: Rule, + code: String, + filename: String = "testfile.${language.extensions[0]}" + ): Report { + val config = PMDConfiguration().apply { + val marker = params.parserOptions?.suppressMarker + if (marker != null) + suppressMarker = marker + } + val processor = SourceCodeProcessor(config) + val ctx = RuleContext() + val report = Report() + ctx.report = report + ctx.sourceCodeFile = File(filename) + ctx.isIgnoreExceptions = false + + val rules = RuleSet.forSingleRule(rule) + try { + processor.processSourceCode(StringReader(code), RuleSets(rules), ctx) + } catch (e: PMDException) { + throw e.cause!! + } + return report + } + + fun executeRuleOnResource(rule: Rule, resourcePath: String): Report = + executeRule(rule, readResource(resourcePath)) + } diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/TestUtils.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/TestUtils.kt index 47dba9b1d4..932fa04b1e 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/TestUtils.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/TestUtils.kt @@ -4,10 +4,15 @@ package net.sourceforge.pmd.lang.ast.test +import io.kotest.matchers.Matcher +import io.kotest.matchers.equalityMatcher import io.kotest.matchers.should +import net.sourceforge.pmd.Report +import net.sourceforge.pmd.RuleViolation +import net.sourceforge.pmd.lang.ast.Node import kotlin.reflect.KCallable import kotlin.reflect.jvm.isAccessible -import io.kotest.matchers.shouldBe as ktShouldBe +import kotlin.test.assertEquals /** * Extension to add the name of a property to error messages. @@ -15,7 +20,12 @@ import io.kotest.matchers.shouldBe as ktShouldBe * @see [shouldBe]. */ infix fun KCallable.shouldEqual(expected: V?) = - assertWrapper(this, expected) { n, v -> n ktShouldBe v } + assertWrapper(this, expected) { n, v -> + // using shouldBe would perform numeric conversion + // eg (3.0 shouldBe 3L) passes, even though (3.0 != 3L) + // equalityMatcher doesn't do this conversion + n.should(equalityMatcher(v) as Matcher) + } private fun assertWrapper(callable: KCallable, right: V, asserter: (N, V) -> Unit) { @@ -55,3 +65,38 @@ infix fun KCallable.shouldBe(expected: V?) = this.shouldEqual(expe infix fun KCallable.shouldMatch(expected: T.() -> Unit) = assertWrapper(this, expected) { n, v -> n should v } + +inline fun Any?.shouldBeA(f: (T) -> Unit = {}): T { + if (this is T) { + f(this) + return this + } else throw AssertionError("Expected an instance of ${T::class.java}, got $this") +} + +operator fun List.component6() = get(5) +operator fun List.component7() = get(6) +operator fun List.component8() = get(7) +operator fun List.component9() = get(8) +operator fun List.component10() = get(9) +operator fun List.component11() = get(10) + + +/** Assert number of violations. */ +fun assertSize(report: Report, size: Int): List { + assertEquals(size, report.violations.size, message = "Wrong number of violations!") + return report.violations +} + +/** Assert number of suppressed violations. */ +fun assertSuppressed(report: Report, size: Int): List { + assertEquals(size, report.suppressedViolations.size, message = "Wrong number of suppressed violations!") + return report.suppressedViolations +} + +/** Checks the coordinates of this node. */ +fun Node.assertPosition(bline: Int, bcol: Int, eline: Int, ecol: Int) { + this::getBeginLine shouldBe bline + this::getBeginColumn shouldBe bcol + this::getEndLine shouldBe eline + this::getEndColumn shouldBe ecol +} From 172c7bec586be33aaa40640f4828529f707b2f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 14:38:31 +0200 Subject: [PATCH 036/104] Also support nested class --- .../sourceforge/pmd/lang/apex/ast/ApexRootNode.java | 4 ++++ .../pmd/lang/apex/ast/ApexParserTest.java | 12 ++++++++++++ .../pmd/lang/apex/ast/ApexParserTestBase.java | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java index be2a1857cc..585cf0f6c4 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java @@ -66,6 +66,10 @@ public abstract class ApexRootNode extends AbstractApexNode parse(String code, String fileName) { + protected ApexNode parse(String code, String fileName) { return apex.parse(code, null, fileName); } From b9d3685b10033198cecd2a07b974362286a4a07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 14:54:26 +0200 Subject: [PATCH 037/104] Fix java test --- .../net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java index 66ad5d08d8..c11e66423e 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java @@ -36,8 +36,8 @@ public class ParserCornersTest { @Test public void testInvalidUnicodeEscape() { expect.expect(TokenMgrError.class); // previously Error - expect.expectMessage("Lexical error in file (no file name provided) at line 1, column 2. Encountered: Invalid unicode escape"); - java.parse("\\u00k0"); + expect.expectMessage("Lexical error in file x/filename.java at line 1, column 2. Encountered: Invalid unicode escape"); + java.parse("\\u00k0", null, "x/filename.java"); } /** From 54dc7562070699b792e5189d47a35862511a934b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 17:05:42 +0200 Subject: [PATCH 038/104] Fix cpp module --- .../pmd/cpd/test/CpdTextComparisonTest.kt | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/cpd/test/CpdTextComparisonTest.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/cpd/test/CpdTextComparisonTest.kt index 3a30d2f036..67fe11f586 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/cpd/test/CpdTextComparisonTest.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/cpd/test/CpdTextComparisonTest.kt @@ -58,10 +58,18 @@ abstract class CpdTextComparisonTest( } @JvmOverloads - fun expectTokenMgrError(source: String, properties: Properties = defaultProperties()): TokenMgrError = - shouldThrow { - newTokenizer(properties).tokenize(sourceCodeOf(source), Tokens()) - } + fun expectTokenMgrError( + source: String, + fileName: String = SourceCode.StringCodeLoader.DEFAULT_NAME, + properties: Properties = defaultProperties() + ): TokenMgrError = + expectTokenMgrError(FileData(fileName, source), properties) + + @JvmOverloads + fun expectTokenMgrError(fileData: FileData, properties: Properties = defaultProperties()): TokenMgrError = + shouldThrow { + newTokenizer(properties).tokenize(sourceCodeOf(fileData), Tokens()) + } private fun StringBuilder.format(tokens: Tokens) { @@ -139,11 +147,13 @@ abstract class CpdTextComparisonTest( fun sourceCodeOf(str: String): SourceCode = SourceCode(SourceCode.StringCodeLoader(str)) + fun sourceCodeOf(fileData: FileData): SourceCode = + SourceCode(SourceCode.StringCodeLoader(fileData.fileText, fileData.fileName)) fun tokenize(tokenizer: Tokenizer, str: String): Tokens = - Tokens().also { - tokenizer.tokenize(sourceCodeOf(str), it) - } + Tokens().also { + tokenizer.tokenize(sourceCodeOf(str), it) + } private companion object { const val Indent = " " From bc2169c087a0710c8c211c76521a29730b6f540f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 18:01:16 +0200 Subject: [PATCH 039/104] Add one more test case for fixed FNs in diff report --- ...lassWithOnlyPrivateConstructorsShouldBeFinal.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml index 805f6a0822..fe66fa1313 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ClassWithOnlyPrivateConstructorsShouldBeFinal.xml @@ -138,6 +138,7 @@ class ClassWithOnlyPrivateConstructorsShouldBeFinal { #2536 [java] ClassWithOnlyPrivateConstructorsShouldBeFinal can't detect inner class with only private constructor 1 + 2 + + Private inner class with no ctor + 1 + 2 + + From 19a4c9cd847d5381d415b546d7327d37a15b6757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 18:07:44 +0200 Subject: [PATCH 040/104] Cleanup performance.xml of deprecated rules --- .ci/files/all-java.xml | 8 - docs/pages/7_0_0_release_notes.md | 8 + .../main/resources/rulesets/releases/38.xml | 2 +- .../resources/rulesets/releases/40rc1.xml | 7 +- .../performance/BooleanInstantiationRule.java | 112 ------- .../UnnecessaryWrapperObjectCreationRule.java | 43 --- .../resources/category/java/performance.xml | 276 ------------------ .../resources/rulesets/java/migrating.xml | 8 +- .../rulesets/java/migrating_to_15.xml | 8 +- .../resources/rulesets/java/optimizations.xml | 6 +- .../resources/rulesets/java/quickstart.xml | 2 - .../performance/AvoidUsingShortTypeTest.java | 11 - .../performance/BooleanInstantiationTest.java | 12 - .../performance/ByteInstantiationTest.java | 11 - .../performance/IntegerInstantiationTest.java | 11 - .../performance/LongInstantiationTest.java | 11 - .../performance/ShortInstantiationTest.java | 11 - .../performance/SimplifyStartsWithTest.java | 11 - .../UnnecessaryWrapperObjectCreationTest.java | 11 - .../performance/xml/AvoidUsingShortType.xml | 144 --------- .../performance/xml/BooleanInstantiation.xml | 163 ----------- .../performance/xml/ByteInstantiation.xml | 30 -- .../performance/xml/IntegerInstantiation.xml | 26 -- .../performance/xml/LongInstantiation.xml | 30 -- .../performance/xml/ShortInstantiation.xml | 30 -- .../performance/xml/SimplifyStartsWith.xml | 90 ------ .../xml/UnnecessaryWrapperObjectCreation.xml | 87 ------ 27 files changed, 23 insertions(+), 1146 deletions(-) delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/BooleanInstantiationRule.java delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UnnecessaryWrapperObjectCreationRule.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/AvoidUsingShortTypeTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/BooleanInstantiationTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/ByteInstantiationTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/IntegerInstantiationTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/LongInstantiationTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/ShortInstantiationTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/SimplifyStartsWithTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UnnecessaryWrapperObjectCreationTest.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidUsingShortType.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/BooleanInstantiation.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/ByteInstantiation.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/IntegerInstantiation.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/LongInstantiation.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/ShortInstantiation.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/SimplifyStartsWith.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UnnecessaryWrapperObjectCreation.xml diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index f4b310ca61..d89d53d893 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -294,25 +294,17 @@ - - - - - - - - diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 2b4c261c86..7fc23c0f1c 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -113,17 +113,25 @@ The following previously deprecated rules have been finally removed: * AbstractNaming (java-codestyle) * AvoidFinalLocalVariable (java-codestyle) * AvoidPrefixingMethodParameters (java-codestyle) +* AvoidUsingShortType (java-performance) +* BooleanInstantiation (java-performance) +* ByteInstantiation (java-performance) * DataflowAnomalyAnalysis (java-errorprone) * ForLoopsMustUseBraces (java-codestyle) * IfElseStmtsMustUseBraces (java-codestyle) * IfStmtsMustUseBraces (java-codestyle) +* IntegerInstantiation (java-performance) * LoggerIsNotStaticFinal (java-errorprone) +* LongInstantiation (java-performance) * MIsLeadingVariableName (java-codestyle) * ModifiedCyclomaticComplexity (java-design) * PositionLiteralsFirstInCaseInsensitiveComparisons (java-bestpractices) * PositionLiteralsFirstInComparisons (java-bestpractices) +* ShortInstantiation (java-performance) +* SimplifyStartsWith (java-performance) * StdCyclomaticComplexity (java-design) * SuspiciousConstantFieldName (java-codestyle) +* UnnecessaryWrapperObjectCreation (java-performance) -> note: the replacement is the new rule {% rule "java/codestyle/UnnecessaryBoxing" %} * UnsynchronizedStaticDateFormatter (java-multithreading) * VariableNamingConventions (apex-codestyle) * VariableNamingConventions (java-codestyle) diff --git a/pmd-core/src/main/resources/rulesets/releases/38.xml b/pmd-core/src/main/resources/rulesets/releases/38.xml index b0528c8caa..9dacc12123 100644 --- a/pmd-core/src/main/resources/rulesets/releases/38.xml +++ b/pmd-core/src/main/resources/rulesets/releases/38.xml @@ -10,7 +10,7 @@ This ruleset contains links to rules that are new in PMD v3.8 - + diff --git a/pmd-core/src/main/resources/rulesets/releases/40rc1.xml b/pmd-core/src/main/resources/rulesets/releases/40rc1.xml index 132f866adf..0ef4736820 100644 --- a/pmd-core/src/main/resources/rulesets/releases/40rc1.xml +++ b/pmd-core/src/main/resources/rulesets/releases/40rc1.xml @@ -8,9 +8,9 @@ This ruleset contains links to rules that are new in PMD v4.0rc1 - - - + + + @@ -26,4 +26,3 @@ This ruleset contains links to rules that are new in PMD v4.0rc1 - \ No newline at end of file diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/BooleanInstantiationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/BooleanInstantiationRule.java deleted file mode 100644 index b8b345c071..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/BooleanInstantiationRule.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.performance; - -import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression; -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.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; -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.rule.AbstractJavaRule; -import net.sourceforge.pmd.lang.java.types.TypeTestUtil; - -/** - * Avoid instantiating Boolean objects; you can reference Boolean.TRUE, - * Boolean.FALSE, or call Boolean.valueOf() instead. - * - *
- *  public class Foo {
- *       Boolean bar = new Boolean("true");    // just do a Boolean
- *       bar = Boolean.TRUE;                   //ok
- *       Boolean buz = Boolean.valueOf(false); // just do a Boolean buz = Boolean.FALSE;
- *  }
- * 
- */ -public class BooleanInstantiationRule extends AbstractJavaRule { - - /* - * see bug 1744065 : If somebody create it owns Boolean, the rule should not - * be triggered Therefore, we use this boolean to flag if the source code - * contains such an import - * - */ - private boolean customBoolean; - - @Override - public Object visit(ASTCompilationUnit decl, Object data) { - // customBoolean needs to be reset for each new file - customBoolean = false; - - return super.visit(decl, data); - } - - @Override - public Object visit(ASTImportDeclaration decl, Object data) { - // If the import actually import a Boolean class that overrides - // java.lang.Boolean - if (decl.getImportedName().endsWith("Boolean") && !"java.lang".equals(decl.getImportedName())) { - customBoolean = true; - } - return super.visit(decl, data); - } - - @Override - public Object visit(ASTAllocationExpression node, Object data) { - - if (!customBoolean) { - if (node.hasDescendantOfType(ASTArrayDimsAndInits.class)) { - return super.visit(node, data); - } - - ASTClassOrInterfaceType n1 = node.getFirstChildOfType(ASTClassOrInterfaceType.class); - if (TypeTestUtil.isA(Boolean.class, n1)) { - super.addViolation(data, node); - return data; - } - } - return super.visit(node, data); - } - - @Override - public Object visit(ASTPrimaryPrefix node, Object data) { - - if (!customBoolean) { - if (node.getNumChildren() == 0 || !(node.getChild(0) instanceof ASTName)) { - return super.visit(node, data); - } - - if ("Boolean.valueOf".equals(((ASTName) node.getChild(0)).getImage()) - || "java.lang.Boolean.valueOf".equals(((ASTName) node.getChild(0)).getImage())) { - ASTPrimaryExpression parent = (ASTPrimaryExpression) node.getParent(); - ASTPrimarySuffix suffix = parent.getFirstDescendantOfType(ASTPrimarySuffix.class); - if (suffix == null) { - return super.visit(node, data); - } - ASTPrimaryPrefix prefix = suffix.getFirstDescendantOfType(ASTPrimaryPrefix.class); - if (prefix == null) { - return super.visit(node, data); - } - - if (prefix.hasDescendantOfType(ASTBooleanLiteral.class)) { - super.addViolation(data, node); - return data; - } - ASTLiteral literal = prefix.getFirstDescendantOfType(ASTLiteral.class); - if (literal != null - && ("\"true\"".equals(literal.getImage()) || "\"false\"".equals(literal.getImage()))) { - super.addViolation(data, node); - return data; - } - } - } - return super.visit(node, data); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UnnecessaryWrapperObjectCreationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UnnecessaryWrapperObjectCreationRule.java deleted file mode 100644 index 41521dda36..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/UnnecessaryWrapperObjectCreationRule.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.performance; - -import static net.sourceforge.pmd.util.CollectionUtil.setOf; - -import java.util.Set; - -import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; -import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.rule.codestyle.UnnecessaryBoxingRule; - -/** - * @deprecated Replaced by {@link UnnecessaryBoxingRule}. - */ -@Deprecated -public class UnnecessaryWrapperObjectCreationRule extends AbstractJavaRulechainRule { - private static final Set SUFFIX_SET = setOf("toString", "byteValue", - "shortValue", "intValue", "longValue", "floatValue", "doubleValue", "charValue", "booleanValue"); - - public UnnecessaryWrapperObjectCreationRule() { - super(ASTMethodCall.class); - } - - @Override - public Object visit(ASTMethodCall node, Object data) { - if (!"valueOf".equals(node.getMethodName()) || node.getQualifier() == null - || !node.getQualifier().getTypeMirror().isBoxedPrimitive() - || !(node.getParent() instanceof ASTMethodCall)) { - return data; - } - - ASTMethodCall nextMethodCall = (ASTMethodCall) node.getParent(); - String methodName = nextMethodCall.getMethodName(); - if (SUFFIX_SET.contains(methodName)) { - addViolation(data, node); - } - - return data; - } -} diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml index f265b4d939..ffe1823903 100644 --- a/pmd-java/src/main/resources/category/java/performance.xml +++ b/pmd-java/src/main/resources/category/java/performance.xml @@ -275,51 +275,6 @@ public class Something {
- - -Note: this rule is deprecated, as its rationale does not hold. - -Java uses the 'short' type to reduce memory usage, not to optimize calculation. In fact, the JVM does not have any -arithmetic capabilities for the short type: the JVM must convert the short into an int, do the proper calculation -and convert the int back to a short. Thus any storage gains found through use of the 'short' type may be offset by -adverse impacts on performance. - - 1 - - - - - - - - - - - - - - -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. - - 2 - - - - - - - -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. - - 2 - - - - - - - - - - - - - - -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. - - 2 - - - - - - - - - - - - - - -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. - - 2 - - - - - - - - - - - - - - -Note: this rule is deprecated for removal, as the optimization is insignificant. - -Calls to `string.startsWith("x")` with a string literal of length 1 can be rewritten using `string.charAt(0)`, -at the expense of some readability. To prevent `IndexOutOfBoundsException` being thrown by the `charAt` method, -ensure that the string is not empty by making an additional check first. - - 3 - - - - - - - - - - - - - - -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. - - 2 - - - - - - - - - - - - - - -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. - - 3 - - - - - - - - - + + + + diff --git a/pmd-java/src/main/resources/rulesets/java/migrating_to_15.xml b/pmd-java/src/main/resources/rulesets/java/migrating_to_15.xml index 58f833176f..a1514ce199 100644 --- a/pmd-java/src/main/resources/rulesets/java/migrating_to_15.xml +++ b/pmd-java/src/main/resources/rulesets/java/migrating_to_15.xml @@ -9,9 +9,9 @@ Contains rules for migrating to JDK 1.5 - - - - + + + + diff --git a/pmd-java/src/main/resources/rulesets/java/optimizations.xml b/pmd-java/src/main/resources/rulesets/java/optimizations.xml index 4439c5385e..ec6d63d4f0 100644 --- a/pmd-java/src/main/resources/rulesets/java/optimizations.xml +++ b/pmd-java/src/main/resources/rulesets/java/optimizations.xml @@ -17,10 +17,10 @@ These rules deal with different optimizations that generally apply to best pract - - + + - \ No newline at end of file + diff --git a/pmd-java/src/main/resources/rulesets/java/quickstart.xml b/pmd-java/src/main/resources/rulesets/java/quickstart.xml index 8c0ed47cc6..3e737e7173 100644 --- a/pmd-java/src/main/resources/rulesets/java/quickstart.xml +++ b/pmd-java/src/main/resources/rulesets/java/quickstart.xml @@ -295,7 +295,6 @@ - @@ -304,7 +303,6 @@ - diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/AvoidUsingShortTypeTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/AvoidUsingShortTypeTest.java deleted file mode 100644 index 5a639a8a74..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/AvoidUsingShortTypeTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.performance; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -public class AvoidUsingShortTypeTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/BooleanInstantiationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/BooleanInstantiationTest.java deleted file mode 100644 index 57510e54c8..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/BooleanInstantiationTest.java +++ /dev/null @@ -1,12 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.performance; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -@org.junit.Ignore("Rule has not been updated yet") -public class BooleanInstantiationTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/ByteInstantiationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/ByteInstantiationTest.java deleted file mode 100644 index 2db2199779..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/ByteInstantiationTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.performance; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -public class ByteInstantiationTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/IntegerInstantiationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/IntegerInstantiationTest.java deleted file mode 100644 index a951c8eda7..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/IntegerInstantiationTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.performance; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -public class IntegerInstantiationTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/LongInstantiationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/LongInstantiationTest.java deleted file mode 100644 index a2b951cb00..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/LongInstantiationTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.performance; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -public class LongInstantiationTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/ShortInstantiationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/ShortInstantiationTest.java deleted file mode 100644 index 564c94b6fd..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/ShortInstantiationTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.performance; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -public class ShortInstantiationTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/SimplifyStartsWithTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/SimplifyStartsWithTest.java deleted file mode 100644 index e2a3fbcd15..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/SimplifyStartsWithTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.performance; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -public class SimplifyStartsWithTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UnnecessaryWrapperObjectCreationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UnnecessaryWrapperObjectCreationTest.java deleted file mode 100644 index 08da381245..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/performance/UnnecessaryWrapperObjectCreationTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.performance; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -public class UnnecessaryWrapperObjectCreationTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidUsingShortType.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidUsingShortType.xml deleted file mode 100644 index 95eecb27da..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/AvoidUsingShortType.xml +++ /dev/null @@ -1,144 +0,0 @@ - - - - - Short as field - 1 - - - - - Short as local variable - 1 - - - - - Short as method return type - 2 - - - - - Short as method return type - 0 - - - - - #1449 false positive when casting a variable to short - 0 - - - - - short as method parameter - 1 - - - - - short as method parameter with @Override - 0 - - - - - [java] AvoidUsingShortType erroneously triggered on overrides of 3rd party methods (anon. class) #586 - 0 - - - - - [java] AvoidUsingShortType erroneously triggered on overrides of 3rd party methods #586 - 0 - - - - - short as annotation property - 1 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/BooleanInstantiation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/BooleanInstantiation.xml deleted file mode 100644 index 4d38c36a64..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/BooleanInstantiation.xml +++ /dev/null @@ -1,163 +0,0 @@ - - - - - simple failure case - 1 - - - - - new java.lang.Boolean - 1 - - - - - ok - 0 - - - - - don't use Boolean.valueOf() with literal - 2 - - - - - valueOf() with variable is fine - 0 - - - - - don't use Boolean.valueOf() with string literal - 1 - - - - - don't use Boolean.valueOf() in method call - 1 - - - - - don't use new Boolean() in method call - 1 - - - - - ok - 0 - - - - - ok - 0 - - - - - don't use new Boolean() in static block - 1 - - - - - Bug 1744065, should be ok - 0 - - - - - Test for failure after rule with custom Boolean, should report failure if rule reset done correctly - 1 - - - - - #1533 [java] BooleanInstantiation: ClassCastException with Annotation - 0 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/ByteInstantiation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/ByteInstantiation.xml deleted file mode 100644 index 2cbd7a2b44..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/ByteInstantiation.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - new Byte(), bad - 1 - - - - - Byte.valueOf(), ok - 0 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/IntegerInstantiation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/IntegerInstantiation.xml deleted file mode 100644 index 208c229141..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/IntegerInstantiation.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - new Integer(), bad - 1 - - - - - Integer.valueOf(), ok - 0 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/LongInstantiation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/LongInstantiation.xml deleted file mode 100644 index 154dc5c2ab..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/LongInstantiation.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - new Long(), bad - 1 - - - - - Long.valueOf(), ok - 0 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/ShortInstantiation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/ShortInstantiation.xml deleted file mode 100644 index 22f52ea6a1..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/ShortInstantiation.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - new Short(), bad - 1 - - - - - Short.valueOf(), ok - 0 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/SimplifyStartsWith.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/SimplifyStartsWith.xml deleted file mode 100644 index 3a67cfa8b9..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/SimplifyStartsWith.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - failure case - 1 - - - - - startsWith multiple chars - 0 - - - - - startsWith defined on some other class, doesn't take a String - 0 - - - - - Document Jaxen exception parsing Unicode chars in startsWith - 0 - - - - - #1392 SimplifyStartsWith false-negative - 1 - 5 - - - - #2712 SimplifyStartsWith false-positive on receiver != String - 0 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UnnecessaryWrapperObjectCreation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UnnecessaryWrapperObjectCreation.xml deleted file mode 100644 index 1ca86628de..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UnnecessaryWrapperObjectCreation.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - failure case - 1 - 3 - - - - - calling valueOf is OK - 0 - - - - - failure case for 1.5+ - 1 - 3 - - - - - Patch 2075906: Add toString() to the rule UnnecessaryWrapperObjectCreation - 1 - 3 - - - - - #1057 False positive for UnnecessaryWrapperObjectCreation - 1 - 3 - - - - - NPE with static method call - 0 - - - From c872cec1d563f936caceba30107822cc4574db3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 18:16:26 +0200 Subject: [PATCH 041/104] Cleanup codestyle.xml of deprecated rules --- .ci/files/all-java.xml | 1 - docs/pages/7_0_0_release_notes.md | 1 + .../main/resources/rulesets/releases/34.xml | 2 +- .../resources/category/java/codestyle.xml | 48 ----- .../resources/rulesets/java/controversial.xml | 2 +- .../resources/rulesets/java/quickstart.xml | 1 - .../rule/codestyle/DefaultPackageTest.java | 11 -- .../rule/codestyle/xml/DefaultPackage.xml | 176 ------------------ 8 files changed, 3 insertions(+), 239 deletions(-) delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/DefaultPackageTest.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/DefaultPackage.xml diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index d89d53d893..39e539c320 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -77,7 +77,6 @@ - diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 7fc23c0f1c..aab4ce8e86 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -117,6 +117,7 @@ The following previously deprecated rules have been finally removed: * BooleanInstantiation (java-performance) * ByteInstantiation (java-performance) * DataflowAnomalyAnalysis (java-errorprone) +* DefaultPackage (java-codestyle) * ForLoopsMustUseBraces (java-codestyle) * IfElseStmtsMustUseBraces (java-codestyle) * IfStmtsMustUseBraces (java-codestyle) diff --git a/pmd-core/src/main/resources/rulesets/releases/34.xml b/pmd-core/src/main/resources/rulesets/releases/34.xml index a3328515ae..6d2924711e 100644 --- a/pmd-core/src/main/resources/rulesets/releases/34.xml +++ b/pmd-core/src/main/resources/rulesets/releases/34.xml @@ -15,7 +15,7 @@ This ruleset contains links to rules that are new in PMD v3.4 - + diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml index 1d010776aa..2aa137c587 100644 --- a/pmd-java/src/main/resources/category/java/codestyle.xml +++ b/pmd-java/src/main/resources/category/java/codestyle.xml @@ -403,54 +403,6 @@ while (true) { // preferred approach
- - -Use explicit scoping instead of accidental usage of default package private level. -The rule allows methods and fields annotated with Guava's @VisibleForTesting and JUnit 5's annotations. - -This rule is deprecated since PMD 6.35.0. It assumes that any usage of package-access is accidental, -and by doing so, prohibits using a really fundamental and useful feature of the language. - -To satisfy the rule, you have to make the member public even if it doesn't need to, or make it protected, -which muddies your intent even more if you don't intend the class to be extended, and may be at odds with -other rules like {% rule "java/codestyle/AvoidProtectedFieldInFinalClass" %}. - -The rule {% rule "java/codestyle/CommentDefaultAccessModifier" %} should be used instead. This rule flags -the same thing, but has an escape hatch. - - 3 - - - - - - - - - - + diff --git a/pmd-java/src/main/resources/rulesets/java/quickstart.xml b/pmd-java/src/main/resources/rulesets/java/quickstart.xml index 3e737e7173..eca04a16fe 100644 --- a/pmd-java/src/main/resources/rulesets/java/quickstart.xml +++ b/pmd-java/src/main/resources/rulesets/java/quickstart.xml @@ -88,7 +88,6 @@ - diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/DefaultPackageTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/DefaultPackageTest.java deleted file mode 100644 index 19c6c714fd..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/DefaultPackageTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 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 DefaultPackageTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/DefaultPackage.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/DefaultPackage.xml deleted file mode 100644 index 5882f7e174..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/DefaultPackage.xml +++ /dev/null @@ -1,176 +0,0 @@ - - - - - ok - 0 - - - - - bad - 1 - - - - - interface methods are always public - 0 - - - - - interface field are always public - 0 - - - - - bad - 1 - - - - - #1410 DefaultPackage triggers on field annotated with @VisibleForTesting - 0 - - - - - #2573 DefaultPackage triggers on field annotated with JUnit 5 @Test - 0 - - - - - #2573 DefaultPackage triggers on field annotated with JUnit 5 @RepeatedTest - 0 - - - - - #2573 DefaultPackage triggers on field annotated with JUnit 5 @ParameterizedTest - 0 - - - - - #2573 DefaultPackage triggers on field annotated with JUnit 5 @TestFactory - 0 - - - - - #2573 DefaultPackage triggers on field annotated with JUnit 5 @TestTemplate - 0 - - - - - #2573 DefaultPackage triggers on field annotated with JUnit 5 @BeforeAll - 0 - - - - - #2573 DefaultPackage triggers on field annotated with JUnit 5 @AfterAll - 0 - - - - - #2573 DefaultPackage triggers on field annotated with JUnit 5 @BeforeEach - 0 - - - - - #2573 DefaultPackage triggers on field annotated with JUnit 5 @AfterEach - 0 - - - From 6b6f7f3445dd54cda3d7e16fc0a8f34f9a57ff80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 18:18:39 +0200 Subject: [PATCH 042/104] Cleanup design.xml of deprecated rules --- .ci/files/all-java.xml | 1 - docs/pages/7_0_0_release_notes.md | 1 + .../main/resources/rulesets/releases/36.xml | 2 +- .../main/resources/category/java/design.xml | 58 ------------ .../main/resources/rulesets/java/junit.xml | 2 +- .../design/SimplifyBooleanAssertionTest.java | 12 --- .../design/xml/SimplifyBooleanAssertion.xml | 93 ------------------- 7 files changed, 3 insertions(+), 166 deletions(-) delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanAssertionTest.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanAssertion.xml diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 39e539c320..312124ab46 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -153,7 +153,6 @@ - diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index aab4ce8e86..0c69d09d5b 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -129,6 +129,7 @@ The following previously deprecated rules have been finally removed: * PositionLiteralsFirstInCaseInsensitiveComparisons (java-bestpractices) * PositionLiteralsFirstInComparisons (java-bestpractices) * ShortInstantiation (java-performance) +* SimplifyBooleanAssertion (java-design) * SimplifyStartsWith (java-performance) * StdCyclomaticComplexity (java-design) * SuspiciousConstantFieldName (java-codestyle) diff --git a/pmd-core/src/main/resources/rulesets/releases/36.xml b/pmd-core/src/main/resources/rulesets/releases/36.xml index 16a32f41f4..8a5cdf594f 100644 --- a/pmd-core/src/main/resources/rulesets/releases/36.xml +++ b/pmd-core/src/main/resources/rulesets/releases/36.xml @@ -11,7 +11,7 @@ This ruleset contains links to rules that are new in PMD v3.6 - + diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index c3c579c464..f07301f0b7 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -1162,64 +1162,6 @@ public class Foo { - - -Avoid negation in an assertTrue or assertFalse test. - -For example, rephrase: - - assertTrue(!expr); - -as: - - assertFalse(expr); - -Deprecated since PMD 6.37.0, use {% rule java/bestpractices/SimplifiableTestAssertion %} instead. - - 3 - - - - - - - - - - - - + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanAssertionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanAssertionTest.java deleted file mode 100644 index 365bb56a0d..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanAssertionTest.java +++ /dev/null @@ -1,12 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -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 SimplifyBooleanAssertionTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanAssertion.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanAssertion.xml deleted file mode 100644 index c14e64f8d3..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifyBooleanAssertion.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - assertFalse(!) - 1 - - - - - assertTrue(!) - 1 - - - - - ok - 0 - - - - - not a JUnit test - assertFalse(!) - 0 - - - - - JUnit 4 - assertFalse(!) - 1 - - - - - JUnit 5 - assertFalse(!) - 1 - - - From f3759d0da093aaf403804a43a920cfa4e1a8b8eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 18:20:35 +0200 Subject: [PATCH 043/104] Cleanup bestpractices.xml of deprecated rules --- .ci/files/all-java.xml | 4 - docs/pages/7_0_0_release_notes.md | 4 + .../main/resources/rulesets/releases/35.xml | 2 +- .../main/resources/rulesets/releases/50.xml | 2 +- .../resources/category/java/bestpractices.xml | 175 ------------------ .../main/resources/rulesets/java/junit.xml | 8 +- ...seAssertEqualsInsteadOfAssertTrueTest.java | 11 -- .../UseAssertNullInsteadOfAssertTrueTest.java | 11 -- .../UseAssertSameInsteadOfAssertTrueTest.java | 11 -- ...seAssertTrueInsteadOfAssertEqualsTest.java | 11 -- .../UseAssertEqualsInsteadOfAssertTrue.xml | 99 ---------- .../xml/UseAssertNullInsteadOfAssertTrue.xml | 92 --------- .../xml/UseAssertSameInsteadOfAssertTrue.xml | 127 ------------- .../UseAssertTrueInsteadOfAssertEquals.xml | 96 ---------- 14 files changed, 10 insertions(+), 643 deletions(-) delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertEqualsInsteadOfAssertTrueTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertNullInsteadOfAssertTrueTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertSameInsteadOfAssertTrueTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertTrueInsteadOfAssertEqualsTest.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertTrueInsteadOfAssertEquals.xml diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index 312124ab46..d80e5a14ec 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -54,10 +54,6 @@ - - - - diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 0c69d09d5b..9b931dab3c 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -135,6 +135,10 @@ The following previously deprecated rules have been finally removed: * SuspiciousConstantFieldName (java-codestyle) * UnnecessaryWrapperObjectCreation (java-performance) -> note: the replacement is the new rule {% rule "java/codestyle/UnnecessaryBoxing" %} * UnsynchronizedStaticDateFormatter (java-multithreading) +* UseAssertEqualsInsteadOfAssertTrue (java-bestpractices) +* UseAssertNullInsteadOfAssertEquals (java-bestpractices) +* UseAssertSameInsteadOfAssertEquals (java-bestpractices) +* UseAssertTrueInsteadOfAssertEquals (java-bestpractices) * VariableNamingConventions (apex-codestyle) * VariableNamingConventions (java-codestyle) * WhileLoopsMustUseBraces (java-codestyle) diff --git a/pmd-core/src/main/resources/rulesets/releases/35.xml b/pmd-core/src/main/resources/rulesets/releases/35.xml index 7753b454c6..f0cfde5318 100644 --- a/pmd-core/src/main/resources/rulesets/releases/35.xml +++ b/pmd-core/src/main/resources/rulesets/releases/35.xml @@ -18,7 +18,7 @@ This ruleset contains links to rules that are new in PMD v3.5 - + diff --git a/pmd-core/src/main/resources/rulesets/releases/50.xml b/pmd-core/src/main/resources/rulesets/releases/50.xml index d612ceac00..7406926431 100644 --- a/pmd-core/src/main/resources/rulesets/releases/50.xml +++ b/pmd-core/src/main/resources/rulesets/releases/50.xml @@ -38,7 +38,7 @@ This ruleset contains links to rules that are new in PMD v5.0 - + diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index e3a667f011..3a2e29b77a 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -1326,11 +1326,6 @@ public class Foo { 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 %}. 3 @@ -1647,176 +1642,6 @@ public class Something { - - -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. - - 3 - - - - - - - - - - - - - - -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. - - 3 - - - - - - - - - - - - - - -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. - - 3 - - - - - - - - - - - - - - -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. - - 3 - - - - - - - - - - - - - - - - + + + + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertEqualsInsteadOfAssertTrueTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertEqualsInsteadOfAssertTrueTest.java deleted file mode 100644 index 4df42d6789..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertEqualsInsteadOfAssertTrueTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 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; - -public class UseAssertEqualsInsteadOfAssertTrueTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertNullInsteadOfAssertTrueTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertNullInsteadOfAssertTrueTest.java deleted file mode 100644 index a593a9e0ff..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertNullInsteadOfAssertTrueTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 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; - -public class UseAssertNullInsteadOfAssertTrueTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertSameInsteadOfAssertTrueTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertSameInsteadOfAssertTrueTest.java deleted file mode 100644 index e874a309b1..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertSameInsteadOfAssertTrueTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 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; - -public class UseAssertSameInsteadOfAssertTrueTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertTrueInsteadOfAssertEqualsTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertTrueInsteadOfAssertEqualsTest.java deleted file mode 100644 index cb8ded71bf..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseAssertTrueInsteadOfAssertEqualsTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 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; - -public class UseAssertTrueInsteadOfAssertEqualsTest extends PmdRuleTst { - // no additional unit tests -} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml deleted file mode 100644 index b604960de4..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertEqualsInsteadOfAssertTrue.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - Identity test doesn't match - 0 - - - - - Junit 3 problem - 1 - - - - - Overload of equal doesn't match - 0 - - - - - JUnit 4, even outside of @Test method - 1 - - - - - JUnit4 - match - 1 - - - - - JUnit5 - @Test - 1 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml deleted file mode 100644 index fdd79d4e26..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertNullInsteadOfAssertTrue.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - assertTrue with null - 1 - - - - - assertFalse with != null - 1 - - - - - assertTrue with x == y - 0 - - - - - Not a JUnit test - assertTrue with null - 0 - - - - - JUnit 4 - assertTrue with null - 1 - - - - - JUnit 5 - assertTrue with null - @Test - 1 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml deleted file mode 100644 index 5a0a74559e..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertSameInsteadOfAssertTrue.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - assert true a == b - 1 - - - - - assert true a != b - 1 - - - - - assert false a == b - 1 - - - - - assert false a != b - 1 - - - - - skip assertTrue(x == null), UseAssertNullInsteadOfAssertTrue will pick those up - 0 - - - - - bug 1626715, the null check in the rule shouldn't match the null outside the assert method - 1 - - - - - assert true a == b BUT not a Junit test - 0 - - - - - JUnit 4 - assert true a == b - 1 - - - - - JUnit 5 - assert true a == b - @Test - 1 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertTrueInsteadOfAssertEquals.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertTrueInsteadOfAssertEquals.xml deleted file mode 100644 index 13358b5119..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseAssertTrueInsteadOfAssertEquals.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - JUnit Test contains assertEquals on other than boolean literal - 0 - - - - - JUnit Test contains assertEquals on boolean literal - 5 - - - - - #1323 False positive case of UseAssertTrueInsteadOfAssertEquals - 0 - - - - - JUnit Test contains assertEquals with Boxed booleans - 8 - - - - - JUnit Test contains assertEquals with Boxed booleans as param - 0 - - - From 02cb1f5725cff5f44918f326bcc9cb57072efd96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 18:28:40 +0200 Subject: [PATCH 044/104] Cleanup errorprone.xml of deprecated rules --- docs/pages/7_0_0_release_notes.md | 5 + .../resources/category/java/errorprone.xml | 103 ------------------ ...eThrowsCloneNotSupportedExceptionTest.java | 12 -- .../ReturnEmptyArrayRatherThanNullTest.java | 12 -- .../CloneThrowsCloneNotSupportedException.xml | 51 --------- .../xml/ReturnEmptyArrayRatherThanNull.xml | 36 ------ 6 files changed, 5 insertions(+), 214 deletions(-) delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloneThrowsCloneNotSupportedExceptionTest.java delete mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/ReturnEmptyArrayRatherThanNullTest.java delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/CloneThrowsCloneNotSupportedException.xml delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ReturnEmptyArrayRatherThanNull.xml diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 9b931dab3c..c5a76d6c0c 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -114,20 +114,25 @@ The following previously deprecated rules have been finally removed: * AvoidFinalLocalVariable (java-codestyle) * AvoidPrefixingMethodParameters (java-codestyle) * AvoidUsingShortType (java-performance) +* BadComparison (java-errorprone) -> use {% rule "java/errorprone/ComparisonWithNaN" %} * BooleanInstantiation (java-performance) * ByteInstantiation (java-performance) +* CloneThrowsCloneNotSupportedException (java-errorprone) -> not replaced * DataflowAnomalyAnalysis (java-errorprone) * DefaultPackage (java-codestyle) * ForLoopsMustUseBraces (java-codestyle) * IfElseStmtsMustUseBraces (java-codestyle) * IfStmtsMustUseBraces (java-codestyle) * IntegerInstantiation (java-performance) +* InvalidSlf4jMessageFormat (java-errorprone) -> use {% rule "java/errorprone/InvalidLogMessageFormat" %} * LoggerIsNotStaticFinal (java-errorprone) * LongInstantiation (java-performance) * MIsLeadingVariableName (java-codestyle) +* MissingBreakInSwitch (java-errorprone) -> use {% rule "java/errorprone/ImplicitSwitchFallThrough" %} * ModifiedCyclomaticComplexity (java-design) * PositionLiteralsFirstInCaseInsensitiveComparisons (java-bestpractices) * PositionLiteralsFirstInComparisons (java-bestpractices) +* ReturnEmptyArrayRatherThanNull (java-errorprone) -> use {% rule "java/errorprone/ReturnEmptyCollectionRatherThanNull" %} * ShortInstantiation (java-performance) * SimplifyBooleanAssertion (java-design) * SimplifyStartsWith (java-performance) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 8127f04f2b..225be238ef 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -637,8 +637,6 @@ k = i * j; // set k with 80 not 120 - - - - -The method clone() should throw a CloneNotSupportedException. - -This rule is deprecated since PMD 6.35.0 without replacement. The rule has no real value as -`CloneNotSupportedException` is a checked exception and therefore you need to deal with it while -implementing the `clone()` method. You either need to declare the exception or catch it. If you catch it, -then subclasses can't throw it themselves explicitly. However, `Object.clone()` will still throw this -exception if the `Cloneable` interface is not implemented. - - 3 - - - - - - - - - - - - - - - - - - -For any method that returns an array, it is a better to return an empty array rather than a -null reference. This removes the need for null checking all results and avoids inadvertent -NullPointerExceptions. - -Deprecated since PMD 6.37.0, use {% rule java/errorprone/ReturnEmptyCollectionRatherThanNull %} instead. - - 1 - - - - - - - - - - - - - - - - ok, throws CloneNotSupportedException - 0 - - - - - bad - 1 - - - - - final class, rule does not apply - 0 - - - - - testing with multiple methods - 1 - - - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ReturnEmptyArrayRatherThanNull.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ReturnEmptyArrayRatherThanNull.xml deleted file mode 100644 index dbdbc79bb5..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ReturnEmptyArrayRatherThanNull.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - Basic test case - 1 - - - - - good behavior should not trigger violation - 0 - - - From d06fce15e54a2990c33752a7d0d57605542ed8c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 18:38:08 +0200 Subject: [PATCH 045/104] Add replacements in release notes --- docs/pages/7_0_0_release_notes.md | 56 +++++++++++++++---------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index c5a76d6c0c..2ebe8ef274 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -110,43 +110,43 @@ conversions that may be made implicit. The following previously deprecated rules have been finally removed: -* AbstractNaming (java-codestyle) -* AvoidFinalLocalVariable (java-codestyle) -* AvoidPrefixingMethodParameters (java-codestyle) -* AvoidUsingShortType (java-performance) +* AbstractNaming (java-codestyle) -> use {% rule 'java/codestyle/ClassNamingConventions' %} +* AvoidFinalLocalVariable (java-codestyle) -> not replaced +* AvoidPrefixingMethodParameters (java-codestyle) -> use {% rule 'java/codestyle/FormalParameterNamingConventions' %} +* AvoidUsingShortType (java-performance) -> not replaced * BadComparison (java-errorprone) -> use {% rule "java/errorprone/ComparisonWithNaN" %} -* BooleanInstantiation (java-performance) -* ByteInstantiation (java-performance) +* BooleanInstantiation (java-performance) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} +* ByteInstantiation (java-performance) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} * CloneThrowsCloneNotSupportedException (java-errorprone) -> not replaced -* DataflowAnomalyAnalysis (java-errorprone) -* DefaultPackage (java-codestyle) -* ForLoopsMustUseBraces (java-codestyle) -* IfElseStmtsMustUseBraces (java-codestyle) -* IfStmtsMustUseBraces (java-codestyle) -* IntegerInstantiation (java-performance) +* DataflowAnomalyAnalysis (java-errorprone) -> not replaced +* DefaultPackage (java-codestyle) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} +* ForLoopsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} +* IfElseStmtsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} +* IfStmtsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} +* IntegerInstantiation (java-performance) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} * InvalidSlf4jMessageFormat (java-errorprone) -> use {% rule "java/errorprone/InvalidLogMessageFormat" %} * LoggerIsNotStaticFinal (java-errorprone) -* LongInstantiation (java-performance) -* MIsLeadingVariableName (java-codestyle) +* LongInstantiation (java-performance) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} +* MIsLeadingVariableName (java-codestyle) -> use {% rule 'java/codestyle/FieldNamingConventions' %} * MissingBreakInSwitch (java-errorprone) -> use {% rule "java/errorprone/ImplicitSwitchFallThrough" %} -* ModifiedCyclomaticComplexity (java-design) -* PositionLiteralsFirstInCaseInsensitiveComparisons (java-bestpractices) -* PositionLiteralsFirstInComparisons (java-bestpractices) +* ModifiedCyclomaticComplexity (java-design) -> use {% rule 'java/design/CyclomaticComplexity' %} +* PositionLiteralsFirstInCaseInsensitiveComparisons (java-bestpractices) -> use {% rule 'java/bestpractices/LiteralsFirstInComparisons' %} +* PositionLiteralsFirstInComparisons (java-bestpractices) -> use {% rule 'java/bestpractices/LiteralsFirstInComparisons' %} * ReturnEmptyArrayRatherThanNull (java-errorprone) -> use {% rule "java/errorprone/ReturnEmptyCollectionRatherThanNull" %} -* ShortInstantiation (java-performance) -* SimplifyBooleanAssertion (java-design) -* SimplifyStartsWith (java-performance) -* StdCyclomaticComplexity (java-design) +* ShortInstantiation (java-performance) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} +* SimplifyBooleanAssertion (java-design) -> use {% rule 'java/bestpractices/SimplifiableTestAssertion' %} +* SimplifyStartsWith (java-performance) -> not replaced +* StdCyclomaticComplexity (java-design) -> use {% rule 'java/design/CyclomaticComplexity' %} * SuspiciousConstantFieldName (java-codestyle) -* UnnecessaryWrapperObjectCreation (java-performance) -> note: the replacement is the new rule {% rule "java/codestyle/UnnecessaryBoxing" %} +* UnnecessaryWrapperObjectCreation (java-performance) -> use the new rule {% rule "java/codestyle/UnnecessaryBoxing" %} * UnsynchronizedStaticDateFormatter (java-multithreading) -* UseAssertEqualsInsteadOfAssertTrue (java-bestpractices) -* UseAssertNullInsteadOfAssertEquals (java-bestpractices) -* UseAssertSameInsteadOfAssertEquals (java-bestpractices) -* UseAssertTrueInsteadOfAssertEquals (java-bestpractices) +* UseAssertEqualsInsteadOfAssertTrue (java-bestpractices) -> use {% rule 'java/bestpractices/SimplifiableTestAssertion' %} +* UseAssertNullInsteadOfAssertEquals (java-bestpractices) -> use {% rule 'java/bestpractices/SimplifiableTestAssertion' %} +* UseAssertSameInsteadOfAssertEquals (java-bestpractices) -> use {% rule 'java/bestpractices/SimplifiableTestAssertion' %} +* UseAssertTrueInsteadOfAssertEquals (java-bestpractices) -> use {% rule 'java/bestpractices/SimplifiableTestAssertion' %} * VariableNamingConventions (apex-codestyle) -* VariableNamingConventions (java-codestyle) -* WhileLoopsMustUseBraces (java-codestyle) +* VariableNamingConventions (java-codestyle) -> use {% rule 'java/codestyle/FieldNamingConventions' %} and such +* WhileLoopsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} ### Fixed Issues From b0832dba821ae1c98241ba8ddf76b0fa4c7801d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 18:43:04 +0200 Subject: [PATCH 046/104] Cleanups --- .ci/files/all-java.xml | 1 - docs/pages/7_0_0_release_notes.md | 1 + pmd-core/src/main/resources/rulesets/releases/550.xml | 2 +- pmd-java/src/main/resources/rulesets/java/logging-java.xml | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index d80e5a14ec..901653482e 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -204,7 +204,6 @@ - diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 2ebe8ef274..3d069a7a1a 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -120,6 +120,7 @@ The following previously deprecated rules have been finally removed: * CloneThrowsCloneNotSupportedException (java-errorprone) -> not replaced * DataflowAnomalyAnalysis (java-errorprone) -> not replaced * DefaultPackage (java-codestyle) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} +* DoNotCallSystemExit (java-errorprone) -> use {% rule 'java/errorprone/DoNotTerminateVM' %} * ForLoopsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} * IfElseStmtsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} * IfStmtsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} diff --git a/pmd-core/src/main/resources/rulesets/releases/550.xml b/pmd-core/src/main/resources/rulesets/releases/550.xml index 5fb17c056b..82a29edb22 100644 --- a/pmd-core/src/main/resources/rulesets/releases/550.xml +++ b/pmd-core/src/main/resources/rulesets/releases/550.xml @@ -9,7 +9,7 @@ This ruleset contains links to rules that are new in PMD v5.5.0 - + diff --git a/pmd-java/src/main/resources/rulesets/java/logging-java.xml b/pmd-java/src/main/resources/rulesets/java/logging-java.xml index e4882f5f14..65858b65d8 100644 --- a/pmd-java/src/main/resources/rulesets/java/logging-java.xml +++ b/pmd-java/src/main/resources/rulesets/java/logging-java.xml @@ -10,7 +10,7 @@ The Java Logging ruleset contains a collection of rules that find questionable u - + From f6093dec0e0542e59d5ffec867481c9b1ca8416f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 18:43:04 +0200 Subject: [PATCH 047/104] Cleanups --- docs/pages/7_0_0_release_notes.md | 50 +++++++++---------- docs/pages/next_major_development.md | 12 ++--- .../main/resources/rulesets/releases/35.xml | 2 +- .../main/resources/rulesets/releases/41.xml | 2 +- .../main/resources/rulesets/java/basic.xml | 2 +- .../resources/rulesets/java/controversial.xml | 2 +- 6 files changed, 34 insertions(+), 36 deletions(-) diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 3d069a7a1a..c008de8d17 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -103,51 +103,49 @@ conversions that may be made implicit. #### Deprecated Rules -* {% rule "java/performance/UnnecessaryWrapperObjectCreation" %} has been deprecated. - It is replaced by the more general rule {% rule java/codestyle/UnnecessaryBoxing %}. #### Removed Rules The following previously deprecated rules have been finally removed: -* AbstractNaming (java-codestyle) -> use {% rule 'java/codestyle/ClassNamingConventions' %} +* AbstractNaming (java-codestyle) -> use {% rule "java/codestyle/ClassNamingConventions" %} * AvoidFinalLocalVariable (java-codestyle) -> not replaced -* AvoidPrefixingMethodParameters (java-codestyle) -> use {% rule 'java/codestyle/FormalParameterNamingConventions' %} +* AvoidPrefixingMethodParameters (java-codestyle) -> use {% rule "java/codestyle/FormalParameterNamingConventions" %} * AvoidUsingShortType (java-performance) -> not replaced * BadComparison (java-errorprone) -> use {% rule "java/errorprone/ComparisonWithNaN" %} -* BooleanInstantiation (java-performance) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} -* ByteInstantiation (java-performance) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} +* BooleanInstantiation (java-performance) -> use {% rule "java/codestyle/UnnecessaryBoxing" %} and {% rule "java/bestpractices/PrimitiveWrapperInstantiation" %} +* ByteInstantiation (java-performance) -> use {% rule "java/codestyle/UnnecessaryBoxing" %} and {% rule "java/bestpractices/PrimitiveWrapperInstantiation" %} * CloneThrowsCloneNotSupportedException (java-errorprone) -> not replaced * DataflowAnomalyAnalysis (java-errorprone) -> not replaced -* DefaultPackage (java-codestyle) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} -* DoNotCallSystemExit (java-errorprone) -> use {% rule 'java/errorprone/DoNotTerminateVM' %} -* ForLoopsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} -* IfElseStmtsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} -* IfStmtsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} -* IntegerInstantiation (java-performance) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} +* DefaultPackage (java-codestyle) -> use {% rule "java/codestyle/CommentDefaultAccessModifier" %} +* DoNotCallSystemExit (java-errorprone) -> use {% rule "java/errorprone/DoNotTerminateVM" %} +* ForLoopsMustUseBraces (java-codestyle) -> use {% rule "java/codestyle/ControlStatementBraces" %} +* IfElseStmtsMustUseBraces (java-codestyle) -> use {% rule "java/codestyle/ControlStatementBraces" %} +* IfStmtsMustUseBraces (java-codestyle) -> use {% rule "java/codestyle/ControlStatementBraces" %} +* IntegerInstantiation (java-performance) -> use {% rule "java/codestyle/UnnecessaryBoxing" %} and {% rule "java/bestpractices/PrimitiveWrapperInstantiation" %} * InvalidSlf4jMessageFormat (java-errorprone) -> use {% rule "java/errorprone/InvalidLogMessageFormat" %} * LoggerIsNotStaticFinal (java-errorprone) -* LongInstantiation (java-performance) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} -* MIsLeadingVariableName (java-codestyle) -> use {% rule 'java/codestyle/FieldNamingConventions' %} +* LongInstantiation (java-performance) -> use {% rule "java/codestyle/UnnecessaryBoxing" %} and {% rule "java/bestpractices/PrimitiveWrapperInstantiation" %} +* MIsLeadingVariableName (java-codestyle) -> use {% rule "java/codestyle/FieldNamingConventions" %} * MissingBreakInSwitch (java-errorprone) -> use {% rule "java/errorprone/ImplicitSwitchFallThrough" %} -* ModifiedCyclomaticComplexity (java-design) -> use {% rule 'java/design/CyclomaticComplexity' %} -* PositionLiteralsFirstInCaseInsensitiveComparisons (java-bestpractices) -> use {% rule 'java/bestpractices/LiteralsFirstInComparisons' %} -* PositionLiteralsFirstInComparisons (java-bestpractices) -> use {% rule 'java/bestpractices/LiteralsFirstInComparisons' %} +* ModifiedCyclomaticComplexity (java-design) -> use {% rule "java/design/CyclomaticComplexity" %} +* PositionLiteralsFirstInCaseInsensitiveComparisons (java-bestpractices) -> use {% rule "java/bestpractices/LiteralsFirstInComparisons" %} +* PositionLiteralsFirstInComparisons (java-bestpractices) -> use {% rule "java/bestpractices/LiteralsFirstInComparisons" %} * ReturnEmptyArrayRatherThanNull (java-errorprone) -> use {% rule "java/errorprone/ReturnEmptyCollectionRatherThanNull" %} -* ShortInstantiation (java-performance) -> use {% rule 'java/codestyle/UnnecessaryBoxing' %} and {% rule 'java/bestpractices/PrimitiveWrapperInstantiation' %} -* SimplifyBooleanAssertion (java-design) -> use {% rule 'java/bestpractices/SimplifiableTestAssertion' %} +* ShortInstantiation (java-performance) -> use {% rule "java/codestyle/UnnecessaryBoxing" %} and {% rule "java/bestpractices/PrimitiveWrapperInstantiation" %} +* SimplifyBooleanAssertion (java-design) -> use {% rule "java/bestpractices/SimplifiableTestAssertion" %} * SimplifyStartsWith (java-performance) -> not replaced -* StdCyclomaticComplexity (java-design) -> use {% rule 'java/design/CyclomaticComplexity' %} +* StdCyclomaticComplexity (java-design) -> use {% rule "java/design/CyclomaticComplexity" %} * SuspiciousConstantFieldName (java-codestyle) * UnnecessaryWrapperObjectCreation (java-performance) -> use the new rule {% rule "java/codestyle/UnnecessaryBoxing" %} * UnsynchronizedStaticDateFormatter (java-multithreading) -* UseAssertEqualsInsteadOfAssertTrue (java-bestpractices) -> use {% rule 'java/bestpractices/SimplifiableTestAssertion' %} -* UseAssertNullInsteadOfAssertEquals (java-bestpractices) -> use {% rule 'java/bestpractices/SimplifiableTestAssertion' %} -* UseAssertSameInsteadOfAssertEquals (java-bestpractices) -> use {% rule 'java/bestpractices/SimplifiableTestAssertion' %} -* UseAssertTrueInsteadOfAssertEquals (java-bestpractices) -> use {% rule 'java/bestpractices/SimplifiableTestAssertion' %} +* UseAssertEqualsInsteadOfAssertTrue (java-bestpractices) -> use {% rule "java/bestpractices/SimplifiableTestAssertion" %} +* UseAssertNullInsteadOfAssertEquals (java-bestpractices) -> use {% rule "java/bestpractices/SimplifiableTestAssertion" %} +* UseAssertSameInsteadOfAssertEquals (java-bestpractices) -> use {% rule "java/bestpractices/SimplifiableTestAssertion" %} +* UseAssertTrueInsteadOfAssertEquals (java-bestpractices) -> use {% rule "java/bestpractices/SimplifiableTestAssertion" %} * VariableNamingConventions (apex-codestyle) -* VariableNamingConventions (java-codestyle) -> use {% rule 'java/codestyle/FieldNamingConventions' %} and such -* WhileLoopsMustUseBraces (java-codestyle) -> use {% rule 'java/codestyle/ControlStatementBraces' %} +* VariableNamingConventions (java-codestyle) -> use {% rule "java/codestyle/FieldNamingConventions" %} and such +* WhileLoopsMustUseBraces (java-codestyle) -> use {% rule "java/codestyle/ControlStatementBraces" %} ### Fixed Issues diff --git a/docs/pages/next_major_development.md b/docs/pages/next_major_development.md index a6dc241374..e259e6545a 100644 --- a/docs/pages/next_major_development.md +++ b/docs/pages/next_major_development.md @@ -1374,13 +1374,13 @@ large projects, with many duplications, it was causing `OutOfMemoryError`s (see * 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 %} + * java/performance/BooleanInstantiation + * java/performance/ByteInstantiation + * java/performance/IntegerInstantiation + * java/performance/LongInstantiation + * java/performance/ShortInstantiation -* The Java rule {% rule java/performance/UnnecessaryWrapperObjectCreation %} is deprecated +* The Java 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 diff --git a/pmd-core/src/main/resources/rulesets/releases/35.xml b/pmd-core/src/main/resources/rulesets/releases/35.xml index f0cfde5318..debffe92c2 100644 --- a/pmd-core/src/main/resources/rulesets/releases/35.xml +++ b/pmd-core/src/main/resources/rulesets/releases/35.xml @@ -16,7 +16,7 @@ This ruleset contains links to rules that are new in PMD v3.5 - + diff --git a/pmd-core/src/main/resources/rulesets/releases/41.xml b/pmd-core/src/main/resources/rulesets/releases/41.xml index 031efb5aee..cbd7252332 100644 --- a/pmd-core/src/main/resources/rulesets/releases/41.xml +++ b/pmd-core/src/main/resources/rulesets/releases/41.xml @@ -13,7 +13,7 @@ This ruleset contains links to rules that are new in PMD v4.1 - + diff --git a/pmd-java/src/main/resources/rulesets/java/basic.xml b/pmd-java/src/main/resources/rulesets/java/basic.xml index f7a216f9fd..c28c9cf770 100644 --- a/pmd-java/src/main/resources/rulesets/java/basic.xml +++ b/pmd-java/src/main/resources/rulesets/java/basic.xml @@ -34,7 +34,7 @@ The Basic ruleset contains a collection of good practices which should be follow - + diff --git a/pmd-java/src/main/resources/rulesets/java/controversial.xml b/pmd-java/src/main/resources/rulesets/java/controversial.xml index 70c9c96f53..1efb0be7c9 100644 --- a/pmd-java/src/main/resources/rulesets/java/controversial.xml +++ b/pmd-java/src/main/resources/rulesets/java/controversial.xml @@ -33,7 +33,7 @@ They are held here to allow people to include them as they see fit within their - + From 3bdb28044e87f5764e3a781e9a9e92b517c9bbe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 Aug 2021 21:33:00 +0200 Subject: [PATCH 048/104] Fix remaining references --- pmd-core/src/main/resources/rulesets/releases/42.xml | 2 +- pmd-java/src/main/resources/rulesets/java/clone.xml | 4 ++-- pmd-java/src/main/resources/rulesets/java/design.xml | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pmd-core/src/main/resources/rulesets/releases/42.xml b/pmd-core/src/main/resources/rulesets/releases/42.xml index 01fe98bc02..aa5f42de36 100644 --- a/pmd-core/src/main/resources/rulesets/releases/42.xml +++ b/pmd-core/src/main/resources/rulesets/releases/42.xml @@ -11,7 +11,7 @@ This ruleset contains links to rules that are new in PMD v4.2 - + diff --git a/pmd-java/src/main/resources/rulesets/java/clone.xml b/pmd-java/src/main/resources/rulesets/java/clone.xml index f662ff5473..ec7dc50558 100644 --- a/pmd-java/src/main/resources/rulesets/java/clone.xml +++ b/pmd-java/src/main/resources/rulesets/java/clone.xml @@ -12,7 +12,7 @@ The Clone Implementation ruleset contains a collection of rules that find questi - + - \ No newline at end of file + diff --git a/pmd-java/src/main/resources/rulesets/java/design.xml b/pmd-java/src/main/resources/rulesets/java/design.xml index 9ac4ae2fda..e2bde4ae93 100644 --- a/pmd-java/src/main/resources/rulesets/java/design.xml +++ b/pmd-java/src/main/resources/rulesets/java/design.xml @@ -28,18 +28,18 @@ are suggested. - + - + - + From 064c1d7aefa5b32a4ea9766eb40a5c3e064b05cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 8 Aug 2021 14:29:20 +0200 Subject: [PATCH 049/104] Store file name in data key --- .../java/net/sourceforge/pmd/SourceCodeProcessor.java | 3 ++- .../net/sourceforge/pmd/benchmark/Benchmarker.java | 3 ++- .../java/net/sourceforge/pmd/lang/AbstractParser.java | 10 ++++++++++ .../java/net/sourceforge/pmd/lang/ast/RootNode.java | 7 +++++++ .../net/sourceforge/pmd/util/designer/Designer.java | 4 +++- .../sourceforge/pmd/util/treeexport/TreeExportCli.java | 3 ++- .../pmd/lang/modelica/ast/ModelicaCoordsTest.kt | 9 +++------ .../sourceforge/pmd/lang/scala/ast/ScalaTreeTests.kt | 7 ++----- 8 files changed, 31 insertions(+), 15 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java index f1cb72de65..7d1838c297 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/SourceCodeProcessor.java @@ -17,6 +17,7 @@ import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.benchmark.TimeTracker; import net.sourceforge.pmd.benchmark.TimedOperation; import net.sourceforge.pmd.benchmark.TimedOperationCategory; +import net.sourceforge.pmd.lang.AbstractParser; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.LanguageVersionHandler; @@ -132,7 +133,7 @@ public class SourceCodeProcessor { private Node parse(RuleContext ctx, Reader sourceCode, Parser parser) { try (TimedOperation to = TimeTracker.startOperation(TimedOperationCategory.PARSER)) { - Node rootNode = parser.parse(String.valueOf(ctx.getSourceCodeFile()), sourceCode); + Node rootNode = AbstractParser.doParse(parser, String.valueOf(ctx.getSourceCodeFile()), sourceCode); ctx.getReport().suppress(parser.getSuppressMap()); return rootNode; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java b/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java index af56e1d1e0..326d3898bf 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java @@ -29,6 +29,7 @@ import net.sourceforge.pmd.RuleSetNotFoundException; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.SourceCodeProcessor; +import net.sourceforge.pmd.lang.AbstractParser; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageFilenameFilter; import net.sourceforge.pmd.lang.LanguageRegistry; @@ -147,7 +148,7 @@ public final class Benchmarker { for (DataSource ds : dataSources) { try (DataSource dataSource = ds; InputStreamReader reader = new InputStreamReader(dataSource.getInputStream())) { - parser.parse(dataSource.getNiceFileName(false, null), reader); + AbstractParser.doParse(parser, dataSource.getNiceFileName(false, null), reader); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/AbstractParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/AbstractParser.java index edd6552f81..fa8954d020 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/AbstractParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/AbstractParser.java @@ -6,6 +6,9 @@ package net.sourceforge.pmd.lang; import java.io.Reader; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.RootNode; + /** * This is a generic implementation of the Parser interface. * @@ -34,4 +37,11 @@ public abstract class AbstractParser implements Parser { } protected abstract TokenManager createTokenManager(Reader source); + + @Deprecated + public static Node doParse(Parser parser, String fileName, Reader source) { + Node rootNode = parser.parse(fileName, source); + rootNode.getUserMap().set(RootNode.FILE_NAME_KEY, fileName); + return rootNode; + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/RootNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/RootNode.java index 16705ace77..68556ca753 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/RootNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/RootNode.java @@ -4,9 +4,16 @@ package net.sourceforge.pmd.lang.ast; +import net.sourceforge.pmd.annotation.Experimental; +import net.sourceforge.pmd.util.DataMap; +import net.sourceforge.pmd.util.DataMap.SimpleDataKey; + /** * This interface can be used to tag the root node of various ASTs. */ public interface RootNode extends Node { + @Experimental + SimpleDataKey FILE_NAME_KEY = DataMap.simpleDataKey("pmd.fileName"); + // that's only a marker interface. } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java index c9a6bdf600..2d77189a41 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/designer/Designer.java @@ -105,6 +105,7 @@ import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.SourceCodeProcessor; +import net.sourceforge.pmd.lang.AbstractParser; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.LanguageVersionHandler; @@ -199,7 +200,8 @@ public class Designer implements ClipboardOwner { static Node getCompilationUnit(LanguageVersionHandler languageVersionHandler, String code) { Parser parser = languageVersionHandler.getParser(languageVersionHandler.getDefaultParserOptions()); - Node node = parser.parse(null, new StringReader(code)); + Node node = AbstractParser.doParse(parser, "no file name", new StringReader(code)); + languageVersionHandler.getSymbolFacade().start(node); languageVersionHandler.getTypeResolutionFacade(Designer.class.getClassLoader()).start(node); return node; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeExportCli.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeExportCli.java index 25cd5397e6..b5bb1a759e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeExportCli.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeExportCli.java @@ -22,6 +22,7 @@ import org.apache.commons.io.input.CloseShieldInputStream; import org.apache.commons.lang3.StringEscapeUtils; import net.sourceforge.pmd.annotation.Experimental; +import net.sourceforge.pmd.lang.AbstractParser; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageVersionHandler; @@ -174,7 +175,7 @@ public class TreeExportCli { Logger.getLogger(Attribute.class.getName()).setLevel(Level.OFF); try (Reader reader = source) { - Node root = parser.parse(file, reader); + Node root = AbstractParser.doParse(parser, file, reader); languageHandler.getQualifiedNameResolutionFacade(this.getClass().getClassLoader()).start(root); renderer.renderSubtree(root, System.out); diff --git a/pmd-modelica/src/test/kotlin/net/sourceforge/pmd/lang/modelica/ast/ModelicaCoordsTest.kt b/pmd-modelica/src/test/kotlin/net/sourceforge/pmd/lang/modelica/ast/ModelicaCoordsTest.kt index d2b0bc9ac6..69e078bdca 100644 --- a/pmd-modelica/src/test/kotlin/net/sourceforge/pmd/lang/modelica/ast/ModelicaCoordsTest.kt +++ b/pmd-modelica/src/test/kotlin/net/sourceforge/pmd/lang/modelica/ast/ModelicaCoordsTest.kt @@ -11,6 +11,7 @@ import net.sourceforge.pmd.lang.LanguageRegistry import net.sourceforge.pmd.lang.ast.Node import net.sourceforge.pmd.lang.ast.test.matchNode import net.sourceforge.pmd.lang.ast.test.shouldBe +import net.sourceforge.pmd.lang.modelica.ModelicaParsingHelper import java.io.StringReader class ModelicaCoordsTest : FunSpec({ @@ -108,12 +109,8 @@ end TestPackage; } }) -fun String.parseModelica(): ASTStoredDefinition { - val ver = LanguageRegistry.getLanguage("Modelica").defaultVersion.languageVersionHandler - val parser = ver.getParser(ver.defaultParserOptions) - - return parser.parse(":dummy:", StringReader(this)) as ASTStoredDefinition -} +fun String.parseModelica(): ASTStoredDefinition = + ModelicaParsingHelper.DEFAULT.parse(this, ":dummy") fun Node.assertBounds(bline: Int, bcol: Int, eline: Int, ecol: Int) { this::getBeginLine shouldBe bline diff --git a/pmd-scala-modules/pmd-scala-common/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaTreeTests.kt b/pmd-scala-modules/pmd-scala-common/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaTreeTests.kt index 48867dd383..cad6ba9066 100644 --- a/pmd-scala-modules/pmd-scala-common/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaTreeTests.kt +++ b/pmd-scala-modules/pmd-scala-common/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaTreeTests.kt @@ -80,12 +80,9 @@ class Foo { } }) -fun String.parseScala(): ASTSource { - val ver = LanguageRegistry.getLanguage("Scala").defaultVersion.languageVersionHandler - val parser = ver.getParser(ver.defaultParserOptions) +fun String.parseScala(): ASTSource = + ScalaParsingHelper.DEFAULT.parse(this, ":dummy") - return parser.parse(":dummy:", StringReader(this)) as ASTSource -} fun Node.assertBounds(bline: Int, bcol: Int, eline: Int, ecol: Int) { this::getBeginLine shouldBe bline From e64d48538449f34b9f42ab22376c0239b6779353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 8 Aug 2021 14:36:10 +0200 Subject: [PATCH 050/104] Add xpath function for file name --- .../pmd/lang/apex/ast/ApexParserTest.java | 8 +-- .../pmd/lang/apex/rule/ApexXPathRuleTest.java | 2 +- .../sourceforge/pmd/lang/AbstractParser.java | 5 +- .../sourceforge/pmd/lang/ast/RootNode.java | 5 ++ .../ast/xpath/DefaultASTXPathHandler.java | 7 ++- .../xpath/internal/CoreXPathFunctions.java | 21 +++++++ .../xpath/internal/FileNameXPathFunction.java | 56 +++++++++++++++++++ .../pmd/lang/java/AbstractJavaHandler.java | 2 + .../pmd/lang/ast/test/BaseParsingHelper.kt | 2 +- 9 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/FileNameXPathFunction.java diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserTest.java index f8530200f4..9dd136dd29 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexParserTest.java @@ -20,6 +20,7 @@ import org.junit.Assert; import org.junit.Test; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.RootNode; import apex.jorje.semantic.ast.compilation.Compilation; @@ -41,15 +42,12 @@ public class ApexParserTest extends ApexParserTestBase { } @Test - public void fileNameInNestedClass() { + public void fileName() { String code = "class Outer { class Inner {}}"; ASTUserClass rootNode = (ASTUserClass) parse(code, "src/filename.cls"); - assertEquals("filename.cls", rootNode.getFileName()); - ASTUserClass inner = rootNode.getFirstDescendantOfType(ASTUserClass.class); - assertEquals("Inner", inner.getImage()); - assertEquals("filename.cls", inner.getFileName()); + assertEquals("filename.cls", rootNode.getUserMap().get(RootNode.FILE_NAME_KEY)); } private String testCodeForLineNumbers = diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRuleTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRuleTest.java index a8f1e3c730..b90d4a26ce 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRuleTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRuleTest.java @@ -30,7 +30,7 @@ public class ApexXPathRuleTest extends ApexParserTestBase { @Test public void testFileNameInXpath() { - Report report = apex.executeRule(makeXPath("/UserClass[@FileName = 'Foo.cls']"), + Report report = apex.executeRule(makeXPath("/UserClass[pmd:fileName() = 'Foo.cls']"), "class Foo {}", "src/Foo.cls"); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/AbstractParser.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/AbstractParser.java index fa8954d020..d68877dd85 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/AbstractParser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/AbstractParser.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang; import java.io.Reader; +import java.nio.file.Paths; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.RootNode; @@ -41,7 +42,9 @@ public abstract class AbstractParser implements Parser { @Deprecated public static Node doParse(Parser parser, String fileName, Reader source) { Node rootNode = parser.parse(fileName, source); - rootNode.getUserMap().set(RootNode.FILE_NAME_KEY, fileName); + // remove prefixed path segments. + String simpleFileName = Paths.get(fileName).getFileName().toString(); + rootNode.getUserMap().set(RootNode.FILE_NAME_KEY, simpleFileName); return rootNode; } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/RootNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/RootNode.java index 68556ca753..be0c51b94d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/RootNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/RootNode.java @@ -12,6 +12,11 @@ import net.sourceforge.pmd.util.DataMap.SimpleDataKey; * This interface can be used to tag the root node of various ASTs. */ public interface RootNode extends Node { + + /** + * The name of the file, including its extension. This + * excludes any segments for containing directories. + */ @Experimental SimpleDataKey FILE_NAME_KEY = DataMap.simpleDataKey("pmd.fileName"); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DefaultASTXPathHandler.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DefaultASTXPathHandler.java index 3fa844f28a..02b30d3da6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DefaultASTXPathHandler.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DefaultASTXPathHandler.java @@ -5,6 +5,8 @@ package net.sourceforge.pmd.lang.ast.xpath; import net.sourceforge.pmd.annotation.InternalApi; +import net.sourceforge.pmd.lang.ast.xpath.internal.CoreXPathFunctions; +import net.sourceforge.pmd.lang.ast.xpath.internal.FileNameXPathFunction; import net.sf.saxon.sxpath.IndependentContext; @@ -15,11 +17,12 @@ public class DefaultASTXPathHandler extends AbstractASTXPathHandler { @Override public void initialize() { - // override if needed + FileNameXPathFunction.registerSelfInSimpleContext(); } @Override public void initialize(IndependentContext context) { - // override if needed + context.declareNamespace("pmd", "java:" + CoreXPathFunctions.class.getName()); } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java new file mode 100644 index 0000000000..8078b223fc --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java @@ -0,0 +1,21 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.ast.xpath.internal; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; + +import net.sf.saxon.expr.XPathContext; + +/** + * @author Clément Fournier + */ +public final class CoreXPathFunctions { + + public static String fileName(final XPathContext context) { + Node ctxNode = ((ElementNode) context.getContextItem()).getUnderlyingNode(); + return FileNameXPathFunction.getFileName(ctxNode); + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/FileNameXPathFunction.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/FileNameXPathFunction.java new file mode 100644 index 0000000000..7e30eb324b --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/FileNameXPathFunction.java @@ -0,0 +1,56 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.ast.xpath.internal; + +import java.util.List; +import java.util.Objects; + +import org.jaxen.Context; +import org.jaxen.FunctionCallException; +import org.jaxen.SimpleFunctionContext; +import org.jaxen.XPathFunctionContext; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.RootNode; + +/** + * A function that returns the current file name. + * + * @author Clément Fournier + */ +public class FileNameXPathFunction implements org.jaxen.Function { + + public static void registerSelfInSimpleContext() { + ((SimpleFunctionContext) XPathFunctionContext.getInstance()).registerFunction(null, "fileName", + new FileNameXPathFunction("fileName")); + } + + private final String name; + + public FileNameXPathFunction(String name) { + this.name = name; + } + + @Override + public Object call(Context context, List args) throws FunctionCallException { + if (!args.isEmpty()) { + throw new IllegalArgumentException(name + " function takes no arguments."); + } + Node n = (Node) context.getNodeSet().get(0); + + return getFileName(n); + } + + public static String getFileName(Node n) { + // todo pmd7: replace with Node.getRoot() + while (n.getParent() != null) { + n = n.getParent(); + } + Objects.requireNonNull(n, "No root node in tree?"); + + String fileName = n.getUserMap().get(RootNode.FILE_NAME_KEY); + return Objects.requireNonNull(fileName, "File name was not set"); + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java index afee0df9c6..3c9dbe488e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/AbstractJavaHandler.java @@ -62,6 +62,7 @@ public abstract class AbstractJavaHandler extends AbstractLanguageVersionHandler return new DefaultASTXPathHandler() { @Override public void initialize() { + super.initialize(); TypeOfFunction.registerSelfInSimpleContext(); GetCommentOnFunction.registerSelfInSimpleContext(); MetricFunction.registerSelfInSimpleContext(); @@ -71,6 +72,7 @@ public abstract class AbstractJavaHandler extends AbstractLanguageVersionHandler @Override public void initialize(IndependentContext context) { + super.initialize(context); super.initialize(context, LanguageRegistry.getLanguage(JavaLanguageModule.NAME), JavaFunctions.class); } }; diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt index de86bd92e9..560512b189 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt @@ -124,7 +124,7 @@ abstract class BaseParsingHelper, T : RootNode val handler = lversion.languageVersionHandler val options = params.parserOptions ?: handler.defaultParserOptions val parser = handler.getParser(options) - val rootNode = rootClass.cast(parser.parse(fileName, StringReader(sourceCode))) + val rootNode = rootClass.cast(AbstractParser.doParse(parser, fileName, StringReader(sourceCode))) if (params.doProcess) { handler.getQualifiedNameResolutionFacade(javaClass.classLoader).start(rootNode) handler.getSymbolFacade(javaClass.classLoader).start(rootNode) From 55c005a39eb18a6b1acca0e4698afcce8f896035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 8 Aug 2021 14:41:17 +0200 Subject: [PATCH 051/104] Revert some changes --- .../sourceforge/pmd/lang/apex/ApexParser.java | 2 +- .../pmd/lang/apex/ast/ApexParser.java | 13 +------ .../pmd/lang/apex/ast/ApexRootNode.java | 22 ----------- .../pmd/lang/apex/ast/ApexParserTest.java | 4 +- .../lang/apex/ast/SafeNavigationOperator.txt | 2 +- .../sourceforge/pmd/lang/AbstractParser.java | 4 +- .../sourceforge/pmd/lang/ast/RootNode.java | 12 ------ .../xpath/internal/CoreXPathFunctions.java | 4 ++ .../xpath/internal/FileNameXPathFunction.java | 11 +++++- .../pmd/lang/xml/rule/XmlXPathRuleTest.java | 39 +++++++++++++++++++ 10 files changed, 60 insertions(+), 53 deletions(-) create mode 100644 pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexParser.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexParser.java index db09d87e61..fdcedcd253 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexParser.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ApexParser.java @@ -42,7 +42,7 @@ public class ApexParser extends AbstractParser { @Override public Node parse(String fileName, Reader source) throws ParseException { - return apexParser.parse(source, fileName); + return apexParser.parse(source); } @Override diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java index d2e9bd2d6f..a6ff552503 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.apex.ast; import java.io.IOException; import java.io.Reader; import java.util.Map; -import java.util.Objects; import org.apache.commons.io.IOUtils; @@ -49,13 +48,7 @@ public class ApexParser { return visitor.getTopLevel(); } - @Deprecated public ApexNode parse(final Reader reader) { - throw new UnsupportedOperationException("use the other overload, this class is internal API btw"); - } - - public ApexNode parse(final Reader reader, final String fileName) { - Objects.requireNonNull(fileName, "file name is null"); try { final String sourceCode = IOUtils.toString(reader); final Compilation astRoot = parseApex(sourceCode); @@ -66,9 +59,7 @@ public class ApexParser { throw new ParseException("Couldn't parse the source - there is not root node - Syntax Error??"); } - ApexRootNode root = (ApexRootNode) treeBuilder.build(astRoot); - root.setFileName(fileName); - return root; + return treeBuilder.build(astRoot); } catch (IOException | apex.jorje.services.exception.ParseException e) { throw new ParseException(e); } @@ -78,7 +69,7 @@ public class ApexParser { return suppressMap; } - private static class TopLevelVisitor extends AstVisitor { + private class TopLevelVisitor extends AstVisitor { Compilation topLevel; public Compilation getTopLevel() { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java index 585cf0f6c4..a14c241b44 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.ast; -import java.nio.file.Paths; - import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.RootNode; import net.sourceforge.pmd.lang.ast.SourceCodePositioner; @@ -16,9 +14,6 @@ import apex.jorje.services.Version; @Deprecated @InternalApi public abstract class ApexRootNode extends AbstractApexNode implements RootNode { - - private String fileName; - @Deprecated @InternalApi public ApexRootNode(T node) { @@ -56,23 +51,6 @@ public abstract class ApexRootNode extends AbstractApexNode FILE_NAME_KEY = DataMap.simpleDataKey("pmd.fileName"); - // that's only a marker interface. } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java index 8078b223fc..40823a5f44 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java @@ -14,6 +14,10 @@ import net.sf.saxon.expr.XPathContext; */ public final class CoreXPathFunctions { + private CoreXPathFunctions() { + // util class + } + public static String fileName(final XPathContext context) { Node ctxNode = ((ElementNode) context.getContextItem()).getUnderlyingNode(); return FileNameXPathFunction.getFileName(ctxNode); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/FileNameXPathFunction.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/FileNameXPathFunction.java index 7e30eb324b..4f4d42503e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/FileNameXPathFunction.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/FileNameXPathFunction.java @@ -13,7 +13,8 @@ import org.jaxen.SimpleFunctionContext; import org.jaxen.XPathFunctionContext; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.ast.RootNode; +import net.sourceforge.pmd.util.DataMap; +import net.sourceforge.pmd.util.DataMap.SimpleDataKey; /** * A function that returns the current file name. @@ -22,6 +23,12 @@ import net.sourceforge.pmd.lang.ast.RootNode; */ public class FileNameXPathFunction implements org.jaxen.Function { + /** + * The name of the file, including its extension. This + * excludes any segments for containing directories. + */ + public static final SimpleDataKey FILE_NAME_KEY = DataMap.simpleDataKey("pmd.fileName"); + public static void registerSelfInSimpleContext() { ((SimpleFunctionContext) XPathFunctionContext.getInstance()).registerFunction(null, "fileName", new FileNameXPathFunction("fileName")); @@ -50,7 +57,7 @@ public class FileNameXPathFunction implements org.jaxen.Function { } Objects.requireNonNull(n, "No root node in tree?"); - String fileName = n.getUserMap().get(RootNode.FILE_NAME_KEY); + String fileName = n.getUserMap().get(FILE_NAME_KEY); return Objects.requireNonNull(fileName, "File name was not set"); } } diff --git a/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java new file mode 100644 index 0000000000..ef22aa88d8 --- /dev/null +++ b/pmd-xml/src/test/java/net/sourceforge/pmd/lang/xml/rule/XmlXPathRuleTest.java @@ -0,0 +1,39 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.xml.rule; + +import static net.sourceforge.pmd.lang.ast.test.TestUtilsKt.assertSize; + +import org.junit.Test; + +import net.sourceforge.pmd.Report; +import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; +import net.sourceforge.pmd.lang.xml.XmlLanguageModule; +import net.sourceforge.pmd.lang.xml.XmlParsingHelper; + +public class XmlXPathRuleTest { + + final XmlParsingHelper xml = XmlParsingHelper.XML; + + private XPathRule makeXPath(String expression) { + XPathRule rule = new XPathRule(XPathVersion.XPATH_2_0, expression); + rule.setLanguage(LanguageRegistry.getLanguage(XmlLanguageModule.NAME)); + rule.setMessage("XPath Rule Failed"); + return rule; + } + + + @Test + public void testFileNameInXpath() { + Report report = xml.executeRule(makeXPath("//b[pmd:fileName() = 'Foo.xml']"), + "", + "src/Foo.xml"); + + assertSize(report, 1); + } + +} From 482268def80f5cedd6e951764436e33d859c00ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 8 Aug 2021 15:06:59 +0200 Subject: [PATCH 052/104] Use existing function registry --- .../ast/xpath/DefaultASTXPathHandler.java | 3 +-- .../xpath/internal/CoreXPathFunctions.java | 25 ------------------- .../pmd/lang/xpath/PMDFunctions.java | 10 ++++++++ 3 files changed, 11 insertions(+), 27 deletions(-) delete mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DefaultASTXPathHandler.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DefaultASTXPathHandler.java index 02b30d3da6..a57373774e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DefaultASTXPathHandler.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/DefaultASTXPathHandler.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.ast.xpath; import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.ast.xpath.internal.CoreXPathFunctions; import net.sourceforge.pmd.lang.ast.xpath.internal.FileNameXPathFunction; import net.sf.saxon.sxpath.IndependentContext; @@ -22,7 +21,7 @@ public class DefaultASTXPathHandler extends AbstractASTXPathHandler { @Override public void initialize(IndependentContext context) { - context.declareNamespace("pmd", "java:" + CoreXPathFunctions.class.getName()); + // override if needed } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java deleted file mode 100644 index 40823a5f44..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/CoreXPathFunctions.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.ast.xpath.internal; - -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; - -import net.sf.saxon.expr.XPathContext; - -/** - * @author Clément Fournier - */ -public final class CoreXPathFunctions { - - private CoreXPathFunctions() { - // util class - } - - public static String fileName(final XPathContext context) { - Node ctxNode = ((ElementNode) context.getContextItem()).getUnderlyingNode(); - return FileNameXPathFunction.getFileName(ctxNode); - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java index 5a26e7b75c..54853ea1f9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/xpath/PMDFunctions.java @@ -5,6 +5,11 @@ package net.sourceforge.pmd.lang.xpath; import net.sourceforge.pmd.annotation.InternalApi; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.internal.FileNameXPathFunction; +import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; + +import net.sf.saxon.expr.XPathContext; @InternalApi @@ -37,4 +42,9 @@ public final class PMDFunctions { String pattern5, String pattern6) { return MatchesFunction.matches(s, pattern1, pattern2, pattern3, pattern4, pattern5, pattern6); } + + public static String fileName(final XPathContext context) { + Node ctxNode = ((ElementNode) context.getContextItem()).getUnderlyingNode(); + return FileNameXPathFunction.getFileName(ctxNode); + } } From 52e3bb1eed418a554a26fb4e4ace3254b95f8766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 8 Aug 2021 20:07:33 +0200 Subject: [PATCH 053/104] Fix tests --- .../net/sourceforge/pmd/lang/modelica/ast/ModelicaCoordsTest.kt | 2 +- .../kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaTreeTests.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pmd-modelica/src/test/kotlin/net/sourceforge/pmd/lang/modelica/ast/ModelicaCoordsTest.kt b/pmd-modelica/src/test/kotlin/net/sourceforge/pmd/lang/modelica/ast/ModelicaCoordsTest.kt index 69e078bdca..cdbb3a9f5b 100644 --- a/pmd-modelica/src/test/kotlin/net/sourceforge/pmd/lang/modelica/ast/ModelicaCoordsTest.kt +++ b/pmd-modelica/src/test/kotlin/net/sourceforge/pmd/lang/modelica/ast/ModelicaCoordsTest.kt @@ -110,7 +110,7 @@ end TestPackage; }) fun String.parseModelica(): ASTStoredDefinition = - ModelicaParsingHelper.DEFAULT.parse(this, ":dummy") + ModelicaParsingHelper.DEFAULT.parse(this) fun Node.assertBounds(bline: Int, bcol: Int, eline: Int, ecol: Int) { this::getBeginLine shouldBe bline diff --git a/pmd-scala-modules/pmd-scala-common/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaTreeTests.kt b/pmd-scala-modules/pmd-scala-common/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaTreeTests.kt index cad6ba9066..4e23e8a6e7 100644 --- a/pmd-scala-modules/pmd-scala-common/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaTreeTests.kt +++ b/pmd-scala-modules/pmd-scala-common/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaTreeTests.kt @@ -81,7 +81,7 @@ class Foo { }) fun String.parseScala(): ASTSource = - ScalaParsingHelper.DEFAULT.parse(this, ":dummy") + ScalaParsingHelper.DEFAULT.parse(this) fun Node.assertBounds(bline: Int, bcol: Int, eline: Int, ecol: Int) { From 99f41d4b7416684ae47379d9df2f1a30fa405d8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 8 Aug 2021 20:24:36 +0200 Subject: [PATCH 054/104] Update SimplifiedTernary --- .../src/main/resources/category/java/design.xml | 8 +++----- .../java/rule/design/SimplifiedTernaryTest.java | 1 - .../java/rule/design/xml/SimplifiedTernary.xml | 16 ++++++++-------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index c3c579c464..07c65f44a2 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -1111,12 +1111,12 @@ public void foo() throws Exception { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SimplifiedTernaryTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SimplifiedTernaryTest.java index b57ae4b5b8..c381684027 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SimplifiedTernaryTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SimplifiedTernaryTest.java @@ -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 SimplifiedTernaryTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifiedTernary.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifiedTernary.xml index 2002135780..5f7a40a850 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifiedTernary.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifiedTernary.xml @@ -9,7 +9,7 @@ 1 1 1 1 0 0 @@ -81,7 +81,7 @@ public class SimplifiedTernary { 0 Date: Sun, 8 Aug 2021 20:30:20 +0200 Subject: [PATCH 055/104] Remove FN when both branches are literals There is no such "existing rule" that reports this. --- .../pmd/lang/java/rule/design/xml/SimplifiedTernary.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifiedTernary.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifiedTernary.xml index 5f7a40a850..e3305ee2ff 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifiedTernary.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SimplifiedTernary.xml @@ -54,11 +54,11 @@ public class Foo { condition ? true : false - 0 + 1 From b50fee14af1147dc8fe658bd75b53d2b167af8bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 8 Aug 2021 20:31:46 +0200 Subject: [PATCH 056/104] Update ci file --- .ci/files/all-java.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index f4b310ca61..ce7106a209 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -153,7 +153,7 @@ - + From 621f5f6dd14d702ef51cd2af89032b9ea82b31ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 8 Aug 2021 20:57:00 +0200 Subject: [PATCH 057/104] Update rule SimplifyConditional --- .ci/files/all-java.xml | 2 +- .../rule/design/SimplifyConditionalRule.java | 63 +++++++++++++++++++ .../lang/java/rule/internal/JavaRuleUtil.java | 22 ++++++- .../java/rule/internal/StablePathMatcher.java | 21 +++++-- .../DoubleCheckedLockingRule.java | 34 ++-------- .../main/resources/category/java/design.xml | 34 +--------- .../rule/design/SimplifyConditionalTest.java | 1 - .../rule/design/xml/SimplifyConditional.xml | 5 +- 8 files changed, 108 insertions(+), 74 deletions(-) create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index f4b310ca61..dc4b65e334 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -157,7 +157,7 @@ - + diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java new file mode 100644 index 0000000000..0f008502ef --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java @@ -0,0 +1,63 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.design; + +import static net.sourceforge.pmd.lang.java.ast.BinaryOp.CONDITIONAL_AND; +import static net.sourceforge.pmd.lang.java.ast.BinaryOp.CONDITIONAL_OR; +import static net.sourceforge.pmd.lang.java.ast.BinaryOp.INSTANCEOF; +import static net.sourceforge.pmd.lang.java.ast.BinaryOp.NE; +import static net.sourceforge.pmd.lang.java.ast.BinaryOp.isInfixExprWithOperator; +import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.getOtherOperandIfInInfixExpr; +import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isBooleanNegation; +import static net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil.isNullCheck; + +import net.sourceforge.pmd.lang.java.ast.ASTExpression; +import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; +import net.sourceforge.pmd.lang.java.rule.internal.StablePathMatcher; + + +public class SimplifyConditionalRule extends AbstractJavaRulechainRule { + + public SimplifyConditionalRule() { + super(ASTInfixExpression.class); + } + + + @Override + public Object visit(ASTInfixExpression node, Object data) { + if (node.getOperator() == INSTANCEOF) { + + StablePathMatcher instanceOfSubject = StablePathMatcher.matching(node.getLeftOperand()); + if (instanceOfSubject == null) { + return null; + } + + ASTExpression nullCheckExpr; + boolean negated; + if (isInfixExprWithOperator(node.getParent(), CONDITIONAL_AND)) { + // a != null && a instanceof T + negated = false; + nullCheckExpr = getOtherOperandIfInInfixExpr(node); + } else if (isBooleanNegation(node.getParent()) + && isInfixExprWithOperator(node.getParent().getParent(), CONDITIONAL_OR)) { + // a == null || a instanceof T + negated = true; + nullCheckExpr = getOtherOperandIfInInfixExpr(node.getParent()); + } else { + return null; + } + + if (!isNullCheck(nullCheckExpr, instanceOfSubject)) { + return null; + } + + if (negated != isInfixExprWithOperator(nullCheckExpr, NE)) { + addViolation(data, nullCheckExpr); + } + } + return null; + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java index 5cfd743803..72d81182ae 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleUtil.java @@ -659,7 +659,7 @@ public final class JavaRuleUtil { return e instanceof ASTBooleanLiteral; } - public static boolean isBooleanNegation(ASTExpression e) { + public static boolean isBooleanNegation(JavaNode e) { return e instanceof ASTUnaryExpression && ((ASTUnaryExpression) e).getOperator() == UnaryOp.NEGATION; } @@ -963,4 +963,24 @@ public final class JavaRuleUtil { public static boolean hasLombokAnnotation(Annotatable node) { return LOMBOK_ANNOTATIONS.stream().anyMatch(node::isAnnotationPresent); } + + /** + * Returns true if the expression is a null check on the given variable. + */ + public static boolean isNullCheck(ASTExpression expr, JVariableSymbol var) { + return isNullCheck(expr, StablePathMatcher.matching(var)); + } + + public static boolean isNullCheck(ASTExpression expr, StablePathMatcher matcher) { + if (expr instanceof ASTInfixExpression) { + ASTInfixExpression condition = (ASTInfixExpression) expr; + if (condition.getOperator().hasSamePrecedenceAs(BinaryOp.EQ)) { + ASTNullLiteral nullLit = condition.firstChild(ASTNullLiteral.class); + if (nullLit != null) { + return matcher.matches(getOtherOperandIfInInfixExpr(nullLit)); + } + } + } + return false; + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/StablePathMatcher.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/StablePathMatcher.java index f3c43de9f7..c6df092758 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/StablePathMatcher.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/StablePathMatcher.java @@ -4,7 +4,9 @@ package net.sourceforge.pmd.lang.java.rule.internal; -import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Objects; import org.checkerframework.checker.nullness.qual.Nullable; @@ -31,9 +33,9 @@ public final class StablePathMatcher { // if owner == null, then the owner is `this`. private final @Nullable JVariableSymbol owner; - private final ArrayDeque path; + private final List path; - private StablePathMatcher(@Nullable JVariableSymbol owner, ArrayDeque path) { + private StablePathMatcher(@Nullable JVariableSymbol owner, List path) { this.owner = owner; this.path = path; } @@ -88,18 +90,21 @@ public final class StablePathMatcher { * Otherwise returns null. */ public static @Nullable StablePathMatcher matching(ASTExpression e) { + if (e == null) { + return null; + } JVariableSymbol owner = null; - ArrayDeque segments = new ArrayDeque<>(); + List segments = new ArrayList<>(); while (e != null) { if (e instanceof ASTFieldAccess) { ASTFieldAccess access = (ASTFieldAccess) e; - segments.addLast(new Segment(access.getName(), true)); + segments.add(new Segment(access.getName(), true)); e = access.getQualifier(); } else if (e instanceof ASTMethodCall) { ASTMethodCall call = (ASTMethodCall) e; if (JavaRuleUtil.isGetterCall(call)) { - segments.addLast(new Segment(call.getMethodName(), false)); + segments.add(new Segment(call.getMethodName(), false)); e = call.getQualifier(); } else { return null; @@ -128,6 +133,10 @@ public final class StablePathMatcher { return new StablePathMatcher(owner, segments); } + public static StablePathMatcher matching(JVariableSymbol e) { + return new StablePathMatcher(e, Collections.emptyList()); + } + private static final class Segment { final String name; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/DoubleCheckedLockingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/DoubleCheckedLockingRule.java index 04427bf008..a944309044 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/DoubleCheckedLockingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/multithreading/DoubleCheckedLockingRule.java @@ -14,15 +14,13 @@ import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr import net.sourceforge.pmd.lang.java.ast.ASTAssignmentExpression; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; -import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral; import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType; import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; import net.sourceforge.pmd.lang.java.ast.ASTSynchronizedStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.java.ast.BinaryOp; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; import net.sourceforge.pmd.lang.java.symbols.JLocalVariableSymbol; import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; @@ -93,15 +91,15 @@ public class DoubleCheckedLockingRule extends AbstractJavaRule { List isl = node.findDescendantsOfType(ASTIfStatement.class); if (isl.size() == 2) { ASTIfStatement outerIf = isl.get(0); - if (isNullCheck(outerIf.getCondition(), returnVariable)) { + if (JavaRuleUtil.isNullCheck(outerIf.getCondition(), returnVariable)) { // find synchronized List ssl = outerIf.findDescendantsOfType(ASTSynchronizedStatement.class); if (ssl.size() == 1 && ssl.get(0).ancestors().any(it -> it == outerIf)) { ASTIfStatement is2 = isl.get(1); - if (isNullCheck(is2.getCondition(), returnVariable)) { + if (JavaRuleUtil.isNullCheck(is2.getCondition(), returnVariable)) { List assignments = is2.findDescendantsOfType(ASTAssignmentExpression.class); if (assignments.size() == 1 - && isReferenceTo(assignments.get(0).getLeftOperand(), returnVariable)) { + && JavaRuleUtil.isReferenceToVar(assignments.get(0).getLeftOperand(), returnVariable)) { addViolation(data, node); } @@ -127,7 +125,7 @@ public class DoubleCheckedLockingRule extends AbstractJavaRule { return (initializer == null || isVolatileFieldReference(initializer)) && method.descendants(ASTAssignmentExpression.class) - .filter(it -> isReferenceTo(it.getLeftOperand(), local)) + .filter(it -> JavaRuleUtil.isReferenceToVar(it.getLeftOperand(), local)) .all(it -> isVolatileFieldReference(it.getRightOperand())); } @@ -140,26 +138,4 @@ public class DoubleCheckedLockingRule extends AbstractJavaRule { } } - private boolean isReferenceTo(@Nullable ASTExpression expr, JVariableSymbol symbol) { - if (expr instanceof ASTNamedReferenceExpr) { - return symbol != null && symbol.equals(((ASTNamedReferenceExpr) expr).getReferencedSym()); - } else { - return false; - } - } - - private boolean isNullCheck(ASTExpression expr, JVariableSymbol var) { - if (expr instanceof ASTInfixExpression) { - ASTInfixExpression condition = (ASTInfixExpression) expr; - if (condition.getOperator().hasSamePrecedenceAs(BinaryOp.EQ)) { - ASTNullLiteral nullLit = condition.getFirstChildOfType(ASTNullLiteral.class); - if (nullLit != null) { - ASTExpression otherChild = (ASTExpression) condition.getChild(1 - nullLit.getIndexInParent()); - return isReferenceTo(otherChild, var); - } - } - } - return false; - } - } diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index c3c579c464..581f716820 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -1285,44 +1285,12 @@ public boolean isBarEqualTo(int x) { language="java" since="3.1" message="No need to check for null before an instanceof" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.java.rule.design.SimplifyConditionalRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#simplifyconditional"> No need to check for null before an instanceof; the instanceof keyword returns false when given a null argument. 3 - - - - - - - Bug 2317099 : False + in SimplifyConditional 0 Date: Mon, 9 Aug 2021 18:28:17 +0200 Subject: [PATCH 058/104] Checkstyle --- .../pmd/lang/java/rule/design/SimplifyConditionalRule.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java index 0f008502ef..a5312867cf 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyConditionalRule.java @@ -40,12 +40,12 @@ public class SimplifyConditionalRule extends AbstractJavaRulechainRule { if (isInfixExprWithOperator(node.getParent(), CONDITIONAL_AND)) { // a != null && a instanceof T negated = false; - nullCheckExpr = getOtherOperandIfInInfixExpr(node); + nullCheckExpr = getOtherOperandIfInInfixExpr(node); } else if (isBooleanNegation(node.getParent()) && isInfixExprWithOperator(node.getParent().getParent(), CONDITIONAL_OR)) { // a == null || a instanceof T negated = true; - nullCheckExpr = getOtherOperandIfInInfixExpr(node.getParent()); + nullCheckExpr = getOtherOperandIfInInfixExpr(node.getParent()); } else { return null; } From c8311e96e47c7bc2a2d95d597bf66c7827d8e2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 9 Aug 2021 18:39:38 +0200 Subject: [PATCH 059/104] Update rule SwitchDensity Maybe we should consider using metrics for this... whatever Add NodeStream#sumBy --- .ci/files/all-java.xml | 2 +- .../sourceforge/pmd/lang/ast/NodeStream.java | 18 ++++++ .../java/rule/design/SwitchDensityRule.java | 58 ++++++------------- .../java/rule/design/SwitchDensityTest.java | 1 - 4 files changed, 37 insertions(+), 42 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index f4b310ca61..dce506bbbe 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -159,7 +159,7 @@ - + diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/NodeStream.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/NodeStream.java index d12c91f76c..75b2f90b3f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/NodeStream.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/NodeStream.java @@ -14,6 +14,7 @@ import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; +import java.util.function.ToIntFunction; import java.util.stream.Collector; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -620,6 +621,23 @@ public interface NodeStream<@NonNull T extends Node> extends Iterable<@NonNull T return result; } + /** + * Sum the elements of this stream by associating them to an integer. + * + * @param toInt Map an element to an integer, which will be added + * to the running sum + * returns the next intermediate result + * + * @return The sum, zero if the stream is empty. + */ + default int sumBy(ToIntFunction toInt) { + int result = 0; + for (T node : this) { + result += toInt.applyAsInt(node); + } + return result; + } + /** * Returns the number of nodes in this stream. diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java index 97c3db3541..b178c2861d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java @@ -6,11 +6,10 @@ package net.sourceforge.pmd.lang.java.rule.design; import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; -import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTStatement; -import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchLike; import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; -import net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; @@ -24,6 +23,7 @@ import net.sourceforge.pmd.properties.PropertyFactory; * looking at Subclasses or State Pattern to alleviate the problem.

* * @author David Dixon-Peugh + * @author Clément Fournier */ public class SwitchDensityRule extends AbstractJavaRulechainRule { @@ -42,45 +42,23 @@ public class SwitchDensityRule extends AbstractJavaRulechainRule { @Override public Object visit(ASTSwitchStatement node, Object data) { - double density = new SwitchDensityVisitor().compute(node); + return visitSwitchLike(node, data); + } + + public Object visit(ASTSwitchExpression node, Object data) { + return visitSwitchLike(node, data); + } + + public Void visitSwitchLike(ASTSwitchLike node, Object data) { + // note: this does not cross find boundaries. + int stmtCount = node.descendants(ASTStatement.class).count(); + int labelCount = node.getBranches().sumBy(branch -> branch.getLabel().getExprList().count()); + + // note: if labelCount is zero, double division will produce NaN, not ArithmeticException + double density = stmtCount / (double) labelCount; if (density >= getProperty(REPORT_LEVEL)) { addViolation(data, node); } - return super.visit(node, data); - } - - private static class SwitchDensityVisitor extends JavaParserVisitorAdapter { - - private int labels = 0; - private int stmts = 0; - private ASTSwitchStatement root; - - - double compute(ASTSwitchStatement root) { - this.root = root; - root.jjtAccept(this, null); - return labels == 0 ? 0 : ((double) stmts) / labels; - } - - - @Override - public Object visitStatement(ASTStatement statement, Object data) { - stmts++; - return super.visitStatement(statement, data); - } - - @Override - public Object visit(ASTExpression node, Object data) { - // don't recurse on anonymous class, etc - return data; - } - - @Override - public Object visit(ASTSwitchLabel switchLabel, Object data) { - if (switchLabel.getParent() == root) { - labels++; - } - return super.visit(switchLabel, data); - } + return null; } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityTest.java index c19a339f55..0da92cecac 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityTest.java @@ -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 SwitchDensityTest extends PmdRuleTst { // no additional unit tests } From 8b98c861a2659a554f554be1cef1deb1f01912da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 9 Aug 2021 19:08:44 +0200 Subject: [PATCH 060/104] Update rule UseUtilityClass --- .../ast/ASTAnonymousClassDeclaration.java | 12 +- .../lang/java/ast/ASTAnyTypeDeclaration.java | 9 +- .../java/rule/design/UseUtilityClassRule.java | 140 ++++++++---------- .../java/rule/design/UseUtilityClassTest.java | 1 - .../java/rule/design/xml/UseUtilityClass.xml | 43 +++++- 5 files changed, 108 insertions(+), 97 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnonymousClassDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnonymousClassDeclaration.java index 1969d8e16c..de7b83edb4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnonymousClassDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnonymousClassDeclaration.java @@ -4,13 +4,9 @@ package net.sourceforge.pmd.lang.java.ast; -import static net.sourceforge.pmd.util.CollectionUtil.listOf; - -import java.util.Collections; -import java.util.List; - import org.checkerframework.checker.nullness.qual.NonNull; +import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.types.JTypeMirror; /** @@ -44,15 +40,15 @@ public final class ASTAnonymousClassDeclaration extends AbstractAnyTypeDeclarati } @Override - public @NonNull List getSuperInterfaceTypeNodes() { + public @NonNull NodeStream getSuperInterfaceTypeNodes() { if (getParent() instanceof ASTConstructorCall) { ASTConstructorCall ctor = (ASTConstructorCall) getParent(); @NonNull JTypeMirror type = ctor.getTypeMirror(); if (type.isInterface()) { - return listOf(ctor.getTypeNode()); + return NodeStream.of(ctor.getTypeNode()); } } - return Collections.emptyList(); + return NodeStream.empty(); } @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.java index 799249e581..5a51c7b109 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.java @@ -6,8 +6,6 @@ package net.sourceforge.pmd.lang.java.ast; import static net.sourceforge.pmd.lang.java.ast.JModifier.ABSTRACT; -import java.util.List; - import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -279,9 +277,8 @@ public interface ASTAnyTypeDeclaration * Returns the list of interfaces implemented by this class, or * extended by this interface. Returns null if no such list is declared. */ - @NonNull - default List getSuperInterfaceTypeNodes() { - return ASTList.orEmpty(isInterface() ? getFirstChildOfType(ASTExtendsList.class) - : getFirstChildOfType(ASTImplementsList.class)); + default @NonNull NodeStream getSuperInterfaceTypeNodes() { + return ASTList.orEmptyStream(isInterface() ? firstChild(ASTExtendsList.class) + : firstChild(ASTImplementsList.class)); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java index 672c6b56b8..683067b2ad 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java @@ -6,98 +6,86 @@ package net.sourceforge.pmd.lang.java.rule.design; import static net.sourceforge.pmd.util.CollectionUtil.setOf; -import java.util.Collection; +import java.util.Set; -import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.ast.ASTAnnotation; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; +import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; +import net.sourceforge.pmd.lang.java.ast.ASTBodyDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMemberValuePair; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTResultType; -import net.sourceforge.pmd.lang.java.rule.AbstractLombokAwareRule; +import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility; +import net.sourceforge.pmd.lang.java.ast.JavaNode; +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; -public class UseUtilityClassRule extends AbstractLombokAwareRule { +public class UseUtilityClassRule extends AbstractJavaRulechainRule { - @Override - protected Collection defaultSuppressionAnnotations() { - return setOf("lombok.experimental.UtilityClass"); + private static final Set IGNORED_CLASS_ANNOT = setOf( + "lombok.experimental.UtilityClass", + "org.junit.runner.RunWith" // for suites and such + ); + + public UseUtilityClassRule() { + super(ASTClassOrInterfaceDeclaration.class); } @Override - public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { - if (hasIgnoredAnnotation(node)) { + public Object visit(ASTClassOrInterfaceDeclaration klass, Object data) { + if (JavaRuleUtil.hasAnyAnnotation(klass, IGNORED_CLASS_ANNOT) + || TypeTestUtil.isA("junit.framework.TestSuite", klass) // suite method is ok + || klass.isInterface() + || klass.isAbstract() + || klass.getSuperClassTypeNode() != null + || klass.getSuperInterfaceTypeNodes().nonEmpty() + // || JavaRuleUtil.isUtilityClass(node) + ) { return data; } - return super.visit(node, data); - } - @Override - public Object visit(ASTClassOrInterfaceBody decl, Object data) { - Object result = super.visit(decl, data); - - if (decl.getParent() instanceof ASTClassOrInterfaceDeclaration) { - ASTClassOrInterfaceDeclaration parent = (ASTClassOrInterfaceDeclaration) decl.getParent(); - if (parent.isAbstract() || parent.isInterface() || parent.getSuperClassTypeNode() != null) { - return result; + boolean hasAnyMethods = false; + boolean hasNonPrivateCtor = false; + boolean hasAnyCtor = false; + for (ASTBodyDeclaration declaration : klass.getDeclarations()) { + if (declaration instanceof ASTFieldDeclaration + && !((ASTFieldDeclaration) declaration).isStatic()) { + return null; } - - if (hasLombokNoArgsConstructor(parent)) { - return result; - } - - int i = decl.getNumChildren(); - int methodCount = 0; - boolean isOK = false; - while (i > 0) { - Node p = decl.getChild(--i); - if (p.getNumChildren() == 0) { - continue; - } - Node n = skipAnnotations(p); - if (n instanceof ASTFieldDeclaration) { - if (!((ASTFieldDeclaration) n).isStatic()) { - isOK = true; - break; - } - } else if (n instanceof ASTConstructorDeclaration) { - if (((ASTConstructorDeclaration) n).isPrivate()) { - isOK = true; - break; - } - } else if (n instanceof ASTMethodDeclaration) { - ASTMethodDeclaration m = (ASTMethodDeclaration) n; - if (!m.isPrivate()) { - methodCount++; - } - if (!m.isStatic()) { - isOK = true; - break; - } - - // TODO use symbol table - if ("suite".equals(m.getName())) { - ASTResultType res = m.getResultType(); - ASTClassOrInterfaceType c = res.getFirstDescendantOfType(ASTClassOrInterfaceType.class); - if (c != null && c.hasImageEqualTo("Test")) { - isOK = true; - break; - } - } + if (declaration instanceof ASTConstructorDeclaration) { + hasAnyCtor = true; + if (((ASTConstructorDeclaration) declaration).getVisibility() != Visibility.V_PRIVATE) { + hasNonPrivateCtor = true; } } - if (!isOK && methodCount > 0) { - addViolation(data, decl); + + if (declaration instanceof ASTMethodDeclaration) { + if (((ASTMethodDeclaration) declaration).getVisibility() != Visibility.V_PRIVATE) { + hasAnyMethods = true; + } + if (!((ASTMethodDeclaration) declaration).isStatic()) { + return null; + } } } - return result; + + // account for default ctor + hasNonPrivateCtor |= !hasAnyCtor + && klass.getVisibility() != Visibility.V_PRIVATE + && !hasLombokPrivateCtor(klass); + + + String message; + if (hasAnyMethods && hasNonPrivateCtor) { + message = "This utility class has a non-private constructor"; + addViolationWithMessage(data, klass, message); + } + return null; } - private boolean hasLombokNoArgsConstructor(ASTClassOrInterfaceDeclaration parent) { + private boolean hasLombokPrivateCtor(ASTClassOrInterfaceDeclaration parent) { // check if there's a lombok no arg private constructor, if so skip the rest of the rules return parent.getDeclaredAnnotations() @@ -105,18 +93,16 @@ public class UseUtilityClassRule extends AbstractLombokAwareRule { .flatMap(ASTAnnotation::getMembers) // to set the access level of a constructor in lombok, you set the access property on the annotation .filterMatching(ASTMemberValuePair::getName, "access") - .map(ASTMemberValuePair::getValue) // This is from the AccessLevel enum in Lombok // if the constructor is found and the accesslevel is private no need to check anything else - .any(it -> "PRIVATE".equals(it.getImage())); + .any(it -> isAccessToVarWithName(it.getValue(), "PRIVATE")); } - private Node skipAnnotations(Node p) { - int index = 0; - Node n = p.getChild(index++); - while (n instanceof ASTAnnotation && index < p.getNumChildren()) { - n = p.getChild(index++); + private static boolean isAccessToVarWithName(JavaNode node, String name) { + if (node instanceof ASTNamedReferenceExpr) { + return ((ASTNamedReferenceExpr) node).getName().equals(name); } - return n; + return false; } + } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassTest.java index b9275c8101..36e7942a09 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassTest.java @@ -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 UseUtilityClassTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/UseUtilityClass.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/UseUtilityClass.xml index 81ab0468f8..db6994e9c4 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/UseUtilityClass.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/UseUtilityClass.xml @@ -7,6 +7,9 @@ should be utility class since all static, public constructor 1 + + This utility class has a non-private constructor + - junit 'suite' method is OK + junit 3 'suite' method is OK 0 + + + junit 4 'suite' method is OK + 0 + Inner class in abstract class false-negative 1 + 2 + + + Private inner class in abstract class + 0 + 1 1 Inner class in sub-class false-negative 1 + 2 Date: Mon, 9 Aug 2021 19:16:32 +0200 Subject: [PATCH 061/104] Remove unresolved reference warnings --- .ci/files/all-java.xml | 2 +- .../java/rule/design/UseUtilityClassRule.java | 1 - .../java/rule/design/xml/UseUtilityClass.xml | 37 +++++-------------- 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index f4b310ca61..9b94a85aea 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -163,7 +163,7 @@ - + diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java index 683067b2ad..abeeb9d7b7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java @@ -41,7 +41,6 @@ public class UseUtilityClassRule extends AbstractJavaRulechainRule { || klass.isAbstract() || klass.getSuperClassTypeNode() != null || klass.getSuperInterfaceTypeNodes().nonEmpty() - // || JavaRuleUtil.isUtilityClass(node) ) { return data; } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/UseUtilityClass.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/UseUtilityClass.xml index db6994e9c4..32af58ff8f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/UseUtilityClass.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/UseUtilityClass.xml @@ -121,14 +121,14 @@ public class FooTest extends TestSuite { 0 + ]]> @@ -226,19 +226,17 @@ public class MyException extends RuntimeException { #1467 UseUtilityClass can't correctly check functions with multiple annotations 0 @@ -277,21 +275,6 @@ public class Foo { ]]> - - Lombok NoArgsConstructor no import- ok - 0 - - - Lombok NoArgsConstructor with no access level- should be a utility class 1 From f9c140ed7af3f81ecc77eec370728b28a198c4cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 9 Aug 2021 19:22:47 +0200 Subject: [PATCH 062/104] Tests for fixed bugs --- .../java/rule/design/SwitchDensityRule.java | 2 +- .../java/rule/design/xml/SwitchDensity.xml | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java index b178c2861d..570a958ad0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java @@ -36,7 +36,7 @@ public class SwitchDensityRule extends AbstractJavaRulechainRule { .build(); public SwitchDensityRule() { - super(ASTSwitchStatement.class); + super(ASTSwitchStatement.class, ASTSwitchExpression.class); definePropertyDescriptor(REPORT_LEVEL); } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml index 8d3c5fc1e2..ff2a677572 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml @@ -26,6 +26,50 @@ public class SwitchDensity1 { } ]]> + + Switch expr + 4 + 1 + + + + Switch expr, composite label + 4 + 0 + + One stmt in one switch case, ok From 7796535a24057dc84a72efdcaaa8db970c2b375f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 16 Aug 2021 19:28:09 +0200 Subject: [PATCH 063/104] Bump ant from 1.10.9 to 1.10.11 CVE-2021-36374: https://github.com/advisories/GHSA-5v34-g2px-j4fw CVE-2021-36373: https://github.com/advisories/GHSA-q5r4-cfpx-h6fh --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9c5d2cc48a..982700e0cd 100644 --- a/pom.xml +++ b/pom.xml @@ -95,7 +95,7 @@ 8.42 3.1.2 3.14.0 - 1.10.9 + 1.10.11 3.2.0 4.7.2 From c961c744582580f5151b12ec36c23445ef6c2b08 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 16 Aug 2021 19:29:40 +0200 Subject: [PATCH 064/104] Bump commons-compress from 1.19 to 1.21 CVE-2021-36090: https://github.com/advisories/GHSA-mc84-pj99-q6hh CVE-2021-35516: https://github.com/advisories/GHSA-crv7-7245-f45f CVE-2021-35515: https://github.com/advisories/GHSA-7hfm-57qf-j43q CVE-2021-35517: https://github.com/advisories/GHSA-xqfj-vm6h-2x34 --- pmd-dist/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml index 7a0e2dacd7..01a5717499 100644 --- a/pmd-dist/pom.xml +++ b/pmd-dist/pom.xml @@ -227,7 +227,7 @@ org.apache.commons commons-compress - 1.19 + 1.21 test From f97347eb8639d5cf059a888a66ce653376935134 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Wed, 18 Aug 2021 14:47:56 -0500 Subject: [PATCH 065/104] ApexCRUDViolationRule now properly recurses into for-each loops. --- .../rule/security/ApexCRUDViolationRule.java | 48 +++++++++++++++---- .../rule/security/xml/ApexCRUDViolation.xml | 32 +++++++++++++ 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java index b1713937f5..45dc322bf6 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java @@ -18,6 +18,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.apex.ast.ASTAssignmentExpression; import net.sourceforge.pmd.lang.apex.ast.ASTBlockStatement; import net.sourceforge.pmd.lang.apex.ast.ASTDmlDeleteStatement; @@ -97,6 +98,17 @@ public class ApexCRUDViolationRule extends AbstractApexRule { setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); } + @Override + public void start(RuleContext ctx) { + varToTypeMapping.clear(); + typeToDMLOperationMapping.clear(); + checkedTypeToDMLOperationViaESAPI.clear(); + classMethods.clear(); + className = null; + super.start(ctx); + } + + @Override public Object visit(ASTUserClass node, Object data) { if (Helper.isTestMethodOrClass(node) || Helper.isSystemLevelClass(node)) { @@ -246,7 +258,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { checkForAccessibility(soql, data); } - return data; + return super.visit(node, data); } private void addVariableToMapping(final String variableName, final String type) { @@ -539,7 +551,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { } - private void validateCRUDCheckPresent(final ApexNode node, final Object data, final String crudMethod, + private boolean validateCRUDCheckPresent(final ApexNode node, final Object data, final String crudMethod, final String typeCheck) { boolean missingKey = !typeToDMLOperationMapping.containsKey(typeCheck); boolean isImproperDMLCheck = !isProperESAPICheckForDML(typeCheck, crudMethod); @@ -548,6 +560,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { //if condition returns true, add violation, otherwise return. if (isImproperDMLCheck && noSecurityEnforced) { addViolation(data, node); + return true; } } else { boolean properChecksHappened = false; @@ -566,8 +579,10 @@ public class ApexCRUDViolationRule extends AbstractApexRule { if (!properChecksHappened) { addViolation(data, node); + return true; } } + return false; } private void checkForAccessibility(final ASTSoqlExpression node, Object data) { @@ -591,7 +606,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { if (wrappingMethod != null) { returnType = getReturnType(wrappingMethod); } - + boolean violationAdded = false; final ASTVariableDeclaration variableDecl = node.getFirstParentOfType(ASTVariableDeclaration.class); if (variableDecl != null) { String type = variableDecl.getType(); @@ -600,15 +615,20 @@ public class ApexCRUDViolationRule extends AbstractApexRule { .append(":").append(type); if (typesFromSOQL.isEmpty()) { - validateCRUDCheckPresent(node, data, ANY, typeCheck.toString()); + violationAdded = validateCRUDCheckPresent(node, data, ANY, typeCheck.toString()); } else { for (String typeFromSOQL : typesFromSOQL) { - validateCRUDCheckPresent(node, data, ANY, typeFromSOQL); + violationAdded = validateCRUDCheckPresent(node, data, ANY, typeFromSOQL) || violationAdded; } } } + // If the node's already in violation, we don't need to keep checking. + if (violationAdded) { + return; + } + final ASTAssignmentExpression assignment = node.getFirstParentOfType(ASTAssignmentExpression.class); if (assignment != null) { final ASTVariableExpression variable = assignment.getFirstChildOfType(ASTVariableExpression.class); @@ -617,10 +637,10 @@ public class ApexCRUDViolationRule extends AbstractApexRule { if (varToTypeMapping.containsKey(variableWithClass)) { String type = varToTypeMapping.get(variableWithClass); if (typesFromSOQL.isEmpty()) { - validateCRUDCheckPresent(node, data, ANY, type); + violationAdded = validateCRUDCheckPresent(node, data, ANY, type); } else { for (String typeFromSOQL : typesFromSOQL) { - validateCRUDCheckPresent(node, data, ANY, typeFromSOQL); + violationAdded = validateCRUDCheckPresent(node, data, ANY, typeFromSOQL) || violationAdded; } } } @@ -628,17 +648,27 @@ public class ApexCRUDViolationRule extends AbstractApexRule { } + // If the node's already in violation, we don't need to keep checking. + if (violationAdded) { + return; + } + final ASTReturnStatement returnStatement = node.getFirstParentOfType(ASTReturnStatement.class); if (returnStatement != null) { if (typesFromSOQL.isEmpty()) { - validateCRUDCheckPresent(node, data, ANY, returnType); + violationAdded = validateCRUDCheckPresent(node, data, ANY, returnType); } else { for (String typeFromSOQL : typesFromSOQL) { - validateCRUDCheckPresent(node, data, ANY, typeFromSOQL); + violationAdded = validateCRUDCheckPresent(node, data, ANY, typeFromSOQL) || violationAdded; } } } + // If the node's already in violation, we don't need to keep checking. + if (violationAdded) { + return; + } + final ASTForEachStatement forEachStatement = node.getFirstParentOfType(ASTForEachStatement.class); if (forEachStatement != null) { if (typesFromSOQL.isEmpty()) { diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/security/xml/ApexCRUDViolation.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/security/xml/ApexCRUDViolation.xml index 6cd0a03809..697ec2b31b 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/security/xml/ApexCRUDViolation.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/security/xml/ApexCRUDViolation.xml @@ -1049,6 +1049,38 @@ public class Foo { ]]> + + No CRUD check inside for-each loop + 1 + (); + for (Id accId : accIds) { + Account acc = [SELECT Id FROM Account WHERE Id = :accId]; + } + } +} + ]]> + + + + Proper CRUD check inside for-each loop + 0 + (); + if (Account.sObjectType.getDescribe().isAccessible()) { + for (Id accId : accIds) { + Account a = [SELECT Id FROM Account WHERE Id = :accId]; + } + } + } +} + ]]> + + Proper CRUD check in SOQL for-loop with security enforced 0 From 389d2e855e1abdda09e461aeb0e86b24f9f64a94 Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Wed, 18 Aug 2021 16:29:27 -0500 Subject: [PATCH 066/104] Switched logical OR to assignment operator, and moved initialization of member variables to .start() method. --- .../rule/security/ApexCRUDViolationRule.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java index 45dc322bf6..dc8e8ee04a 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java @@ -86,10 +86,10 @@ public class ApexCRUDViolationRule extends AbstractApexRule { private static final Pattern WITH_SECURITY_ENFORCED = Pattern.compile("(?is).*[^']\\s*WITH\\s+SECURITY_ENFORCED\\s*[^']*"); - private final Map varToTypeMapping = new HashMap<>(); - private final ListMultimap typeToDMLOperationMapping = ArrayListMultimap.create(); - private final Map checkedTypeToDMLOperationViaESAPI = new HashMap<>(); - private final Map classMethods = new WeakHashMap<>(); + private Map varToTypeMapping; + private ListMultimap typeToDMLOperationMapping; + private Map checkedTypeToDMLOperationViaESAPI; + private Map classMethods; private String className; public ApexCRUDViolationRule() { @@ -100,10 +100,10 @@ public class ApexCRUDViolationRule extends AbstractApexRule { @Override public void start(RuleContext ctx) { - varToTypeMapping.clear(); - typeToDMLOperationMapping.clear(); - checkedTypeToDMLOperationViaESAPI.clear(); - classMethods.clear(); + varToTypeMapping = new HashMap<>(); + typeToDMLOperationMapping = ArrayListMultimap.create(); + checkedTypeToDMLOperationViaESAPI = new HashMap<>(); + classMethods = new WeakHashMap<>(); className = null; super.start(ctx); } @@ -618,7 +618,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { violationAdded = validateCRUDCheckPresent(node, data, ANY, typeCheck.toString()); } else { for (String typeFromSOQL : typesFromSOQL) { - violationAdded = validateCRUDCheckPresent(node, data, ANY, typeFromSOQL) || violationAdded; + violationAdded |= validateCRUDCheckPresent(node, data, ANY, typeFromSOQL); } } @@ -640,7 +640,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { violationAdded = validateCRUDCheckPresent(node, data, ANY, type); } else { for (String typeFromSOQL : typesFromSOQL) { - violationAdded = validateCRUDCheckPresent(node, data, ANY, typeFromSOQL) || violationAdded; + violationAdded |= validateCRUDCheckPresent(node, data, ANY, typeFromSOQL); } } } @@ -659,7 +659,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { violationAdded = validateCRUDCheckPresent(node, data, ANY, returnType); } else { for (String typeFromSOQL : typesFromSOQL) { - violationAdded = validateCRUDCheckPresent(node, data, ANY, typeFromSOQL) || violationAdded; + violationAdded |= validateCRUDCheckPresent(node, data, ANY, typeFromSOQL); } } } From 0a92718a4ec501a92dfbe9e58aed65d70ef605bf Mon Sep 17 00:00:00 2001 From: Joshua Feingold Date: Wed, 18 Aug 2021 16:49:04 -0500 Subject: [PATCH 067/104] Added comment explaining reason for decisions. --- .../pmd/lang/apex/rule/security/ApexCRUDViolationRule.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java index dc8e8ee04a..d4185600a6 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java @@ -100,6 +100,8 @@ public class ApexCRUDViolationRule extends AbstractApexRule { @Override public void start(RuleContext ctx) { + // At the start of each rule execution, these member variables need to be fresh. So they're initialized in the + // .start() method instead of the constructor, since .start() is called before every execution. varToTypeMapping = new HashMap<>(); typeToDMLOperationMapping = ArrayListMultimap.create(); checkedTypeToDMLOperationViaESAPI = new HashMap<>(); From f23d68e43230c3a0c0ff15b460f1aa0cd0d142c5 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 19 Aug 2021 17:59:03 +0200 Subject: [PATCH 068/104] Bump maven from 3.8.1 to 3.8.2 --- .mvn/wrapper/maven-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index ffdc10e59f..abd303b673 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,2 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.2/apache-maven-3.8.2-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar From 4516f396868e4f6f6cb378d61c65e3cc00112da5 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 19 Aug 2021 18:11:53 +0200 Subject: [PATCH 069/104] Bump build-tools from 15 to 16-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 982700e0cd..462fc1eb3b 100644 --- a/pom.xml +++ b/pom.xml @@ -105,7 +105,7 @@ -Xmx512m -Dfile.encoding=${project.build.sourceEncoding} - 15 + 16-SNAPSHOT 6.37.0 From 7e15f1781cc747d4df5c7a4b4ec3b595606c0b69 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 19 Aug 2021 18:38:58 +0200 Subject: [PATCH 070/104] [java] Suppress ReturnEmptyCollectionRatherThanNull violations in InferenceRuleType - as null is used as a additional value... and null/empty is different. --- .../java/typeresolution/typeinference/InferenceRuleType.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typeinference/InferenceRuleType.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typeinference/InferenceRuleType.java index 169c9a3965..0988fd4448 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typeinference/InferenceRuleType.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/typeinference/InferenceRuleType.java @@ -14,6 +14,10 @@ import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefin @Deprecated @InternalApi +// we use "null" if the constraint reduces to false. If we return a empty list, this indicates, +// that the constraint reduces to true without bounds. If there are bounds, then the returned list +// is not empty. +@SuppressWarnings("PMD.ReturnEmptyCollectionRatherThanNull") public enum InferenceRuleType { /** From 57707858475b1a1a40e845796ae579eb35b597b1 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 19 Aug 2021 19:23:01 +0200 Subject: [PATCH 071/104] [ci] Remove profile "pmd-dogfood" as this doesn't work well with release Use alternative solution by modifying the version directly in pom.xml for dogfood build. --- .ci/build.sh | 10 +++++----- pom.xml | 32 +++----------------------------- 2 files changed, 8 insertions(+), 34 deletions(-) diff --git a/.ci/build.sh b/.ci/build.sh index 0f5d26a996..31eadbebdd 100755 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -87,15 +87,15 @@ function build() { if pmd_ci_maven_isSnapshotBuild; then if [ "${PMD_CI_MAVEN_PROJECT_VERSION}" != "7.0.0-SNAPSHOT" ]; then pmd_ci_log_group_start "Executing PMD dogfood test with ${PMD_CI_MAVEN_PROJECT_VERSION}" - ./mvnw versions:set -DnewVersion=${PMD_CI_MAVEN_PROJECT_VERSION}-dogfood -DgenerateBackupPoms=false + ./mvnw versions:set -DnewVersion="${PMD_CI_MAVEN_PROJECT_VERSION}-dogfood" -DgenerateBackupPoms=false + sed -i 's/[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}.*<\/version>\( *\)/'"${PMD_CI_MAVEN_PROJECT_VERSION}"'<\/version>\1/' pom.xml ./mvnw verify --show-version --errors --batch-mode --no-transfer-progress "${PMD_MAVEN_EXTRA_OPTS[@]}" \ -DskipTests \ -Dmaven.javadoc.skip=true \ -Dmaven.source.skip=true \ - -Dcheckstyle.skip=true \ - -Ppmd-dogfood \ - -Dpmd.dogfood.version=${PMD_CI_MAVEN_PROJECT_VERSION} - ./mvnw versions:set -DnewVersion=${PMD_CI_MAVEN_PROJECT_VERSION} -DgenerateBackupPoms=false + -Dcheckstyle.skip=true + ./mvnw versions:set -DnewVersion="${PMD_CI_MAVEN_PROJECT_VERSION}" -DgenerateBackupPoms=false + git checkout -- pom.xml pmd_ci_log_group_end else # current maven-pmd-plugin is not compatible with PMD 7 yet. diff --git a/pom.xml b/pom.xml index 462fc1eb3b..e1c71b0c32 100644 --- a/pom.xml +++ b/pom.xml @@ -402,15 +402,16 @@ + net.sourceforge.pmd pmd-core - 6.37.0 + 6.37.0 net.sourceforge.pmd pmd-java - 6.37.0 + 6.37.0 @@ -1054,33 +1055,6 @@ - - - pmd-dogfood - - ${project.version} - - - - - org.apache.maven.plugins - maven-pmd-plugin - - - net.sourceforge.pmd - pmd-core - ${pmd.dogfood.version} - - - net.sourceforge.pmd - pmd-java - ${pmd.dogfood.version} - - - - - - From b379a670b1333e721081d58784a7d9779cfa74ff Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 Aug 2021 13:00:59 +0200 Subject: [PATCH 072/104] [java] Update rule UseEqualsToCompareStrings --- .ci/files/all-java.xml | 2 +- pmd-java/src/main/resources/category/java/errorprone.xml | 5 ++--- .../java/rule/errorprone/UseEqualsToCompareStringsTest.java | 1 - .../java/rule/errorprone/xml/UseEqualsToCompareStrings.xml | 4 ++++ 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.ci/files/all-java.xml b/.ci/files/all-java.xml index daa4af09bc..a4f21dddcd 100644 --- a/.ci/files/all-java.xml +++ b/.ci/files/all-java.xml @@ -268,7 +268,7 @@ - + diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 65e9fa0ff9..13d19fbc70 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -3405,15 +3405,14 @@ public class Main { externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#useequalstocomparestrings"> Using '==' or '!=' to compare strings only works if intern version is used on both sides. -Use the equals() method instead. +Use the `equals()` method instead. 3 diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/UseEqualsToCompareStringsTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/UseEqualsToCompareStringsTest.java index 2ac4f0f2dc..903c0d420d 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/UseEqualsToCompareStringsTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/UseEqualsToCompareStringsTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class UseEqualsToCompareStringsTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseEqualsToCompareStrings.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseEqualsToCompareStrings.xml index 934090bf33..cf3820d99b 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseEqualsToCompareStrings.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseEqualsToCompareStrings.xml @@ -144,6 +144,8 @@ public class O { #2979 UseEqualsToCompareStrings: FP with "var" variables 0 #2979 UseEqualsToCompareStrings: FP with "var" variables (control, types are explicit) 0 Date: Fri, 20 Aug 2021 14:53:40 +0200 Subject: [PATCH 073/104] [java] UseEqualsToCompareStrings: Fix false positives --- .../src/main/resources/category/java/errorprone.xml | 7 +++++-- .../rule/errorprone/xml/UseEqualsToCompareStrings.xml | 10 ++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 13d19fbc70..9a29397d1f 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -3404,7 +3404,9 @@ public class Main { class="net.sourceforge.pmd.lang.rule.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#useequalstocomparestrings"> -Using '==' or '!=' to compare strings only works if intern version is used on both sides. +Using '==' or '!=' to compare strings only works if the internalized string (`String#intern()`) +is used on both sides. + Use the `equals()` method instead. 3 @@ -3412,7 +3414,8 @@ Use the `equals()` method instead. diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseEqualsToCompareStrings.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseEqualsToCompareStrings.xml index cf3820d99b..d535631744 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseEqualsToCompareStrings.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseEqualsToCompareStrings.xml @@ -184,4 +184,14 @@ public class O { } ]]> + + + False positive with string concatentation + 0 + + From 742871afcc73f33ce387036399ecc8ad4a1be67d Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 Aug 2021 19:29:29 +0200 Subject: [PATCH 074/104] [doc] Add rule guidelines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Clément Fournier --- docs/_data/sidebars/pmd_sidebar.yml | 3 + .../major_contributions/rule_guidelines.md | 77 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 docs/pages/pmd/devdocs/major_contributions/rule_guidelines.md diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index 5244fdbdf8..501772784f 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -385,6 +385,9 @@ entries: - title: Major contributions output: web, pdf subfolderitems: + - title: Rule Guidelines + url: /pmd_devdocs_major_rule_guidelines.html + output: web, pdf - title: Adding a new language url: /pmd_devdocs_major_adding_new_language.html output: web, pdf diff --git a/docs/pages/pmd/devdocs/major_contributions/rule_guidelines.md b/docs/pages/pmd/devdocs/major_contributions/rule_guidelines.md new file mode 100644 index 0000000000..2b252ba996 --- /dev/null +++ b/docs/pages/pmd/devdocs/major_contributions/rule_guidelines.md @@ -0,0 +1,77 @@ +--- +title: Guidelines for standard rules +short_title: Rule guidelines +tags: [devdocs, extending] +summary: "Guidelines for rules that are included in the standard distribution" +last_updated: August, 2021 +sidebar: pmd_sidebar +permalink: pmd_devdocs_major_rule_guidelines.html +--- + +{% include note.html content=" +These guidelines are new and most rules don't follow these guidelines yet. +The goal is, that eventually all rules are updated. +" %} + +## Why do we need these guidelines? + +* To prevent low quality contributions +* To reduce time reviewing rules + +They just apply to rules included in the standard distribution. + +## Requirements for standard rules + +To be included in stock PMD, a rule needs + +* Broad applicability. It may be specific to a framework, but then, this framework should be widely used +* Solid documentation. See below +* If it's a performance rule: solid benchmarks. No micro-optimization rules +* No overlap with other rules + +## Dos/Don'ts (rule rules) + +* Rule naming + * **Don't** put the implementation of the rule in the name, because it will be awkward + if the scope of the rule changes + * Eg. *SwitchStmtShouldHaveDefault* -> since enums are a thing they don't necessarily + need to have a default anymore, they should be exhaustive. So the rule name lies now... + * Eg. *MissingBreakInSwitch* -> it's obvious that this is supposed to find fall-through + switches. Counting breaks is not a clever way to do it, but since it's in the name + we can't change it without renaming the rule. + * **Do** use rule names that name the underlying problem that violations exhibit + * Eg. instead of *SwitchStmtShouldHaveDefault*, use *NonExhaustiveSwitchStatement* -> this + is the problem, the description of the rule will clarify why it is a problem and how + to fix it (add a default, or add branches, or something else in the future) + * Eg. instead of *MissingBreakInSwitch*, use *SwitchCaseFallsThrough* + * **Don't** create several rules for instances of the same problem + * *EmptyIfStmt* and *EmptyWhileStmt* are actually the same problem, namely, + that there's useless syntax in the tree. + * **Don't** limit the rule name to strictly what the rule can do today + * Eg. *UnusedPrivateField* is a bad name. The problem is that there is an unused field, + not that it is private as well. If we had the ability to find unused package-private + fields, we would report them too. So if one day we get that ability, + using a name like *UnusedField* would allow us to keep the name. +* Rule messages + * **Do** write rule messages that neutrally point out a problem or construct that should + be reviewed ("Unnecessary parentheses") + * **Don't** write rule messages that give an order ("Avoid unnecessary parentheses") + especially without explaining why, like here + * **Don't** write rule messages that are tautological ("Unnecessary parentheses should be removed"). + The answer to this would be an annoyed "yes I know, so what?". +* **Do** use Markdown in rule descriptions and break lines at a reasonable 80 chars +* **Do** thoroughly comment rule examples. It must be obvious where to look +* **Do** comment your xpath expressions too + +## Rule description template + +* What the rule reports (1 summary line) +* Why the rule exists and where it might be useful (including, since which language version, etc) +* Blank line +* Explain all assumptions that the rule makes and keywords used in the previous paragraph. + ("overridden methods are ignored", "for the purposes of this rule, a 'visible' field is + non-private"). +* Describe known limitations if any +* Blank line +* For each property, explain how it modifies the assumptions and why you would want to use it. + **If you can't explain why it's there then it shouldn’t be there!** From 5a22ef104bd7da582a36b8cedb7c5c608f8c9e92 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 22 Aug 2021 14:31:18 +0200 Subject: [PATCH 075/104] [doc] Document new xpath fun "pmd:fileName()" --- docs/_data/xpath_funs.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/_data/xpath_funs.yml b/docs/_data/xpath_funs.yml index 222f3b70f2..1936d7cfb4 100644 --- a/docs/_data/xpath_funs.yml +++ b/docs/_data/xpath_funs.yml @@ -10,6 +10,22 @@ aliases: - &needs_typenode "The context node must be a {% jdoc jast::TypeNode %}" langs: + - name: "Any language" + ns: "pmd" + funs: + - name: fileName + returnType: "xs:string" + shortDescription: "Returns the current filename" + description: "Returns the current simple filename without path but including the extension. + This can be used to write rules that check filename naming conventions. + +

This function is available since PMD 6.38.0.

" + notes: "The function can be called on any node." + examples: + - code: "//b[pmd:fileName() = 'Foo.xml']" + outcome: "Matches any `<b>` tags in files called `Foo.xml`." + + - name: "Java" ns: "pmd-java" funs: From e9e51ddfdb772ff77850ef4391608df843ec2117 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 22 Aug 2021 14:35:33 +0200 Subject: [PATCH 076/104] [doc] Update release notes (#3447, #3446) --- docs/pages/release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index b8f8783555..adc34dc633 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,6 +16,9 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues +* core + * [#3446](https://github.com/pmd/pmd/issues/3446): \[core] Allow XPath rules to access the current file name + ### API Changes ### External Contributions From e22a43452789bf31692949684ba37311a9ea95df Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 22 Aug 2021 14:51:49 +0200 Subject: [PATCH 077/104] [doc] Update release notes (#3462, #3484, #3470) --- docs/pages/release_notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 5c1bcda9b0..a33cdf24c4 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,6 +16,9 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues +* apex + * [#3462](https://github.com/pmd/pmd/issues/3462): \[apex] SOQL performed in a for-each loop doesn't trigger ApexCRUDViolationRule + * [#3484](https://github.com/pmd/pmd/issues/3484): \[apex] ApexCRUDViolationRule maintains state across files * java-bestpractices * [#3403](https://github.com/pmd/pmd/issues/3403): \[java] MethodNamingConventions junit5TestPattern does not detect parameterized tests @@ -24,6 +27,7 @@ This is a {{ site.pmd.release_type }} release. ### External Contributions * [#3445](https://github.com/pmd/pmd/pull/3445): \[java] Fix #3403 about MethodNamingConventions and JUnit5 parameterized tests - [Cyril Sicard](https://github.com/CyrilSicard) +* [#3470](https://github.com/pmd/pmd/pull/3470): \[apex] Fix ApexCRUDViolationRule - add super call - [Josh Feingold](https://github.com/jfeingold35) {% endtocmaker %} From b49093daf4973037ea4136fedfb704d450ecf80d Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 22 Aug 2021 17:03:19 +0200 Subject: [PATCH 078/104] [doc] UseUtilityClass: The property `ignoredAnnotations` has been removed. --- docs/pages/7_0_0_release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index 2b4c261c86..9bf6eeb791 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -100,6 +100,7 @@ conversions that may be made implicit. * {% rule "java/codestyle/UseDiamondOperator" %}: the property `java7Compatibility` is removed. The rule now handles Java 7 properly without a property. * {% rule "java/design/SingularField" %}: Properties `checkInnerClasses` and `disallowNotAssignment` are removed. The rule is now more precise and will check these cases properly. +* {% rule "java/design/UseUtilityClass" %}: The property `ignoredAnnotations` has been removed. #### Deprecated Rules From b0b20873162bda29c6c048a363b5897eb8bdb3e7 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 22 Aug 2021 17:19:44 +0200 Subject: [PATCH 079/104] [doc] Fix more old rule references --- docs/pages/next_major_development.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/pages/next_major_development.md b/docs/pages/next_major_development.md index e259e6545a..62394bcaf9 100644 --- a/docs/pages/next_major_development.md +++ b/docs/pages/next_major_development.md @@ -1352,22 +1352,22 @@ large projects, with many duplications, it was causing `OutOfMemoryError`s (see is deprecated in favour of {% rule "java/bestpractices/UnusedAssignment" %} (`java-bestpractices`), which was introduced in PMD 6.26.0. -* The java rule {% rule "java/codestyle/DefaultPackage" %} has been deprecated in favor of +* The java rule `DefaultPackage` (java-codestyle) has been deprecated in favor of {% rule "java/codestyle/CommentDefaultAccessModifier" %}. -* The Java rule {% rule "java/errorprone/CloneThrowsCloneNotSupportedException" %} has been deprecated without +* The Java rule `CloneThrowsCloneNotSupportedException` (java-errorprone) has been deprecated without replacement. * 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 %} + * `UseAssertEqualsInsteadOfAssertTrue` (java-bestpractices) + * `UseAssertNullInsteadOfAssertTrue` (java-bestpractices) + * `UseAssertSameInsteadOfAssertTrue` (java-bestpractices) + * `UseAssertTrueInsteadOfAssertEquals` (java-bestpractices) + * `SimplifyBooleanAssertion` (java-design) -* The Java rule {% rule java/errorprone/ReturnEmptyArrayRatherThanNull %} is deprecated and removed from +* The Java rule `ReturnEmptyArrayRatherThanNull` (java-errorprone) is deprecated and removed from the quickstart ruleset, as the new rule {% rule java/errorprone/ReturnEmptyCollectionRatherThanNull %} supersedes it. From 2df54339e713a1926c848a897c247e2850b69be0 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 22 Aug 2021 20:15:36 +0200 Subject: [PATCH 080/104] Add missing @Override --- .../sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java | 1 + 1 file changed, 1 insertion(+) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java index 570a958ad0..e9eeca0c27 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java @@ -45,6 +45,7 @@ public class SwitchDensityRule extends AbstractJavaRulechainRule { return visitSwitchLike(node, data); } + @Override public Object visit(ASTSwitchExpression node, Object data) { return visitSwitchLike(node, data); } From ea79544a59fc5be617c612fbceb8208735218fc2 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 22 Aug 2021 21:40:52 +0200 Subject: [PATCH 081/104] [java] SwitchDensity: Fix FP with default label --- .../java/rule/design/SwitchDensityRule.java | 5 ++++- .../java/rule/design/xml/SwitchDensity.xml | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java index e9eeca0c27..f1aef397b3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.rule.design; import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; import net.sourceforge.pmd.lang.java.ast.ASTStatement; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchBranch; import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression; import net.sourceforge.pmd.lang.java.ast.ASTSwitchLike; import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; @@ -53,7 +54,9 @@ public class SwitchDensityRule extends AbstractJavaRulechainRule { public Void visitSwitchLike(ASTSwitchLike node, Object data) { // note: this does not cross find boundaries. int stmtCount = node.descendants(ASTStatement.class).count(); - int labelCount = node.getBranches().sumBy(branch -> branch.getLabel().getExprList().count()); + int labelCount = node.getBranches() + .map(ASTSwitchBranch::getLabel) + .sumBy(label -> label.isDefault() ? 1 : label.getExprList().count()); // note: if labelCount is zero, double division will produce NaN, not ArithmeticException double density = stmtCount / (double) labelCount; diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml index ff2a677572..7024c73d82 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml @@ -113,6 +113,28 @@ public class SwitchDensity3 { } } } +} + ]]>
+ + + + False positive with default label + 10 + 0 + From 07a736095961b589523007ecef4cd15d69e1eacb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 23 Aug 2021 15:25:50 +0200 Subject: [PATCH 082/104] Fix comment about double division Co-authored-by: Andreas Dangel --- .../pmd/lang/java/rule/design/SwitchDensityRule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java index f1aef397b3..21f8d2bcb1 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java @@ -58,7 +58,7 @@ public class SwitchDensityRule extends AbstractJavaRulechainRule { .map(ASTSwitchBranch::getLabel) .sumBy(label -> label.isDefault() ? 1 : label.getExprList().count()); - // note: if labelCount is zero, double division will produce NaN, not ArithmeticException + // note: if labelCount is zero, double division will produce +Infinity or NaN, not ArithmeticException double density = stmtCount / (double) labelCount; if (density >= getProperty(REPORT_LEVEL)) { addViolation(data, node); From def74df7a98f2cd2b5b313dd6a58d884c9c1b73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 23 Aug 2021 15:26:51 +0200 Subject: [PATCH 083/104] Add test with empty switch stmt --- .../lang/java/rule/design/xml/SwitchDensity.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml index 7024c73d82..b5e408cdb5 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/SwitchDensity.xml @@ -135,6 +135,22 @@ public class SwitchWithDefault break; } } +} + ]]> + + + Empty switch + 0 + From af51d2d33198eb844f1ca6fb83f07a31f37803fa Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 23 Aug 2021 19:19:50 +0200 Subject: [PATCH 084/104] Bump build-tools from 16-SNAPSHOT to 16 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e1c71b0c32..79ab82a595 100644 --- a/pom.xml +++ b/pom.xml @@ -105,7 +105,7 @@ -Xmx512m -Dfile.encoding=${project.build.sourceEncoding} - 16-SNAPSHOT + 16 6.37.0 From 5aa23354d4a0219a220d4713fed90735f321c610 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 28 Aug 2021 17:15:29 +0200 Subject: [PATCH 085/104] Prepare pmd release 6.38.0 --- docs/_config.yml | 2 +- docs/pages/next_major_development.md | 4 ++++ docs/pages/release_notes.md | 9 +++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/_config.yml b/docs/_config.yml index 20ec943b05..66de4727aa 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,7 +1,7 @@ repository: pmd/pmd pmd: - version: 6.38.0-SNAPSHOT + version: 6.38.0 previous_version: 6.37.0 date: 28-August-2021 release_type: minor diff --git a/docs/pages/next_major_development.md b/docs/pages/next_major_development.md index f44548b64c..7e9878aac1 100644 --- a/docs/pages/next_major_development.md +++ b/docs/pages/next_major_development.md @@ -125,6 +125,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.38.0 + +No changes. + #### 6.37.0 ##### PMD CLI diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index ee489a311b..a813784db9 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -12,8 +12,6 @@ This is a {{ site.pmd.release_type }} release. {% tocmaker is_release_notes_processor %} -### New and noteworthy - ### Fixed Issues * apex @@ -24,12 +22,15 @@ This is a {{ site.pmd.release_type }} release. * java-bestpractices * [#3403](https://github.com/pmd/pmd/issues/3403): \[java] MethodNamingConventions junit5TestPattern does not detect parameterized tests -### API Changes - ### External Contributions * [#3445](https://github.com/pmd/pmd/pull/3445): \[java] Fix #3403 about MethodNamingConventions and JUnit5 parameterized tests - [Cyril Sicard](https://github.com/CyrilSicard) * [#3470](https://github.com/pmd/pmd/pull/3470): \[apex] Fix ApexCRUDViolationRule - add super call - [Josh Feingold](https://github.com/jfeingold35) +### Stats +* 32 commits +* 8 closed tickets & PRs +* Days since last release: 27 + {% endtocmaker %} From 7d11a020521d587cf4631c44512464ad1f4e83cb Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 28 Aug 2021 17:27:12 +0200 Subject: [PATCH 086/104] [maven-release-plugin] prepare release pmd_releases/6.38.0 --- pmd-apex-jorje/pom.xml | 2 +- pmd-apex/pom.xml | 2 +- pmd-core/pom.xml | 2 +- pmd-cpp/pom.xml | 2 +- pmd-cs/pom.xml | 2 +- pmd-dart/pom.xml | 2 +- pmd-dist/pom.xml | 2 +- pmd-doc/pom.xml | 2 +- pmd-fortran/pom.xml | 2 +- pmd-go/pom.xml | 2 +- pmd-groovy/pom.xml | 2 +- pmd-java/pom.xml | 2 +- pmd-java8/pom.xml | 2 +- pmd-javascript/pom.xml | 2 +- pmd-jsp/pom.xml | 2 +- pmd-kotlin/pom.xml | 2 +- pmd-lang-test/pom.xml | 2 +- pmd-lua/pom.xml | 2 +- pmd-matlab/pom.xml | 2 +- pmd-modelica/pom.xml | 2 +- pmd-objectivec/pom.xml | 2 +- pmd-perl/pom.xml | 2 +- pmd-php/pom.xml | 2 +- pmd-plsql/pom.xml | 2 +- pmd-python/pom.xml | 2 +- pmd-ruby/pom.xml | 2 +- pmd-scala-modules/pmd-scala-common/pom.xml | 2 +- pmd-scala-modules/pmd-scala_2.12/pom.xml | 2 +- pmd-scala-modules/pmd-scala_2.13/pom.xml | 2 +- pmd-scala/pom.xml | 2 +- pmd-swift/pom.xml | 2 +- pmd-test/pom.xml | 2 +- pmd-visualforce/pom.xml | 2 +- pmd-vm/pom.xml | 2 +- pmd-xml/pom.xml | 2 +- pom.xml | 6 +++--- 36 files changed, 38 insertions(+), 38 deletions(-) diff --git a/pmd-apex-jorje/pom.xml b/pmd-apex-jorje/pom.xml index 1fbad57b7e..9e7797c1a0 100644 --- a/pmd-apex-jorje/pom.xml +++ b/pmd-apex-jorje/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml index 07347a24df..fc2dc18c97 100644 --- a/pmd-apex/pom.xml +++ b/pmd-apex/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml index 279e93c935..a853324572 100644 --- a/pmd-core/pom.xml +++ b/pmd-core/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-cpp/pom.xml b/pmd-cpp/pom.xml index 040ec9a4c8..e904f94310 100644 --- a/pmd-cpp/pom.xml +++ b/pmd-cpp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-cs/pom.xml b/pmd-cs/pom.xml index 9c4c6528ec..8676c300ed 100644 --- a/pmd-cs/pom.xml +++ b/pmd-cs/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-dart/pom.xml b/pmd-dart/pom.xml index 3f432eeaba..593cae49e6 100644 --- a/pmd-dart/pom.xml +++ b/pmd-dart/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml index 01a5717499..96567c0945 100644 --- a/pmd-dist/pom.xml +++ b/pmd-dist/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml index 34a735f5da..5be8d38519 100644 --- a/pmd-doc/pom.xml +++ b/pmd-doc/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-fortran/pom.xml b/pmd-fortran/pom.xml index 9aa757cd84..8151b1be0b 100644 --- a/pmd-fortran/pom.xml +++ b/pmd-fortran/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-go/pom.xml b/pmd-go/pom.xml index de0d29ef42..0ac2282133 100644 --- a/pmd-go/pom.xml +++ b/pmd-go/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-groovy/pom.xml b/pmd-groovy/pom.xml index 81748d5c73..7a62176a5a 100644 --- a/pmd-groovy/pom.xml +++ b/pmd-groovy/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index 2fd7d4c0d2..41007a63ae 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-java8/pom.xml b/pmd-java8/pom.xml index 9f08b33dcb..a2ceee7662 100644 --- a/pmd-java8/pom.xml +++ b/pmd-java8/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml index 7089c683b1..c4c6fd829b 100644 --- a/pmd-javascript/pom.xml +++ b/pmd-javascript/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-jsp/pom.xml b/pmd-jsp/pom.xml index e8e2536616..e48bfb3a73 100644 --- a/pmd-jsp/pom.xml +++ b/pmd-jsp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-kotlin/pom.xml b/pmd-kotlin/pom.xml index fa532436ef..b91618b041 100644 --- a/pmd-kotlin/pom.xml +++ b/pmd-kotlin/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index f3b99287f3..30d4e457fb 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -12,7 +12,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-lua/pom.xml b/pmd-lua/pom.xml index c690bc4986..52ca77c3b8 100644 --- a/pmd-lua/pom.xml +++ b/pmd-lua/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-matlab/pom.xml b/pmd-matlab/pom.xml index 52a2ca2dd8..5ad7c8c167 100644 --- a/pmd-matlab/pom.xml +++ b/pmd-matlab/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-modelica/pom.xml b/pmd-modelica/pom.xml index 7bd4582829..19345a2d0d 100644 --- a/pmd-modelica/pom.xml +++ b/pmd-modelica/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-objectivec/pom.xml b/pmd-objectivec/pom.xml index 165166a1fb..634e510e78 100644 --- a/pmd-objectivec/pom.xml +++ b/pmd-objectivec/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-perl/pom.xml b/pmd-perl/pom.xml index 24082d4cca..bec68400a4 100644 --- a/pmd-perl/pom.xml +++ b/pmd-perl/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-php/pom.xml b/pmd-php/pom.xml index 891dc1f892..5b038d8131 100644 --- a/pmd-php/pom.xml +++ b/pmd-php/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-plsql/pom.xml b/pmd-plsql/pom.xml index c01f0d428f..9e67746d5d 100644 --- a/pmd-plsql/pom.xml +++ b/pmd-plsql/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-python/pom.xml b/pmd-python/pom.xml index 462e7151d2..6acd5aa48e 100644 --- a/pmd-python/pom.xml +++ b/pmd-python/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-ruby/pom.xml b/pmd-ruby/pom.xml index 131fc26250..5cfaa54293 100644 --- a/pmd-ruby/pom.xml +++ b/pmd-ruby/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-scala-modules/pmd-scala-common/pom.xml b/pmd-scala-modules/pmd-scala-common/pom.xml index e927783cbf..2eaa97d43e 100644 --- a/pmd-scala-modules/pmd-scala-common/pom.xml +++ b/pmd-scala-modules/pmd-scala-common/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../.. diff --git a/pmd-scala-modules/pmd-scala_2.12/pom.xml b/pmd-scala-modules/pmd-scala_2.12/pom.xml index 6928da5017..0597ee1666 100644 --- a/pmd-scala-modules/pmd-scala_2.12/pom.xml +++ b/pmd-scala-modules/pmd-scala_2.12/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd-scala-common - 6.38.0-SNAPSHOT + 6.38.0 ../pmd-scala-common diff --git a/pmd-scala-modules/pmd-scala_2.13/pom.xml b/pmd-scala-modules/pmd-scala_2.13/pom.xml index 189491bca6..355af52da1 100644 --- a/pmd-scala-modules/pmd-scala_2.13/pom.xml +++ b/pmd-scala-modules/pmd-scala_2.13/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd-scala-common - 6.38.0-SNAPSHOT + 6.38.0 ../pmd-scala-common diff --git a/pmd-scala/pom.xml b/pmd-scala/pom.xml index 375743dd0a..112f61c9c8 100644 --- a/pmd-scala/pom.xml +++ b/pmd-scala/pom.xml @@ -9,7 +9,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-swift/pom.xml b/pmd-swift/pom.xml index cd03470d2b..9f7e9c6fb8 100644 --- a/pmd-swift/pom.xml +++ b/pmd-swift/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml index cf40c4c74b..8b891f4341 100644 --- a/pmd-test/pom.xml +++ b/pmd-test/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-visualforce/pom.xml b/pmd-visualforce/pom.xml index 7d944dc67a..69f0443217 100644 --- a/pmd-visualforce/pom.xml +++ b/pmd-visualforce/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-vm/pom.xml b/pmd-vm/pom.xml index c55b5d7bc0..dadbfce74c 100644 --- a/pmd-vm/pom.xml +++ b/pmd-vm/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml index 887b071d97..b9dae8ddcd 100644 --- a/pmd-xml/pom.xml +++ b/pmd-xml/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 ../ diff --git a/pom.xml b/pom.xml index 79ab82a595..e00741d95f 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 net.sourceforge.pmd pmd - 6.38.0-SNAPSHOT + 6.38.0 pom PMD @@ -55,7 +55,7 @@ scm:git:git://github.com/pmd/pmd.git scm:git:ssh://git@github.com/pmd/pmd.git https://github.com/pmd/pmd - HEAD + pmd_releases/6.38.0 @@ -76,7 +76,7 @@ - 2021-07-31T17:02:07Z + 2021-08-28T15:15:57Z 7 From 65af1c06756581c1d2ea6d72baa1213ec29c2eeb Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 28 Aug 2021 17:27:18 +0200 Subject: [PATCH 087/104] [maven-release-plugin] prepare for next development iteration --- pmd-apex-jorje/pom.xml | 2 +- pmd-apex/pom.xml | 2 +- pmd-core/pom.xml | 2 +- pmd-cpp/pom.xml | 2 +- pmd-cs/pom.xml | 2 +- pmd-dart/pom.xml | 2 +- pmd-dist/pom.xml | 2 +- pmd-doc/pom.xml | 2 +- pmd-fortran/pom.xml | 2 +- pmd-go/pom.xml | 2 +- pmd-groovy/pom.xml | 2 +- pmd-java/pom.xml | 2 +- pmd-java8/pom.xml | 2 +- pmd-javascript/pom.xml | 2 +- pmd-jsp/pom.xml | 2 +- pmd-kotlin/pom.xml | 2 +- pmd-lang-test/pom.xml | 2 +- pmd-lua/pom.xml | 2 +- pmd-matlab/pom.xml | 2 +- pmd-modelica/pom.xml | 2 +- pmd-objectivec/pom.xml | 2 +- pmd-perl/pom.xml | 2 +- pmd-php/pom.xml | 2 +- pmd-plsql/pom.xml | 2 +- pmd-python/pom.xml | 2 +- pmd-ruby/pom.xml | 2 +- pmd-scala-modules/pmd-scala-common/pom.xml | 2 +- pmd-scala-modules/pmd-scala_2.12/pom.xml | 2 +- pmd-scala-modules/pmd-scala_2.13/pom.xml | 2 +- pmd-scala/pom.xml | 2 +- pmd-swift/pom.xml | 2 +- pmd-test/pom.xml | 2 +- pmd-visualforce/pom.xml | 2 +- pmd-vm/pom.xml | 2 +- pmd-xml/pom.xml | 2 +- pom.xml | 6 +++--- 36 files changed, 38 insertions(+), 38 deletions(-) diff --git a/pmd-apex-jorje/pom.xml b/pmd-apex-jorje/pom.xml index 9e7797c1a0..824781c888 100644 --- a/pmd-apex-jorje/pom.xml +++ b/pmd-apex-jorje/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml index fc2dc18c97..a237d22c10 100644 --- a/pmd-apex/pom.xml +++ b/pmd-apex/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml index a853324572..21ba064316 100644 --- a/pmd-core/pom.xml +++ b/pmd-core/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-cpp/pom.xml b/pmd-cpp/pom.xml index e904f94310..ba1caf686a 100644 --- a/pmd-cpp/pom.xml +++ b/pmd-cpp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-cs/pom.xml b/pmd-cs/pom.xml index 8676c300ed..efbf30aa36 100644 --- a/pmd-cs/pom.xml +++ b/pmd-cs/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-dart/pom.xml b/pmd-dart/pom.xml index 593cae49e6..bfc7940b4a 100644 --- a/pmd-dart/pom.xml +++ b/pmd-dart/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml index 96567c0945..1e6d52d9ea 100644 --- a/pmd-dist/pom.xml +++ b/pmd-dist/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml index 5be8d38519..8899408858 100644 --- a/pmd-doc/pom.xml +++ b/pmd-doc/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-fortran/pom.xml b/pmd-fortran/pom.xml index 8151b1be0b..41841531ee 100644 --- a/pmd-fortran/pom.xml +++ b/pmd-fortran/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-go/pom.xml b/pmd-go/pom.xml index 0ac2282133..6c815d641e 100644 --- a/pmd-go/pom.xml +++ b/pmd-go/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-groovy/pom.xml b/pmd-groovy/pom.xml index 7a62176a5a..5f1f1906dd 100644 --- a/pmd-groovy/pom.xml +++ b/pmd-groovy/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index 41007a63ae..de21159108 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-java8/pom.xml b/pmd-java8/pom.xml index a2ceee7662..810b45c57d 100644 --- a/pmd-java8/pom.xml +++ b/pmd-java8/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml index c4c6fd829b..5c7e3cdc08 100644 --- a/pmd-javascript/pom.xml +++ b/pmd-javascript/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-jsp/pom.xml b/pmd-jsp/pom.xml index e48bfb3a73..b4afbe5cc3 100644 --- a/pmd-jsp/pom.xml +++ b/pmd-jsp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-kotlin/pom.xml b/pmd-kotlin/pom.xml index b91618b041..e8d27046c5 100644 --- a/pmd-kotlin/pom.xml +++ b/pmd-kotlin/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index 30d4e457fb..a87a15a527 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -12,7 +12,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-lua/pom.xml b/pmd-lua/pom.xml index 52ca77c3b8..60c1a09194 100644 --- a/pmd-lua/pom.xml +++ b/pmd-lua/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-matlab/pom.xml b/pmd-matlab/pom.xml index 5ad7c8c167..44b504386a 100644 --- a/pmd-matlab/pom.xml +++ b/pmd-matlab/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-modelica/pom.xml b/pmd-modelica/pom.xml index 19345a2d0d..5a23db9a16 100644 --- a/pmd-modelica/pom.xml +++ b/pmd-modelica/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-objectivec/pom.xml b/pmd-objectivec/pom.xml index 634e510e78..78e8dd6c82 100644 --- a/pmd-objectivec/pom.xml +++ b/pmd-objectivec/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-perl/pom.xml b/pmd-perl/pom.xml index bec68400a4..2ec89ac4c5 100644 --- a/pmd-perl/pom.xml +++ b/pmd-perl/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-php/pom.xml b/pmd-php/pom.xml index 5b038d8131..688298ba20 100644 --- a/pmd-php/pom.xml +++ b/pmd-php/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-plsql/pom.xml b/pmd-plsql/pom.xml index 9e67746d5d..5155396d01 100644 --- a/pmd-plsql/pom.xml +++ b/pmd-plsql/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-python/pom.xml b/pmd-python/pom.xml index 6acd5aa48e..a8a5031698 100644 --- a/pmd-python/pom.xml +++ b/pmd-python/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-ruby/pom.xml b/pmd-ruby/pom.xml index 5cfaa54293..1e95ffd567 100644 --- a/pmd-ruby/pom.xml +++ b/pmd-ruby/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-scala-modules/pmd-scala-common/pom.xml b/pmd-scala-modules/pmd-scala-common/pom.xml index 2eaa97d43e..102dfd20e6 100644 --- a/pmd-scala-modules/pmd-scala-common/pom.xml +++ b/pmd-scala-modules/pmd-scala-common/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../.. diff --git a/pmd-scala-modules/pmd-scala_2.12/pom.xml b/pmd-scala-modules/pmd-scala_2.12/pom.xml index 0597ee1666..3ca7828336 100644 --- a/pmd-scala-modules/pmd-scala_2.12/pom.xml +++ b/pmd-scala-modules/pmd-scala_2.12/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd-scala-common - 6.38.0 + 6.39.0-SNAPSHOT ../pmd-scala-common diff --git a/pmd-scala-modules/pmd-scala_2.13/pom.xml b/pmd-scala-modules/pmd-scala_2.13/pom.xml index 355af52da1..917a2be7fd 100644 --- a/pmd-scala-modules/pmd-scala_2.13/pom.xml +++ b/pmd-scala-modules/pmd-scala_2.13/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd-scala-common - 6.38.0 + 6.39.0-SNAPSHOT ../pmd-scala-common diff --git a/pmd-scala/pom.xml b/pmd-scala/pom.xml index 112f61c9c8..cb195d9de5 100644 --- a/pmd-scala/pom.xml +++ b/pmd-scala/pom.xml @@ -9,7 +9,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-swift/pom.xml b/pmd-swift/pom.xml index 9f7e9c6fb8..cf2a6b8ec7 100644 --- a/pmd-swift/pom.xml +++ b/pmd-swift/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml index 8b891f4341..e477838f3e 100644 --- a/pmd-test/pom.xml +++ b/pmd-test/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-visualforce/pom.xml b/pmd-visualforce/pom.xml index 69f0443217..244d643bd8 100644 --- a/pmd-visualforce/pom.xml +++ b/pmd-visualforce/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-vm/pom.xml b/pmd-vm/pom.xml index dadbfce74c..83dc162d3b 100644 --- a/pmd-vm/pom.xml +++ b/pmd-vm/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml index b9dae8ddcd..aac6c46cae 100644 --- a/pmd-xml/pom.xml +++ b/pmd-xml/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT ../ diff --git a/pom.xml b/pom.xml index e00741d95f..5a3447b089 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 net.sourceforge.pmd pmd - 6.38.0 + 6.39.0-SNAPSHOT pom PMD @@ -55,7 +55,7 @@ scm:git:git://github.com/pmd/pmd.git scm:git:ssh://git@github.com/pmd/pmd.git https://github.com/pmd/pmd - pmd_releases/6.38.0 + HEAD @@ -76,7 +76,7 @@ - 2021-08-28T15:15:57Z + 2021-08-28T15:27:18Z 7 From c38e9d40e68a611813fca5653cb8f7dff2dff1ac Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 28 Aug 2021 17:31:18 +0200 Subject: [PATCH 088/104] Prepare next development version --- docs/_config.yml | 6 +++--- docs/pages/release_notes.md | 18 +++--------------- docs/pages/release_notes_old.md | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/docs/_config.yml b/docs/_config.yml index 66de4727aa..1c09b2cb15 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,9 +1,9 @@ repository: pmd/pmd pmd: - version: 6.38.0 - previous_version: 6.37.0 - date: 28-August-2021 + version: 6.39.0-SNAPSHOT + previous_version: 6.38.0 + date: 25-September-2021 release_type: minor # release types: major, minor, bugfix diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index a813784db9..b8f8783555 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -12,25 +12,13 @@ This is a {{ site.pmd.release_type }} release. {% tocmaker is_release_notes_processor %} +### New and noteworthy + ### Fixed Issues -* apex - * [#3462](https://github.com/pmd/pmd/issues/3462): \[apex] SOQL performed in a for-each loop doesn't trigger ApexCRUDViolationRule - * [#3484](https://github.com/pmd/pmd/issues/3484): \[apex] ApexCRUDViolationRule maintains state across files -* core - * [#3446](https://github.com/pmd/pmd/issues/3446): \[core] Allow XPath rules to access the current file name -* java-bestpractices - * [#3403](https://github.com/pmd/pmd/issues/3403): \[java] MethodNamingConventions junit5TestPattern does not detect parameterized tests +### API Changes ### External Contributions -* [#3445](https://github.com/pmd/pmd/pull/3445): \[java] Fix #3403 about MethodNamingConventions and JUnit5 parameterized tests - [Cyril Sicard](https://github.com/CyrilSicard) -* [#3470](https://github.com/pmd/pmd/pull/3470): \[apex] Fix ApexCRUDViolationRule - add super call - [Josh Feingold](https://github.com/jfeingold35) - -### Stats -* 32 commits -* 8 closed tickets & PRs -* Days since last release: 27 - {% endtocmaker %} diff --git a/docs/pages/release_notes_old.md b/docs/pages/release_notes_old.md index c3f16303a4..ea280928cd 100644 --- a/docs/pages/release_notes_old.md +++ b/docs/pages/release_notes_old.md @@ -5,6 +5,38 @@ permalink: pmd_release_notes_old.html Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases +## 28-August-2021 - 6.38.0 + +The PMD team is pleased to announce PMD 6.38.0. + +This is a minor release. + +### Table Of Contents + +* [Fixed Issues](#fixed-issues) +* [External Contributions](#external-contributions) +* [Stats](#stats) + +### Fixed Issues + +* apex + * [#3462](https://github.com/pmd/pmd/issues/3462): \[apex] SOQL performed in a for-each loop doesn't trigger ApexCRUDViolationRule + * [#3484](https://github.com/pmd/pmd/issues/3484): \[apex] ApexCRUDViolationRule maintains state across files +* core + * [#3446](https://github.com/pmd/pmd/issues/3446): \[core] Allow XPath rules to access the current file name +* java-bestpractices + * [#3403](https://github.com/pmd/pmd/issues/3403): \[java] MethodNamingConventions junit5TestPattern does not detect parameterized tests + +### External Contributions + +* [#3445](https://github.com/pmd/pmd/pull/3445): \[java] Fix #3403 about MethodNamingConventions and JUnit5 parameterized tests - [Cyril Sicard](https://github.com/CyrilSicard) +* [#3470](https://github.com/pmd/pmd/pull/3470): \[apex] Fix ApexCRUDViolationRule - add super call - [Josh Feingold](https://github.com/jfeingold35) + +### Stats +* 32 commits +* 8 closed tickets & PRs +* Days since last release: 27 + ## 28-August-2021 - 6.38.0-SNAPSHOT The PMD team is pleased to announce PMD 6.38.0-SNAPSHOT. From 46e70a0d8fe13e479024b623e1802e30f1921971 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 28 Aug 2021 18:05:06 +0200 Subject: [PATCH 089/104] Bump pmd from 6.37.0 to 6.38.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5a3447b089..9cc497cc59 100644 --- a/pom.xml +++ b/pom.xml @@ -406,12 +406,12 @@ net.sourceforge.pmd pmd-core - 6.37.0 + 6.38.0 net.sourceforge.pmd pmd-java - 6.37.0 + 6.38.0 From e6d2b5815fdf6416279f68efbebb815239e805b6 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 30 Aug 2021 20:21:33 +0200 Subject: [PATCH 090/104] [java] AvoidAccessibilityAlteration: add tests and fix rule --- .../resources/category/java/errorprone.xml | 85 +++++----- .../AvoidAccessibilityAlterationTest.java | 11 ++ .../xml/AvoidAccessibilityAlteration.xml | 153 ++++++++++++++++++ 3 files changed, 203 insertions(+), 46 deletions(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidAccessibilityAlterationTest.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index a92d8216e9..53340d181f 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -60,9 +60,13 @@ public class StaticField { class="net.sourceforge.pmd.lang.rule.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#avoidaccessibilityalteration"> -Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and setAccessible(), -as the interface PrivilegedAction, allow for the runtime alteration of variable, class, or -method visibility, even if they are private. This violates the principle of encapsulation. +Methods such as `getDeclaredConstructors()`, `getDeclaredMethods()`, and `getDeclaredFields()` also +return private constructors, methods and fields. These can be made accessible by calling `setAccessible(true)`. +This gives access to normally protected data which violates the principle of encapsulation. + +This rule detects calls to `setAccessible` and finds possible accessibility alterations. +If the call to `setAccessible` is wrapped within a `PrivilegedAction`, then the access alteration +is assumed to be deliberate and is not reported. 3 @@ -70,60 +74,49 @@ method visibility, even if they are private. This violates the principle of enca constructor = this.getClass().getDeclaredConstructor(String.class); + // call to forbidden setAccessible + constructor.setAccessible(true); - // Possible call to forbidden PrivilegedAction - PrivilegedAction priv = (PrivilegedAction) new Object(); priv.run(); - } + Method privateMethod = this.getClass().getDeclaredMethod("aPrivateMethod"); + // call to forbidden setAccessible + privateMethod.setAccessible(true); + + // deliberate accessibility alteration + String privateField = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public String run() { + try { + Field field = Violation.class.getDeclaredField("aPrivateField"); + field.setAccessible(true); + return (String) field.get(null); + } catch (ReflectiveOperationException | SecurityException e) { + throw new RuntimeException(e); + } + } + }); + } } ]]> diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidAccessibilityAlterationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidAccessibilityAlterationTest.java new file mode 100644 index 0000000000..cd5c41a995 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidAccessibilityAlterationTest.java @@ -0,0 +1,11 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.errorprone; + +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class AvoidAccessibilityAlterationTest extends PmdRuleTst { + // no additional unit tests +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml new file mode 100644 index 0000000000..8fd4834958 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml @@ -0,0 +1,153 @@ + + + + + Example code snippet + 2 + 11,15 + constructor = this.getClass().getDeclaredConstructor(String.class); + // call to forbidden setAccessible + constructor.setAccessible(true); + + Method privateMethod = this.getClass().getDeclaredMethod("aPrivateMethod"); + // call to forbidden setAccessible + privateMethod.setAccessible(true); + + // deliberate accessibility alteration + String privateField = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public String run() { + try { + Field field = Violation.class.getDeclaredField("aPrivateField"); + field.setAccessible(true); + return (String) field.get(null); + } catch (ReflectiveOperationException | SecurityException e) { + throw new RuntimeException(e); + } + } + }); + } +} + ]]> + + + + Detect calls to setAccessible + 9 + 9,12,13,16,19,20,23,26,27 + constructor : this.getClass().getConstructors()) { + constructor.setAccessible(true); + } + Constructor[] constructors = this.getClass().getConstructors(); + AccessibleObject.setAccessible(constructors, true); + Constructor.setAccessible(constructors, true); + + for (Method method : this.getClass().getMethods()) { + method.setAccessible(true); + } + Method[] methods = this.getClass().getMethods(); + AccessibleObject.setAccessible(methods, true); + Method.setAccessible(methods, true); + + for (Field field : this.getClass().getFields()) { + field.setAccessible(true); + } + Field[] fields = this.getClass().getFields(); + AccessibleObject.setAccessible(fields, true); + Field.setAccessible(fields, true); + } +} + ]]> + + + + + Make sure to detect method call chains + 6 + 3,4,5,6,7,8 + + + + + Anonymous privileged action is OK + 0 + () { + @Override + public Method[] run() { + Method[] declaredMethods = Violation.class.getDeclaredMethods(); + AccessibleObject.setAccessible(declaredMethods, true); + return declaredMethods; + } + }); + try { + methods[0].invoke(null); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + } +} + ]]> + + + + Inner class privileged action is OK + 0 + { + @Override + public Field[] run() { + Field[] declaredFields = Violation.class.getDeclaredFields(); + AccessibleObject.setAccessible(declaredFields, true); + return declaredFields; + } + } +} + ]]> + + \ No newline at end of file From c00d84aa9afe4b47ccd2e638b09bfd961078caed Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 2 Sep 2021 16:18:03 +0200 Subject: [PATCH 091/104] [core] Fix XPath rulechain optimization bug For XPath query "//dummyNode[ends-with(@Image, 'foo')][pmd-dummy:typeIs('bar')]" we lost the first condition (ends-with...) and only applied the second one (pmd-dummy:typeIs). --- .../rule/xpath/internal/RuleChainAnalyzer.java | 14 +++++++++++++- .../lang/rule/xpath/SaxonXPathRuleQueryTest.java | 10 ++++++++++ .../xml/AvoidAccessibilityAlteration.xml | 15 +++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java index e093c07dd7..6a704b2035 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java @@ -4,8 +4,10 @@ package net.sourceforge.pmd.lang.rule.xpath.internal; +import java.util.ArrayDeque; import java.util.Collections; import java.util.Comparator; +import java.util.Deque; import net.sourceforge.pmd.lang.ast.Node; @@ -69,7 +71,17 @@ public class RuleChainAnalyzer extends SaxonExprVisitor { Expression step = newPath.getStepExpression(); if (step instanceof FilterExpression) { FilterExpression filterExpression = (FilterExpression) newPath.getStepExpression(); - result = new FilterExpression(new AxisExpression(Axis.SELF, null), filterExpression.getFilter()); + + Deque filters = new ArrayDeque<>(); + Expression walker = filterExpression; + while (walker instanceof FilterExpression) { + filters.push(((FilterExpression) walker).getFilter()); + walker = ((FilterExpression) walker).getBaseExpression(); + } + result = new FilterExpression(new AxisExpression(Axis.SELF, null), filters.pop()); + while (!filters.isEmpty()) { + result = new FilterExpression(result, filters.pop()); + } rootElementReplaced = true; } else if (step instanceof AxisExpression) { if (newPath.getStartExpression() instanceof RootExpression) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java index bfe925bac3..48c2ad3694 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java @@ -193,6 +193,16 @@ public class SaxonXPathRuleQueryTest { assertExpression("DocumentSorter((LetExpression(LazyExpression(CardinalityChecker(ItemChecker(UntypedAtomicConverter(Atomizer($testClassPattern))))), (((/)/descendant::element(dummyNode, xs:anyType))[matches(CardinalityChecker(ItemChecker(UntypedAtomicConverter(Atomizer(attribute::attribute(SimpleName, xs:anyAtomicType))))), $zz:zz952562199)]))/child::element(foo, xs:anyType)))", query.nodeNameToXPaths.get(SaxonXPathRuleQuery.AST_ROOT).get(0)); } + @Test + public void ruleChainVisitWithTwoFunctions() { + SaxonXPathRuleQuery query = createQuery("//dummyNode[ends-with(@Image, 'foo')][pmd-dummy:typeIs('bar')]"); + List ruleChainVisits = query.getRuleChainVisits(); + Assert.assertEquals(1, ruleChainVisits.size()); + Assert.assertTrue(ruleChainVisits.contains("dummyNode")); + Assert.assertEquals(2, query.nodeNameToXPaths.size()); + assertExpression("((self::node()[ends-with(CardinalityChecker(ItemChecker(UntypedAtomicConverter(Atomizer(attribute::attribute(Image, xs:anyAtomicType))))), \"foo\")])[pmd-dummy:typeIs(\"bar\")])", query.nodeNameToXPaths.get("dummyNode").get(0)); + } + private static void assertExpression(String expected, Expression actual) { Assert.assertEquals(normalizeExprDump(expected), normalizeExprDump(actual.toString())); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml index 8fd4834958..9e215b28eb 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml @@ -150,4 +150,19 @@ public class Violation { } ]]> + + + false positive when accessible object is used as primary prefix + 0 + > list = new ArrayList<>(); + Constructor ctor = NoViolation.class.getConstructor(); + list.add(ctor); +} } + ]]> + \ No newline at end of file From 1f520a9f6f3c9cecf70136c93c5e807010bceae6 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 2 Sep 2021 16:18:28 +0200 Subject: [PATCH 092/104] [java] AvoidAccessibilityAlteration - improve rule message --- pmd-java/src/main/resources/category/java/errorprone.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 53340d181f..0bfa9e4138 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -56,7 +56,7 @@ public class StaticField { From 83d56dab2844cdac1ca8680ad6ef00b0cc0cf703 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 3 Sep 2021 09:31:03 +0200 Subject: [PATCH 093/104] [java] AvoidAccessibilityAlteration: allow setAccessible(false) This restores the cheks for the Java language access control. --- .../main/resources/category/java/errorprone.xml | 1 + .../xml/AvoidAccessibilityAlteration.xml | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 0bfa9e4138..475e47af45 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -76,6 +76,7 @@ is assumed to be deliberate and is not reported. + + + setAccessible(false) is ok + 0 + constructor = this.getClass().getDeclaredConstructor(String.class); + // call to setAccessible with false - that's ok + constructor.setAccessible(false); + } +} + ]]> + \ No newline at end of file From 1138b96b81cd7c65bd4691dc7f881b2a9ca9cc7a Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 3 Sep 2021 09:35:07 +0200 Subject: [PATCH 094/104] [doc] Update release notes (#3493, #3010) --- docs/pages/release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index b8f8783555..cc61c77fe9 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,6 +16,9 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues +* java-errorprone + * [#3493](https://github.com/pmd/pmd/pull/3493): \[java] AvoidAccessibilityAlteration: add tests and fix rule + ### API Changes ### External Contributions From 3dd4eda7eac9bb88ff497d1df2e92ada130f2f85 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 3 Sep 2021 09:41:15 +0200 Subject: [PATCH 095/104] [java] AvoidAccessibilityAlteration: more tests for setAccessible(false) --- .../rule/errorprone/xml/AvoidAccessibilityAlteration.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml index d8d654159c..66f18866b4 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/AvoidAccessibilityAlteration.xml @@ -170,6 +170,7 @@ public class NoViolation { { setAccessible(false) is ok 0 constructor = this.getClass().getDeclaredConstructor(String.class); // call to setAccessible with false - that's ok constructor.setAccessible(false); + + Constructor[] constructors = this.getClass().getConstructors(); + AccessibleObject.setAccessible(constructors, false); + Constructor.setAccessible(constructors, false); } } ]]> From 8ce8da1ea0ab2536620a51d10105995b4624e86d Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 4 Sep 2021 10:33:38 +0200 Subject: [PATCH 096/104] [doc] Update release notes, refs #1881 --- docs/pages/7_0_0_release_notes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index cb206bc2da..d01bca241a 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -259,7 +259,8 @@ The metrics framework has been made simpler and more general. * [#1658](https://github.com/pmd/pmd/pull/1658): \[core] Node support for Antlr-based languages - [Matías Fraga](https://github.com/matifraga) * [#1698](https://github.com/pmd/pmd/pull/1698): \[core] [swift] Antlr Base Parser adapter and Swift Implementation - [Lucas Soncini](https://github.com/lsoncini) * [#1774](https://github.com/pmd/pmd/pull/1774): \[core] Antlr visitor rules - [Lucas Soncini](https://github.com/lsoncini) -* [#1877](https://github.com/pmd/pmd/pull/1877): \[swift] Feature/swift rules - [Matias Fraga](https://github.com/matifraga) +* [#1877](https://github.com/pmd/pmd/pull/1877): \[swift] Feature/swift rules - [Matías Fraga](https://github.com/matifraga) +* [#1881](https://github.com/pmd/pmd/pull/1881): \[doc] Add ANTLR documentation - [Matías Fraga](https://github.com/matifraga) * [#1882](https://github.com/pmd/pmd/pull/1882): \[swift] UnavailableFunction Swift rule - [Tomás de Lucca](https://github.com/tomidelucca) * [#2830](https://github.com/pmd/pmd/pull/2830): \[apex] Apexlink POC - [Kevin Jones](https://github.com/nawforce) From 973df243b79ff2caf20c1f6dbc7778691d242ac4 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 4 Sep 2021 10:51:18 +0200 Subject: [PATCH 097/104] [doc] Update ANTLR documentation --- docs/_data/sidebars/pmd_sidebar.yml | 7 +- .../adding_a_new_antlr_based_language.md | 155 +++++++++++++----- .../adding_a_new_javacc_based_language.md | 2 +- docs/pages/pmd/projectdocs/credits.md | 2 +- .../pmd/lang/swift/SwiftLanguageModule.java | 2 +- 5 files changed, 122 insertions(+), 46 deletions(-) diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index 5492c3d2f0..c4d8aad28c 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -400,8 +400,11 @@ entries: - title: Rule Guidelines url: /pmd_devdocs_major_rule_guidelines.html output: web, pdf - - title: Adding a new language - url: /pmd_devdocs_major_adding_new_language.html + - title: Adding a new language (JavaCC) + url: /pmd_devdocs_major_adding_new_language_javacc.html + output: web, pdf + - title: Adding a new language (Antlr) + url: /pmd_devdocs_major_adding_new_language_antlr.html output: web, pdf - title: Adding a new CPD language url: /pmd_devdocs_major_adding_new_cpd_language.html diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md index cee98699b2..7f156054d7 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_antlr_based_language.md @@ -5,8 +5,11 @@ tags: [devdocs, extending] summary: "How to add a new language to PMD using ANTLR grammar." last_updated: July 21, 2019 sidebar: pmd_sidebar -permalink: pmd_devdocs_major_adding_new_language.html +permalink: pmd_devdocs_major_adding_new_language_antlr.html folder: pmd/devdocs + +# needs to be changed to branch master instead of pmd/7.0.x +# https://github.com/pmd/pmd/blob/pmd/7.0.x -> https://github.com/pmd/pmd/blob/master --- @@ -14,70 +17,140 @@ folder: pmd/devdocs * See pmd-swift for examples. ## 2. Implement an AST parser for your language -* ANTLR gives you this for free. +* ANTLR will generate the parser for you based on the grammar file. The grammar file needs to be placed in the + folder `src/main/antlr4` in the appropriate sub package `ast` of the language. E.g. for swift, the grammar + file is [Swift.g4](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/antlr4/net/sourceforge/pmd/lang/swift/ast/Swift.g4) + and is placed in the package `net.sourceforge.pmd.lang.swift.ast`. ## 3. Create AST node classes -* We provide an [`AntlrBaseNode`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AntlrBaseNode.java). -* We override ANTLR auto-generated code to provide this for free, you need to add an ANT script similar to the [swift script](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/ant/antlr4.xml). -* You can extend `AntlrBaseNode` and override any method that you require, but on most cases you won't need to do anything. +* The individual AST nodes are generated, but you need to define the common interface for them. +* You need a need to define the supertype interface for all nodes of the language. For that, we provide + [`AntlrNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrNode.java). +* See [`SwiftNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftNode.java) + as an example. +* Additionally, you need several base classes: + * a language specific inner node - these nodes represent the production rules from the grammar. + In Antlr, they are called "ParserRuleContext". We call them "InnerNode". Use the + base class from pmd-core + [`BaseAntlrInnerNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/BaseAntlrInnerNode.java) + . And example is [`SwiftInnerNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftInnerNode.java). + * a language specific root node - this provides the root of the AST and our parser will return + subtypes of this node. The root node itself is a "InnerNode". + See [`SwiftRootNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftRootNode.java). + * a language specific terminal node. + See [`SwiftTerminalNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftTerminalNode.java). + * a language specific error node. + See [`SwiftErrorNode`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftErrorNode.java). +* In order for the generated code to match and use our custom classes, we have a common ant script, that fiddles with + the generated code. The ant script is [`antlr4-wrapper.xml`](https://github.com/pmd/pmd/blob/pmd/7.0.x/antlr4-wrapper.xml) and + does not need to be adjusted - it has plenty of parameters to set. The ant script is added in the + language module's `pom.xml` where the parameters are set (e.g. name of root name class). Have a look at + Swift's example: [`pmd-swift/pom.xml`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/pom.xml). +* You can add additional methods in your "InnerNode" (e.g. `SwiftInnerNode`) that are available on all nodes. + But on most cases you won't need to do anything. -## 4. Compile your parser -* We override ANTLR auto-generated code to provide this for free, similar to the step before, you will need to use the ANT script. -* You should review the [swift pom](https://github.com/pmd/pmd/blob/master/pmd-swift/pom.xml). Don't forget to enable visitor generation property. +## 4. Generate your parser +* Make sure, you have the property `true` in your `pom.xml` file. +* This is just a matter of building the language module. ANTLR is called via ant, and this step is added + to the phase `generate-sources`. So you can just call e.g. `./mvnw generate-source -pl pmd-swift` to + have the parser generated. +* The generated code will be placed under `target/generated-sources/antlr4` and will not be committed to + source control. +* You should review the [swift pom](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/pom.xml). ## 5. Create a TokenManager -* We provide a default implementation using [`AntlrTokenManager`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrTokenManager.java) that uses an [`AntlrTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java). -* You must create your own `AntlrTokenizer` such as we do with [`SwiftTokenizer`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftTokenizer.java). -* If you wish to filter specific tokens you can create your own implementation of [`BaseTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) as we did with [`SwiftTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). If you don't need a custom token filter, you can return an instance of [`AntlrTokenFilter`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). +* This is needed to support CPD (copy paste detection) +* We provide a default implementation using [`AntlrTokenManager`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/cpd/internal/AntlrTokenizer.java). +* You must create your own "AntlrTokenizer" such as we do with + [`SwiftTokenizer`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/cpd/SwiftTokenizer.java). +* If you wish to filter specific tokens (e.g. comments to support CPD suppression via "CPD-OFF" and "CPD-ON") + you can create your own implementation of + [`AntlrTokenFilter`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java). + You'll need to override then the protected method `getTokenFilter(AntlrTokenManager)` + and return your custom filter. See the tokenizer for C# as an exmaple: + [`CsTokenizer`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-cs/src/main/java/net/sourceforge/pmd/cpd/CsTokenizer.java). + + If you don't need a custom token filter, you don't need to override the method. It returns the default + `AntlrTokenFilter` which doesn't filter anything. ## 6. Create a PMD parser “adapter” -* We provide a [`BaseParser`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrBaseParser.java) implementation that you need to extend to create your own adapter as we do with [`SwiftParserAdapter`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftParserAdapter.java). +* Create your own parser, that adapts the ANLTR interface to PMD's parser interface. +* We provide a [`AntlrBaseParser`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrBaseParser.java) + implementation that you need to extend to create your own adapter as we do with + [`PmdSwiftParser`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/PmdSwiftParser.java). ## 7. Create a rule violation factory -* We provide a [`AntlrRuleViolationFactory`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleViolationFactory.java) as base implementation, you can use that for most scenarios. -* The purpose of this class is to create a rule violation instance for your handler (spoiler). +* This is an optional step. Most like, the default implementation will do what you need. + The default implementation is [`DefaultRuleViolationFactory`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/impl/DefaultRuleViolationFactory.java). +* The purpose of a rule violation factory is to create a rule violation instance for your handler (spoiler). + In case you want to provide additional data in your rule violation, you can create a custom one. However, + adding additional date here is discouraged, as you would need a custom renderer to actually use this + additional data. Such extensions are not language agnostic. ## 8. Create a version handler -* Now you need to create your version handler, as we did with [`SwiftHandler`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftHandler.java). +* Now you need to create your version handler, as we did with [`SwiftHandler`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftHandler.java). * This class is sort of a gateway between PMD and all parsing logic specific to your language. It has 2 purposes: - * `getRuleViolationFactory` method returns an instance of your rule violation factory *(see step #7)* - * `getParser` returns an instance of your parser adapter *(see step #6)* + * `getRuleViolationFactory` method returns an instance of your rule violation factory *(see step #7)*. + By default, this returns the default rule violation factory. + * `getParser` returns an instance of your parser adapter *(see step #6)*. + That's the only method, that needs to be implemented here. ## 9. Create a parser visitor adapter -* We provide an [`AbstractAntlrVisitor`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AbstractAntlrVisitor.java) as default implementation, to be able to use this you should also add it to the ANT script we talked about on step #3 -* The purpose of this class is to serve as a pass-through `visitor` implementation, which, for all AST types in your language, just executes visit on the base AST type +* A parser visitor adapter is not needed anymore with PMD 7. The visitor interface now provides a default + implementation. +* The visitor for ANTLR based AST is generated along the parser from the ANTLR grammar file. The + base interface for a visitor is [`AstVisitor`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AstVisitor.java). +* The generated visitor class for Swift is called `SwiftVisitor`. +* In order to help use this visitor later on, a base visitor class should be created. + See [`SwiftVisitorBase`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/ast/SwiftVisitorBase.java) + as an example. ## 10. Create a rule chain visitor -* We provide an [`AntlrRuleChainVisitor`](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/lang/antlr/AntlrRuleChainVisitor.java), you can use that for most scenarios. -* If you wish to create your own, you should `implement` two `important` methods: - * `indexNodes` generates a map of "node type" to "list of nodes of that type". This is used to visit all applicable nodes when a rule is applied. - * `visit` method should evaluate what kind of rule is being applied, and execute appropriate logic. Usually it will just check if the rule is a "parser visitor" kind of rule specific to your language, then execute the visitor. If it’s an XPath rule, then we just need to execute evaluate on that. +* This step is not needed anymore. For using rule chain, there is no additional adjustment necessary anymore + in the languages. +* This feature has been merged into AbstractRule via the overridable method + {% jdoc !!core::lang.rule.AbstractRule#buildTargetSelector() %}. Individual rules can make use of this optimization + by overriding this method and return an appropriate RuleTargetSelector. ## 11. Make PMD recognize your language -* Create your own subclass of `net.sourceforge.pmd.lang.BaseLanguageModule`, see Swift as an example. -* You’ll need to refer the rule chain visitor created in step #10. -* Add for each version of your language a call to `addVersion` in your language module’s constructor. +* Create your own subclass of `net.sourceforge.pmd.lang.BaseLanguageModule`, see Swift as an example: + [`SwiftLanguageModule`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java). +* Add your default version with `addDefaultVersion` in your language module's constructor. +* Add for each additional version of your language a call to `addVersion` as well. * Create the service registration via the text file `src/main/resources/META-INF/services/net.sourceforge.pmd.lang.Language`. Add your fully qualified class name as a single line into it. ## 12. Create an abstract rule class for the language -* You need to create your own `AbstractRule`, our `AbstractAntlrVisitor` implements this and makes the connection with ANTLR via our ANT script (see step #3). -* You will have an auto-generated `XBaseVisitor` class (similar to `SwiftBaseVisitor`) that you will have to extend as we did with [`AbstractSwiftRule`](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java). -* All other rules for your language should extend this class. The purpose of this class is to implement visit methods for all AST types to simply delegate to default behavior. This is useful because most rules care only about specific AST nodes, but PMD needs to know what to do with each node - so this just lets you use default behavior for nodes you don’t care about. +* You need to create your own `AbstractRule` in order to interface your language with PMD's generic rule + execution. +* See [`AbstractSwiftRule`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/AbstractSwiftRule.java) as an example. +* While the rule basically just extends + [`AntlrBaseRule`](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/antlr4/AntlrBaseRule.java) without adding anything, every language should have its own base class for rule. + This helps to organize the code. +* All other rules for your language should extend this class. The purpose of this class is to provide a visitor + via the method `buildVisitor()` for analyzing the AST. The provided visitor only implements the visit methods + for specific AST nodes. The other node types use the default behavior and you don't need to care about them. ## 13. Create rules -* Creating rules is already pretty well documented in PMD - and it’s no different for a new language, except you may have different AST nodes. -* PMD supports 2 types of rules, through visitors or XPath. -* To add a visitor rule: - * You need to extend the abstract rule you created on the previous step, you can use [this rule](https://github.com/pmd/pmd/blob/master/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/rule/bestpractices/ProhibitedInterfaceBuilderRule.java) as an example. -* To add an XPath rule you can follow our [guide](https://pmd.github.io/pmd-6.15.0/pmd_userdocs_extending_writing_xpath_rules.html). +* Creating rules is already pretty well documented in PMD - and it’s no different for a new language, except you + may have different AST nodes. +* PMD supports 2 types of rules, through visitors or XPath. +* To add a visitor rule: + * You need to extend the abstract rule you created on the previous step, you can use the swift + rule [UnavailableFunctionRule](https://github.com/pmd/pmd/blob/pmd/7.0.x/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/rule/bestpractices/UnavailableFunctionRule.java) + as an example. Note, that all rule classes should be suffixed with `Rule` and should be placed + in a package the corresponds to their category. +* To add an XPath rule you can follow our guide [Writing XPath Rules](pmd_userdocs_extending_writing_xpath_rules.html). ## 14. Test the rules -* See BasicRulesTest for example -* You have to create a rule set for your language *(see vm/basic.xml for example)* -* For each rule in this set you want to test, call `addRule` method in setUp of the unit test - * This triggers the unit test to read the corresponding XML file with rule test data *(see `EmptyForeachStmtRule.xml` for example)* - * This test XML file contains sample pieces of code which should trigger a specified number of violations of this rule. The unit test will execute the rule on this piece of code, and verify that the number of violations matches -* To verify the validity of the created ruleset, create a subclass of `AbstractRuleSetFactoryTest` (*see `RuleSetFactoryTest` in pmd-vm for example)*. +* See UnavailableFunctionRuleTest for example. Each rule has it's own test class. +* You have to create the category rule set for your language *(see pmd-swift/src/main/resources/bestpractices.xml for example)* +* When executing the test class + * this triggers the unit test to read the corresponding XML file with the rule test data + *(see `UnavailableFunctionRule.xml` for example)* + * This test XML file contains sample pieces of code which should trigger a specified number of + violations of this rule. The unit test will execute the rule on this piece of code, and verify + that the number of violations matches. +* To verify the validity of all the created rulesets, create a subclass of `AbstractRuleSetFactoryTest` (*see `RuleSetFactoryTest` in pmd-swift for example)*. This will load all rulesets and verify, that all required attributes are provided. - *Note:* You'll need to add your ruleset to `rulesets.properties`, so that it can be found. + *Note:* You'll need to add your ruleset to `categories.properties`, so that it can be found. diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md index 4b7965edee..c3b470247c 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_a_new_javacc_based_language.md @@ -5,7 +5,7 @@ tags: [devdocs, extending] summary: "How to add a new language to PMD using JAVACC grammar." last_updated: October 5, 2019 sidebar: pmd_sidebar -permalink: pmd_devdocs_major_adding_new_language.html +permalink: pmd_devdocs_major_adding_new_language_javacc.html folder: pmd/devdocs --- diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index d1a771e9ec..41b5a8a3d6 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -428,7 +428,7 @@ author: Tom Copeland * Mat Booth - #1109 Patch to build with Javacc 5.0 * Stuart Turton - for PLSQL support. See also [pldoc](http://pldoc.sourceforge.net/) * Andrey Utis - for adding Apache Velocity as a new language and writing up a - [howto for adding new languages](pmd_devdocs_major_adding_new_language.html). + [howto for adding new languages JavaCC](pmd_devdocs_major_adding_new_language_javacc.html). * Alan Hohn - for adding Standard and modified cyclomatic complexity rules * Jan van Nunen - for adding CPD support for Matlab, Objective-C, Python, Scala and various bug fixes * Juan Martín Sotuyo Dodero - for many bugfixes/pull requests improving Java grammar and performance diff --git a/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java b/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java index e36a3c0af7..6dff8fbf56 100644 --- a/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java +++ b/pmd-swift/src/main/java/net/sourceforge/pmd/lang/swift/SwiftLanguageModule.java @@ -21,6 +21,6 @@ public class SwiftLanguageModule extends BaseLanguageModule { */ public SwiftLanguageModule() { super(NAME, null, TERSE_NAME, "swift"); - addVersion("", new SwiftHandler(), true); + addDefaultVersion("", new SwiftHandler()); } } From 8fd326ca0a002f9d8a744a82bb75d451393fcbad Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 10 Sep 2021 10:06:44 +0200 Subject: [PATCH 098/104] [core] Fix XPath rulechain with combined node tests For now, we don't try to optimize the expression for rulechain. Although it would be theoretically possible: the manual optimization looks like variant3 in the unit test. --- .../xpath/internal/RuleChainAnalyzer.java | 6 +++- .../rule/xpath/SaxonXPathRuleQueryTest.java | 31 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java index e093c07dd7..bceefc45c7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java @@ -17,6 +17,7 @@ import net.sf.saxon.expr.LazyExpression; import net.sf.saxon.expr.PathExpression; import net.sf.saxon.expr.RootExpression; import net.sf.saxon.om.Axis; +import net.sf.saxon.pattern.CombinedNodeTest; import net.sf.saxon.pattern.NameTest; import net.sf.saxon.sort.DocumentSorter; import net.sf.saxon.type.Type; @@ -40,6 +41,7 @@ public class RuleChainAnalyzer extends SaxonExprVisitor { private boolean rootElementReplaced; private boolean insideLazyExpression; private boolean foundPathInsideLazy; + private boolean foundCombinedNodeTest; public RuleChainAnalyzer(Configuration currentConfiguration) { this.configuration = currentConfiguration; @@ -93,13 +95,15 @@ public class RuleChainAnalyzer extends SaxonExprVisitor { @Override public Expression visit(AxisExpression e) { - if (rootElement == null && e.getNodeTest() instanceof NameTest) { + if (rootElement == null && e.getNodeTest() instanceof NameTest && !foundCombinedNodeTest) { NameTest test = (NameTest) e.getNodeTest(); if (test.getPrimitiveType() == Type.ELEMENT && e.getAxis() == Axis.DESCENDANT) { rootElement = configuration.getNamePool().getClarkName(test.getFingerprint()); } else if (test.getPrimitiveType() == Type.ELEMENT && e.getAxis() == Axis.CHILD) { rootElement = configuration.getNamePool().getClarkName(test.getFingerprint()); } + } else if (e.getNodeTest() instanceof CombinedNodeTest) { + foundCombinedNodeTest = true; } return super.visit(e); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java index bfe925bac3..d0ca1bef67 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java @@ -256,4 +256,35 @@ public class SaxonXPathRuleQueryTest { List ruleChainVisits = query.getRuleChainVisits(); Assert.assertEquals(0, ruleChainVisits.size()); } + + @Test + public void ruleChainWithUnionsCustomFunctionsVariant1() { + SaxonXPathRuleQuery query = createQuery("(//ForStatement | //WhileStatement | //DoStatement)//dummyNode[pmd-dummy:typeIs(@Image)]"); + List ruleChainVisits = query.getRuleChainVisits(); + Assert.assertEquals(0, ruleChainVisits.size()); + } + + @Test + public void ruleChainWithUnionsCustomFunctionsVariant2() { + SaxonXPathRuleQuery query = createQuery("//(ForStatement | WhileStatement | DoStatement)//dummyNode[pmd-dummy:typeIs(@Image)]"); + List ruleChainVisits = query.getRuleChainVisits(); + Assert.assertEquals(0, ruleChainVisits.size()); + } + + @Test + public void ruleChainWithUnionsCustomFunctionsVariant3() { + SaxonXPathRuleQuery query = createQuery("//ForStatement//dummyNode[pmd-dummy:typeIs(@Image)]" + + " | //WhileStatement//dummyNode[pmd-dummy:typeIs(@Image)]" + + " | //DoStatement//dummyNode[pmd-dummy:typeIs(@Image)]"); + List ruleChainVisits = query.getRuleChainVisits(); + Assert.assertEquals(3, ruleChainVisits.size()); + Assert.assertTrue(ruleChainVisits.contains("ForStatement")); + Assert.assertTrue(ruleChainVisits.contains("WhileStatement")); + Assert.assertTrue(ruleChainVisits.contains("DoStatement")); + + final String expectedSubexpression = "((self::node()/descendant-or-self::node())/(child::element(dummyNode, xs:anyType)[pmd-dummy:typeIs(CardinalityChecker(ItemChecker(UntypedAtomicConverter(Atomizer(attribute::attribute(Image, xs:anyAtomicType))))))]))"; + assertExpression(expectedSubexpression, query.nodeNameToXPaths.get("ForStatement").get(0)); + assertExpression(expectedSubexpression, query.nodeNameToXPaths.get("WhileStatement").get(0)); + assertExpression(expectedSubexpression, query.nodeNameToXPaths.get("DoStatement").get(0)); + } } From 414b5c9a89b5e37e7a1be91894ec85ddf2cd68c7 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 10 Sep 2021 10:18:46 +0200 Subject: [PATCH 099/104] [doc] Update release notes (#3499) --- docs/pages/release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index b8f8783555..77a8a3a44b 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,6 +16,9 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues +* core + * [#3499](https://github.com/pmd/pmd/pull/3499): \[core] Fix XPath rulechain with combined node tests + ### API Changes ### External Contributions From a7f3e388f1ff2fd9cb8a423de82113070f1147a9 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 10 Sep 2021 11:25:32 +0200 Subject: [PATCH 100/104] [java] UnnecessaryBoxing - check for Integer.valueOf(String) calls This implements the last point of #2973 --- .../rule/codestyle/UnnecessaryBoxingRule.java | 34 ++++++ .../resources/category/java/codestyle.xml | 19 +-- .../rule/codestyle/xml/UnnecessaryBoxing.xml | 115 +++++++++++++++++- 3 files changed, 160 insertions(+), 8 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryBoxingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryBoxingRule.java index 3ac1554cac..33f56b41b8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryBoxingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryBoxingRule.java @@ -8,6 +8,8 @@ import static net.sourceforge.pmd.util.CollectionUtil.setOf; import java.util.Set; +import org.apache.commons.lang3.StringUtils; + import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; import net.sourceforge.pmd.lang.java.ast.ASTExpression; @@ -19,6 +21,7 @@ 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.TypeTestUtil; import net.sourceforge.pmd.lang.java.types.ast.ExprContext; /** @@ -71,6 +74,8 @@ public class UnnecessaryBoxingRule extends AbstractJavaRulechainRule { if (isValueOf && isWrapperValueOf(m)) { checkBox((RuleContext) data, "boxing", node, node.getArguments().get(0), m.getFormalParameters().get(0)); + } else if (isValueOf && isStringValueOf(m) && qualifier != null) { + checkUnboxing((RuleContext) data, node, qualifier.getTypeMirror()); } else if (!isValueOf && isUnboxingCall(m) && qualifier != null) { checkBox((RuleContext) data, "unboxing", node, qualifier, qualifier.getTypeMirror()); } @@ -89,6 +94,13 @@ public class UnnecessaryBoxingRule extends AbstractJavaRulechainRule { && m.getFormalParameters().get(0).isPrimitive(); } + private boolean isStringValueOf(JMethodSig m) { + return m.isStatic() + && (m.getArity() == 1 || m.getArity() == 2) + && m.getDeclaringType().isBoxedPrimitive() + && TypeTestUtil.isA(String.class, m.getFormalParameters().get(0)); + } + private void checkBox( RuleContext rctx, String opKind, @@ -150,6 +162,28 @@ public class UnnecessaryBoxingRule extends AbstractJavaRulechainRule { } } + private void checkUnboxing( + RuleContext rctx, + ASTMethodCall methodCall, + JTypeMirror conversionOutput + ) { + // methodCall is e.g. Integer.valueOf("42") + // this checks, whether the resulting type "Integer" is e.g. assigned to an "int" + // which triggers implicit unboxing. + ExprContext ctx = methodCall.getConversionContext(); + JTypeMirror ctxType = ctx.getTargetType(); + + if (ctxType != null) { + if (isImplicitlyConvertible(conversionOutput, ctxType)) { + if (conversionOutput.unbox().equals(ctxType)) { + addViolation(rctx, methodCall, "implicit unboxing. Use " + + conversionOutput.getSymbol().getSimpleName() + ".parse" + + StringUtils.capitalize(ctxType.getSymbol().getSimpleName()) + "(...) instead"); + } + } + } + } + private boolean isImplicitlyConvertible(JTypeMirror i, JTypeMirror o) { return i.box().isSubtypeOf(o.box()) || i.unbox().isSubtypeOf(o.unbox()); diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml index 2aa137c587..9bf49f835a 100644 --- a/pmd-java/src/main/resources/category/java/codestyle.xml +++ b/pmd-java/src/main/resources/category/java/codestyle.xml @@ -1447,14 +1447,19 @@ public class Foo { 3 diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryBoxing.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryBoxing.xml index a4b5e0ea2d..bdca54bacc 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryBoxing.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryBoxing.xml @@ -200,4 +200,117 @@ public class Foo { } } ]]> - + + + + Uses of Integer.valueOf(someString) where an int is expected + 4 + 3,4,5,6 + + Unnecessary implicit unboxing. Use Integer.parseInt(...) instead + Unnecessary implicit unboxing. Use Integer.parseInt(...) instead + Unnecessary implicit unboxing. Use Integer.parseInt(...) instead + Unnecessary implicit unboxing. Use Integer.parseInt(...) instead + + + + + + Uses of Long.valueOf(someString) where an long is expected + 4 + 3,4,5,6 + + Unnecessary implicit unboxing. Use Long.parseLong(...) instead + Unnecessary implicit unboxing. Use Long.parseLong(...) instead + Unnecessary implicit unboxing. Use Long.parseLong(...) instead + Unnecessary implicit unboxing. Use Long.parseLong(...) instead + + + + + + Uses of Double.valueOf(someString) where an double is expected + 2 + 3,4 + + Unnecessary implicit unboxing. Use Double.parseDouble(...) instead + Unnecessary implicit unboxing. Use Double.parseDouble(...) instead + + + + + + Uses of Float.valueOf(someString) where an float is expected + 2 + 3,4 + + Unnecessary implicit unboxing. Use Float.parseFloat(...) instead + Unnecessary implicit unboxing. Use Float.parseFloat(...) instead + + + + + + Uses of Short.valueOf(someString) where an short is expected + 4 + 3,4,5,6 + + Unnecessary implicit unboxing. Use Short.parseShort(...) instead + Unnecessary implicit unboxing. Use Short.parseShort(...) instead + Unnecessary implicit unboxing. Use Short.parseShort(...) instead + Unnecessary implicit unboxing. Use Short.parseShort(...) instead + + + + From 6a641ccb342756d2c63bc72b9cd6df9bcd88e9e7 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 10 Sep 2021 14:31:39 +0200 Subject: [PATCH 101/104] Add tests for Boolean.valueOf --- .../rule/codestyle/xml/UnnecessaryBoxing.xml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryBoxing.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryBoxing.xml index bdca54bacc..d891877022 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryBoxing.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UnnecessaryBoxing.xml @@ -310,6 +310,26 @@ public class Foo { short y = Short.parseShort("42"); short z = Short.parseShort(number); } +} + ]]> + + + + Uses of Boolean.valueOf(someString) where an boolean is expected + 2 + 3,4 + + Unnecessary implicit unboxing. Use Boolean.parseBoolean(...) instead + Unnecessary implicit unboxing. Use Boolean.parseBoolean(...) instead + + From 4377ca0ef915fc059cb7e48755757489e8636c9c Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 10 Sep 2021 16:38:17 +0200 Subject: [PATCH 102/104] [doc] Mention deprecation of Security Manager for AvoidAccessAlteration --- pmd-java/src/main/resources/category/java/errorprone.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 475e47af45..444aa61bea 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -67,6 +67,11 @@ This gives access to normally protected data which violates the principle of enc This rule detects calls to `setAccessible` and finds possible accessibility alterations. If the call to `setAccessible` is wrapped within a `PrivilegedAction`, then the access alteration is assumed to be deliberate and is not reported. + +Note that with Java 17 the Security Manager, which is used for `PrivilegedAction` execution, +is deprecated: [JEP 411: Deprecate the Security Manager for Removal](https://openjdk.java.net/jeps/411). +For future-proof code, deliberate access alteration should be suppressed using the usual +suppression methods (e.g. by using `@SuppressWarnings` annotation). 3 From ae0352fea027279e5ee387819b80d8aaac9f5b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 18 Sep 2021 13:36:55 +0200 Subject: [PATCH 103/104] Fix xpath, refs #3499 --- .../xpath/internal/RuleChainAnalyzer.java | 4 +-- .../internal/SaxonXPathRuleQueryTest.java | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java index bae1d78491..afaf60ff6b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/RuleChainAnalyzer.java @@ -9,8 +9,8 @@ import static net.sourceforge.pmd.util.CollectionUtil.listOf; import java.util.ArrayDeque; import java.util.Collections; import java.util.Comparator; -import java.util.List; import java.util.Deque; +import java.util.List; import net.sourceforge.pmd.lang.ast.Node; @@ -101,7 +101,7 @@ public class RuleChainAnalyzer extends SaxonExprVisitor { Expression walker = filterExpression; while (walker instanceof FilterExpression) { filters.push(((FilterExpression) walker).getFilter()); - walker = ((FilterExpression) walker).getBaseExpression(); + walker = ((FilterExpression) walker).getBase(); } result = new FilterExpression(new AxisExpression(AxisInfo.SELF, null), filters.pop()); while (!filters.isEmpty()) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java index 454ccc12a5..eab4f0f9f6 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java @@ -322,6 +322,38 @@ public class SaxonXPathRuleQueryTest { assertExpression("docOrder((((/)/descendant::element(Q{}dummyNode))[matches(convertUntyped(data(@SimpleName)), \"a\", \"\")])/child::element(Q{}foo))", query.getFallbackExpr()); } + + @Test + public void ruleChainWithUnionsCustomFunctionsVariant1() { + SaxonXPathRuleQuery query = createQuery("(//ForStatement | //WhileStatement | //DoStatement)//dummyNode[@Image != '']"); + List ruleChainVisits = query.getRuleChainVisits(); + Assert.assertEquals(0, ruleChainVisits.size()); + } + + @Test + public void ruleChainWithUnionsCustomFunctionsVariant2() { + SaxonXPathRuleQuery query = createQuery("//(ForStatement | WhileStatement | DoStatement)//dummyNode[@Image != '']"); + List ruleChainVisits = query.getRuleChainVisits(); + Assert.assertEquals(0, ruleChainVisits.size()); + } + + @Test + public void ruleChainWithUnionsCustomFunctionsVariant3() { + SaxonXPathRuleQuery query = createQuery("//ForStatement//dummyNode[@Image != '']" + + " | //WhileStatement//dummyNode[@Image != '']" + + " | //DoStatement//dummyNode[@Image != '']"); + List ruleChainVisits = query.getRuleChainVisits(); + Assert.assertEquals(3, ruleChainVisits.size()); + Assert.assertTrue(ruleChainVisits.contains("ForStatement")); + Assert.assertTrue(ruleChainVisits.contains("WhileStatement")); + Assert.assertTrue(ruleChainVisits.contains("DoStatement")); + + final String expectedSubexpression = "(self::node()/descendant::element(dummyNode))[(string(data(@Image))) ne \"\"]"; + assertExpression(expectedSubexpression, query.nodeNameToXPaths.get("ForStatement").get(0)); + assertExpression(expectedSubexpression, query.nodeNameToXPaths.get("WhileStatement").get(0)); + assertExpression(expectedSubexpression, query.nodeNameToXPaths.get("DoStatement").get(0)); + } + private static void assertExpression(String expected, Expression actual) { assertEquals(normalizeExprDump(expected), normalizeExprDump(actual.toString())); From d70821a48d88fd384500893c5dd13adeab0b4850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 18 Sep 2021 14:07:41 +0200 Subject: [PATCH 104/104] Apply suggestions from code review --- pmd-java/src/main/resources/category/java/errorprone.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index 9a29397d1f..ffe1a97a02 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -3404,7 +3404,7 @@ public class Main { class="net.sourceforge.pmd.lang.rule.XPathRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#useequalstocomparestrings"> -Using '==' or '!=' to compare strings only works if the internalized string (`String#intern()`) +Using '==' or '!=' to compare strings is only reliable if the interned string (`String#intern()`) is used on both sides. Use the `equals()` method instead. @@ -3414,7 +3414,7 @@ Use the `equals()` method instead.