diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6d529e9e99..a1c9a7bd37 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,19 @@ - +## Describe the PR -Before submitting a PR, please check that: - - [ ] The PR is submitted against `master`. The PMD team will merge back to support branches as needed. - - [ ] `./mvnw clean verify` passes. This will [build](https://github.com/pmd/pmd/blob/master/BUILDING.md) and test PMD, execute PMD and checkstyle rules. [Check this for more info](https://github.com/pmd/pmd/blob/master/CONTRIBUTING.md#code-style) + -**PR Description:** +## Related issues + + + +- Fixes # + +## Ready? + + + +- [ ] Added unit tests for fixed bug/feature +- [ ] Passing all unit tests +- [ ] Complete build `./mvnw clean verify` passes (checked automatically by travis) +- [ ] Added (in-code) documentation (if needed) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f86d7d2287..68b0cdc2ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,10 @@ First off, thanks for taking the time to contribute! +Please note that this project is released with a Contributor Code of Conduct. +By participating in this project you agree to abide by its terms. + +You can find the code of conduct in the file [code_of_conduct.md](code_of_conduct.md). | NB: the rule designer is developed over at [pmd/pmd-designer](https://github.com/pmd/pmd-designer). Please refer to the specific [contributor documentation](https://github.com/pmd/pmd-designer#contributing) if your issue, feature request or PR touches the designer. | | --- | diff --git a/README.md b/README.md index dbfbd7d9ca..e54a445913 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.sourceforge.pmd/pmd/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.sourceforge.pmd/pmd) [![Coverage Status](https://coveralls.io/repos/github/pmd/pmd/badge.svg)](https://coveralls.io/github/pmd/pmd) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/a674ee8642ed44c6ba7633626ee95967)](https://www.codacy.com/app/pmd/pmd?utm_source=github.com&utm_medium=referral&utm_content=pmd/pmd&utm_campaign=Badge_Grade) +[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](code_of_conduct.md) + ## About **PMD** is a source code analyzer. It finds common programming flaws like unused variables, empty catch blocks, diff --git a/code_of_conduct.md b/code_of_conduct.md new file mode 100644 index 0000000000..c1cf699e74 --- /dev/null +++ b/code_of_conduct.md @@ -0,0 +1,129 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/do-release.sh b/do-release.sh index 614c8f12c4..f276238301 100755 --- a/do-release.sh +++ b/do-release.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e # Make sure, everything is English... @@ -15,7 +15,7 @@ if [ ! -f pom.xml -o ! -d ../pmd.github.io ]; then exit 1 fi - +LAST_VERSION= RELEASE_VERSION= DEVELOPMENT_VERSION= CURRENT_BRANCH= @@ -33,11 +33,16 @@ PATCH=$(echo $RELEASE_VERSION | cut -d . -f 3) if [ "$PATCH" == "0" ]; then NEXT_MINOR=$(expr ${MINOR} + 1) NEXT_PATCH="0" + LAST_MINOR=$(expr ${MINOR} - 1) + LAST_PATCH="0" else # this is a bugfixing release NEXT_MINOR="${MINOR}" NEXT_PATCH=$(expr ${PATCH} + 1) + LAST_MINOR="${MINOR}" + LAST_PATCH=$(expr ${PATCH} - 1) fi +LAST_VERSION="$MAJOR.$LAST_MINOR.$LAST_PATCH" DEVELOPMENT_VERSION="$MAJOR.$NEXT_MINOR.$NEXT_PATCH" DEVELOPMENT_VERSION="${DEVELOPMENT_VERSION}-SNAPSHOT" @@ -52,17 +57,18 @@ CURRENT_BRANCH=$(git symbolic-ref -q HEAD) CURRENT_BRANCH=${CURRENT_BRANCH##refs/heads/} CURRENT_BRANCH=${CURRENT_BRANCH:-HEAD} -echo "RELEASE_VERSION: ${RELEASE_VERSION}" -echo "DEVELOPMENT_VERSION: ${DEVELOPMENT_VERSION}" +echo "LAST_VERSION: ${LAST_VERSION}" +echo "RELEASE_VERSION: ${RELEASE_VERSION} (this release)" +echo "DEVELOPMENT_VERSION: ${DEVELOPMENT_VERSION} (the next version after the release)" echo "CURRENT_BRANCH: ${CURRENT_BRANCH}" echo echo "Is this correct?" echo -echo "Press enter to continue..." +echo "Press enter to continue... (or CTRL+C to cancel)" read - +export LAST_VERSION export RELEASE_VERSION export DEVELOPMENT_VERSION export CURRENT_BRANCH @@ -89,6 +95,26 @@ echo echo "Press enter to continue..." read + +# calculating stats for release notes + +STATS=$( +echo "### Stats" +echo "* $(git log pmd_releases/${LAST_VERSION}..HEAD --oneline --no-merges |wc -l) commits" +echo "* $(curl -s https://api.github.com/repos/pmd/pmd/milestones|jq ".[] | select(.title == \"$RELEASE_VERSION\") | .closed_issues") closed tickets & PRs" +echo "* Days since last release: $(( ( $(date +%s) - $(git log --max-count=1 --format="%at" pmd_releases/${LAST_VERSION}) ) / 86400))" +) + +TEMP_RELEASE_NOTES=$(cat docs/pages/release_notes.md) +TEMP_RELEASE_NOTES=${TEMP_RELEASE_NOTES/\{\% endtocmaker \%\}/$STATS$'\n'$'\n'\{\% endtocmaker \%\}$'\n'} +echo "${TEMP_RELEASE_NOTES}" > docs/pages/release_notes.md + +echo +echo "Updated stats in release notes:" +echo "$STATS" +echo +echo + # install bundles needed for rendering release notes bundle install --with=release_notes_preprocessing --path vendor/bundle diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index 0d6145cd6c..6c84019247 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -55,6 +55,21 @@ entries: - title: PMD CLI reference url: /pmd_userdocs_cli_reference.html output: web, pdf + - title: PMD Report formats + url: /pmd_userdocs_report_formats.html + output: web, pdf + - title: null + output: web, pdf + subfolders: + - title: CPD reference + output: web, pdf + subfolderitems: + - title: Copy-paste detection + url: /pmd_userdocs_cpd.html + output: web, pdf + - title: CPD Report formats + url: /pmd_userdocs_cpd_report_formats.html + output: web, pdf - title: null output: web, pdf subfolders: @@ -88,9 +103,6 @@ entries: - title: Testing your rules url: /pmd_userdocs_extending_testing.html output: web, pdf - - title: Copy-paste detection - url: /pmd_userdocs_cpd.html - output: web, pdf - title: null output: web, pdf subfolders: diff --git a/docs/pages/pmd/projectdocs/committers/releasing.md b/docs/pages/pmd/projectdocs/committers/releasing.md index 0951ac7e16..f8966a7730 100644 --- a/docs/pages/pmd/projectdocs/committers/releasing.md +++ b/docs/pages/pmd/projectdocs/committers/releasing.md @@ -53,6 +53,25 @@ The designer lives at [pmd/pmd-designer](https://github.com/pmd/pmd-designer). Update property `pmd-designer.version` in **pom.xml** to reference the latest pmd-designer release. See for the available releases. +Starting with PMD 6.23.0 we'll provide small statistics for every release. This needs to be added +to the release notes as the last section. To count the closed issues and pull requests, the milestone +on github with the title of the new release is searched. Make sure, there is a milestone +on . The following snippet will +create the numbers, that can be attached to the release notes as a last section: + +```shell +LAST_VERSION=6.22.0 +NEW_VERSION=6.23.0 +NEW_VERSION_COMMITISH=HEAD + +echo "### Stats" +echo "* $(git log pmd_releases/${LAST_VERSION}..${NEW_VERSION_COMMITISH} --oneline --no-merges |wc -l) commits" +echo "* $(curl -s https://api.github.com/repos/pmd/pmd/milestones|jq ".[] | select(.title == \"$NEW_VERSION\") | .closed_issues") closed tickets & PRs" +echo "* Days since last release: $(( ( $(date +%s) - $(git log --max-count=1 --format="%at" pmd_releases/${LAST_VERSION}) ) / 86400))" +``` + +Note: this part is also integrated into `do-release.sh`. + Check in all (version) changes to branch master or any other branch, from which the release takes place: $ git commit -a -m "Prepare pmd release " diff --git a/docs/pages/pmd/userdocs/cli_reference.md b/docs/pages/pmd/userdocs/cli_reference.md index ca45b101de..a43c809081 100644 --- a/docs/pages/pmd/userdocs/cli_reference.md +++ b/docs/pages/pmd/userdocs/cli_reference.md @@ -198,76 +198,5 @@ Example: ## Available Report Formats PMD comes with many different renderers. -The mnemonics in bold are used to select them on the command line, as -arguments to the `-format` option. Some formats accept *properties*, -which can be specified with the `-property` option on the command-line. +All formats are described at [PMD Report formats](pmd_userdocs_report_formats.html) -* **codeclimate**: Renderer for Code Climate JSON format. - -* **csv**: Comma-separated values tabular format. - - Properties: - - * problem: Include problem column. Default: true. - * package: Include package column. Default: true. - * file: Include file column. Default: true. - * priority: Include priority column. Default: true. - * line: Include line column. Default: true. - * desc: Include description column. Default: true. - * ruleSet: Include Rule set column. Default: true. - * rule: Include Rule column. Default: true. - -* **emacs**: GNU Emacs integration. - -* **html**: HTML format. - - Properties: - - * linePrefix: Prefix for line number anchor in the source file. - * linkPrefix: Path to HTML source. - -* **ideaj**: IntelliJ IDEA integration. - - Properties: - - * classAndMethodName: Class and method name, pass `.method` when processing a directory. - * sourcePath: - * fileName: - -* **summaryhtml**: Summary HTML format. - - Properties: - - * linePrefix: Prefix for line number anchor in the source file. - * linkPrefix: Path to HTML source. - -* **text**: Text format. - -* **textcolor**: Text format, with color support (requires ANSI console support, e.g. xterm, rxvt, etc.). - - Properties: - - * color: Enables colors with anything other than `false` or `0`. Default: yes. - -* **textpad**: TextPad integration. - -* **vbhtml**: Vladimir Bossicard HTML format. - -* **xml**: XML format. - - Properties: - - * encoding: XML encoding format, defaults to UTF-8. - -* **xslt**: XML with a XSL transformation applied. - - Properties: - - * encoding: XML encoding format, defaults to UTF-8. - * xsltFilename: The XSLT file name. - -* **yahtml**: Yet Another HTML format. - - Properties: - - * outputDir: Output directory. diff --git a/docs/pages/pmd/userdocs/cpd.md b/docs/pages/pmd/userdocs/cpd/cpd.md similarity index 99% rename from docs/pages/pmd/userdocs/cpd.md rename to docs/pages/pmd/userdocs/cpd/cpd.md index e9843661fe..bb341e8e2a 100644 --- a/docs/pages/pmd/userdocs/cpd.md +++ b/docs/pages/pmd/userdocs/cpd/cpd.md @@ -239,6 +239,7 @@ This behavior has been introduced to ease CPD integration into scripts or hooks, * csv_with_linecount_per_file * vs +For details, see [CPD Report Formats](pmd_userdocs_cpd_report_formats.html). ## Ant task diff --git a/docs/pages/pmd/userdocs/cpd/cpd_report_formats.md b/docs/pages/pmd/userdocs/cpd/cpd_report_formats.md new file mode 100644 index 0000000000..d224b28ee7 --- /dev/null +++ b/docs/pages/pmd/userdocs/cpd/cpd_report_formats.md @@ -0,0 +1,220 @@ +--- +title: Report formats for CPD +tags: [cpd, userdocs] +keywords: [formats, renderers] +summary: "Overview of the built-in report formats for CPD" +permalink: pmd_userdocs_cpd_report_formats.html +author: Andreas Dangel +--- + +## Overview + +CPD collects occurrences of found duplications and provides them to the selected report format. +Each found code duplication appears in one or more other files, so that each code duplication can +have multiple locations. Not all report formats display all locations. + +The following examples always describe the same duplications: + +1. a code block of 239 tokens spanning 33 lines in RuleReferenceTest. This is a duplication within the same file. +2. a code block of 110 tokens spanning 16 lines in JaxenXPathRuleQueryTest. This is a duplication that appears + 3 times within the same file. + + +## text + +This is the default format. + +All duplications are reported one after another. For each duplication, the complete code snippet is output. +Each duplication is separated by `======`. + +Example: + +``` +Found a 33 line (239 tokens) duplication in the following files: +Starting at line 32 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java +Starting at line 68 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java + + public void testOverride() { + final StringProperty PROPERTY1_DESCRIPTOR = new StringProperty("property1", "Test property", null, 0f); + MockRule rule = new MockRule(); + rule.definePropertyDescriptor(PROPERTY1_DESCRIPTOR); + rule.setLanguage(LanguageRegistry.getLanguage(Dummy2LanguageModule.NAME)); + rule.setName("name1"); + rule.setProperty(PROPERTY1_DESCRIPTOR, "value1"); + rule.setMessage("message1"); + rule.setDescription("description1"); + rule.addExample("example1"); + rule.setExternalInfoUrl("externalInfoUrl1"); + rule.setPriority(RulePriority.HIGH); + + final StringProperty PROPERTY2_DESCRIPTOR = new StringProperty("property2", "Test property", null, 0f); + RuleReference ruleReference = new RuleReference(); + ruleReference.setRule(rule); + ruleReference.definePropertyDescriptor(PROPERTY2_DESCRIPTOR); + ruleReference.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME)); + ruleReference + .setMinimumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.3")); + ruleReference + .setMaximumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.7")); + ruleReference.setDeprecated(true); + ruleReference.setName("name2"); + ruleReference.setProperty(PROPERTY1_DESCRIPTOR, "value2"); + ruleReference.setProperty(PROPERTY2_DESCRIPTOR, "value3"); + ruleReference.setMessage("message2"); + ruleReference.setDescription("description2"); + ruleReference.addExample("example2"); + ruleReference.setExternalInfoUrl("externalInfoUrl2"); + ruleReference.setPriority(RulePriority.MEDIUM_HIGH); + + validateOverridenValues(PROPERTY1_DESCRIPTOR, PROPERTY2_DESCRIPTOR, ruleReference); +===================================================================== +Found a 16 line (110 tokens) duplication in the following files: +Starting at line 66 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java +Starting at line 88 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java +Starting at line 110 of /home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java + + JaxenXPathRuleQuery query = createQuery(xpath); + List ruleChainVisits = query.getRuleChainVisits(); + Assert.assertEquals(2, ruleChainVisits.size()); + Assert.assertTrue(ruleChainVisits.contains("dummyNode")); + // Note: Having AST_ROOT in the rule chain visits is probably a mistake. But it doesn't hurt, it shouldn't + // match a real node name. + Assert.assertTrue(ruleChainVisits.contains(JaxenXPathRuleQuery.AST_ROOT)); + + DummyNodeWithListAndEnum dummy = new DummyNodeWithListAndEnum(1); + RuleContext data = new RuleContext(); + data.setLanguageVersion(LanguageRegistry.findLanguageByTerseName("dummy").getDefaultVersion()); + + query.evaluate(dummy, data); + // note: the actual xpath queries are only available after evaluating + Assert.assertEquals(2, query.nodeNameToXPaths.size()); + Assert.assertEquals("self::node()[(attribute::Test1 = \"false\")][(attribute::Test2 = \"true\")]", query.nodeNameToXPaths.get("dummyNode").get(0).toString()); +``` + + +## xml + +This format uses XML to output the duplications in a more structured format. + +Example: + +```xml + + + + + + + + + + + + ruleChainVisits = query.getRuleChainVisits(); + Assert.assertEquals(2, ruleChainVisits.size()); + Assert.assertTrue(ruleChainVisits.contains("dummyNode")); + // Note: Having AST_ROOT in the rule chain visits is probably a mistake. But it doesn't hurt, it shouldn't + // match a real node name. + Assert.assertTrue(ruleChainVisits.contains(JaxenXPathRuleQuery.AST_ROOT)); + + DummyNodeWithListAndEnum dummy = new DummyNodeWithListAndEnum(1); + RuleContext data = new RuleContext(); + data.setLanguageVersion(LanguageRegistry.findLanguageByTerseName("dummy").getDefaultVersion()); + + query.evaluate(dummy, data); + // note: the actual xpath queries are only available after evaluating + Assert.assertEquals(2, query.nodeNameToXPaths.size()); + Assert.assertEquals("self::node()[(attribute::Test1 = \"false\")][(attribute::Test2 = \"true\")]", query.nodeNameToXPaths.get("dummyNode").get(0).toString());]]> + + +``` + + +## csv + +This outputs the duplication as comma separated values. It only reports the duplication size (number +of lines and tokens) and the number of occurrences. After that, the begin lines and filenames are reported on +after another. + +Example: + +``` +lines,tokens,occurrences +33,239,2,32,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java,68,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java +16,110,3,66,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java,88,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java,110,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java +``` + + +## csv_with_linecount_per_file + +This format is similar to "csv", but it has one difference: The duplication size in number of lines is reported +for each occurrence separately. While the tokens are the same, due to formatting or comments, the code blocks might be +different. Whitespace and comments are usually ignored when finding duplicated code. + +In each line, the duplication size in tokens is reported, then the number of occurrences. And after that, for each +file, the begin line, the number of duplicated lines and the filename. + +Example: + +``` +tokens,occurrences +239,2,32,33,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java,68,33,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenc +eTest.java +110,3,66,16,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java,88,16,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java,110,16,/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java +``` + + +## vs + +This outputs the duplication in a format, that Visual Studio. CPD can be added as a external tool and the output +is shown in the console. You can then click on the filenames to jump to the source where the duplication is located. + +Each occurrence of a duplication is reported in a separate line, that's why in this example, we have 5 lines. + +Example: + +``` +/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java(32): Between lines 32 and 65 +/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java(68): Between lines 68 and 101 +/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java(66): Between lines 66 and 82 +/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java(88): Between lines 88 and 104 +/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java(110): Between lines 110 and 126 +``` diff --git a/docs/pages/pmd/userdocs/pmd_report_formats.md b/docs/pages/pmd/userdocs/pmd_report_formats.md new file mode 100644 index 0000000000..ff7fd639e7 --- /dev/null +++ b/docs/pages/pmd/userdocs/pmd_report_formats.md @@ -0,0 +1,339 @@ +--- +title: Report formats for PMD +tags: [pmd, userdocs] +keywords: [formats, renderers] +summary: "Overview of the built-in report formats for CPD" +permalink: pmd_userdocs_report_formats.html +author: Andreas Dangel +--- + +## Overview + +PMD can report the found rule violations in various formats. Some formats can +be customized further via properties. Violations might also be suppressed and there might +be processing errors or configuration errors. Not all report formats display all information. + +The header of the sections below are used to select the format on the command line, as +arguments to the `-format` option. When a format accepts *properties*, +those can be specified with the `-property` / `-P` option on the command-line. + +{% include note.html content="Suppressed violations are only reported, if the CLI parameter `-showsuppressed` is set." %} + +## codeclimate + +Renderer for Code Climate JSON format. + +This format is used when running PMD within [Code Climate](https://codeclimate.com/). +The renderer will stream JSON objects, each object is a own issue (a PMD rule violation). Each issue +is separated by the null character (`\0`). + +The format is specified here: . + +The code climate format doesn't support suppressed violations. It also doesn't report any errors. But it contains +the full rule details for each reported rule violation. + +Example: + +``` +{"type":"issue","check_name":"GuardLogStatement","description":"Logger calls should be surrounded by log level guards.","content":{"body":"## GuardLogStatement\n\nSince: PMD 5.1.0\n\nPriority: Medium High\n\n[Categories](https://github.com/codeclimate/spec/blob/master/SPEC.md#categories): Style\n\n[Remediation Points](https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points): 50000\n\nWhenever using a log level, one should check if the loglevel is actually enabled, or otherwise skip the associate String creation and manipulation.\n\n### Example:\n\n```java\n\n\n // Add this for performance\n if (log.isDebugEnabled() { ...\n log.debug('log something' + ' and ' + 'concat strings');\n\n \n``` \n\n### [PMD properties](https://pmd.github.io/pmd-6.22.0/pmd_devdocs_working_with_properties.html)\n\nName | Value | Description\n--- | --- | ---\nviolationSuppressRegex | | Suppress violations with messages matching a regular expression\nviolationSuppressXPath | | Suppress violations on nodes which match a given relative XPath expression.\nlogLevels | trace,debug,info,warn,error,log,finest,finer,fine,info,warning,severe | LogLevels to guard\nguardsMethods | isTraceEnabled,isDebugEnabled,isInfoEnabled,isWarnEnabled,isErrorEnabled,isLoggable | Method use to guard the log statement\n"},"categories":["Style"],"location":{"path":"/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java","lines":{"begin":124,"end":125}},"severity":"normal","remediation_points":50000} +{"type":"issue","check_name":"ForLoopCanBeForeach","description":"This for loop can be replaced by a foreach loop","content":{"body":"## ForLoopCanBeForeach\n\nSince: PMD 6.0.0\n\nPriority: Medium\n\n[Categories](https://github.com/codeclimate/spec/blob/master/SPEC.md#categories): Style\n\n[Remediation Points](https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points): 50000\n\nReports loops that can be safely replaced with the foreach syntax. The rule considers loops over lists, arrays and iterators. A loop is safe to replace if it only uses the index variable to access an element of the list or array, only has one update statement, and loops through *every* element of the list or array left to right.\n\n### Example:\n\n```java\n\n\npublic class MyClass {\n void loop(List l) {\n for (int i = 0; i < l.size(); i++) { // pre Java 1.5\n System.out.println(l.get(i));\n }\n\n for (String s : l) { // post Java 1.5\n System.out.println(s);\n }\n }\n}\n\n \n``` \n\n### [PMD properties](https://pmd.github.io/pmd-6.22.0/pmd_devdocs_working_with_properties.html)\n\nName | Value | Description\n--- | --- | ---\nviolationSuppressRegex | | Suppress violations with messages matching a regular expression\nviolationSuppressXPath | | Suppress violations on nodes which match a given relative XPath expression.\n"},"categories":["Style"],"location":{"path":"/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java","lines":{"begin":58,"end":62}},"severity":"normal","remediation_points":50000} +``` + +## csv + +Comma-separated values tabular format. + +This format only renders rule violations. Suppressed violations or errors are ignored. + +Example: + +``` +"Problem","Package","File","Priority","Line","Description","Rule set","Rule" +"1","net.sourceforge.pmd","/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java","2","124","Logger calls should be surrounded by log level guards.","Best Practices","GuardLogStatement" +"1","net.sourceforge.pmd.benchmark","/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java","3","58","This for loop can be replaced by a foreach loop","Best Practices","ForLoopCanBeForeach" +``` + +This format can be configured to display only certain columns. In order to not show the problem counter and package +columns, use these CLI parameters additionally: `-property problem=false -property package=false` + +**Properties:** + +* problem: Include problem column. Default: true. +* package: Include package column. Default: true. +* file: Include file column. Default: true. +* priority: Include priority column. Default: true. +* line: Include line column. Default: true. +* desc: Include description column. Default: true. +* ruleSet: Include Rule set column. Default: true. +* rule: Include Rule column. Default: true. + +## emacs + +GNU Emacs integration. + +Example: + +``` +/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java:124: Logger calls should be surrounded by log level guards. +/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java:58: This for loop can be replaced by a foreach loop +``` + +## html + +HTML format. + +This renderer provides two properties. If these are provided, then a link to the source where the violations +have been found is rendered. The following example has been created with `-property linkPrefix=https://github.com/pmd/pmd/blob/master/ -property linePrefix=L -shortnames -d pmd`. + +When using [Maven JXR Plugin](https://maven.apache.org/jxr/maven-jxr-plugin/index.html) to generate a html view +of the project's sources, then the property "htmlExtension" needs to be set to "true". This will then replace the +normal source file extensions (e.g. ".java") with ".html", so that the generated html pages are referenced. + +[Example](report-examples/pmd-report-html.html) + +**Properties:** + +* linePrefix: Prefix for line number anchor in the source file. +* linkPrefix: Path to HTML source. +* htmlExtension: Replace file extension with .html for the links (default: false) + +## ideaj + +IntelliJ IDEA integration. + +{% include warning.html content="This format can only be used as described in [Tools: IDEA](pmd_userdocs_tools.html#idea)." %} + +It has two ways of calling: + +1. For a single file: then all three properties need to be provided + +`run.sh pmd -d src/Foo.java -R rulesets/java/quickstart.xml -f ideaj -P fileName=src/Foo.java -P sourcePath=/home/pmd/src -P classAndMethodName=Foo` + +2. For a directory: then the fileName property can be omitted + +`run.sh pmd -d src -R rulesets/java/quickstart.xml -f ideaj -P sourcePath=/home/pmd/src -P classAndMethodName=.method` + +Example: + +``` +Logger calls should be surrounded by log level guards. + at Foo(:124) +This for loop can be replaced by a foreach loop + at Foo(:58) +``` + +**Properties:** + +* classAndMethodName: Class and method name, pass `.method` when processing a directory. +* sourcePath: +* fileName: + +## summaryhtml + +Summary HTML format. + +This is the [html renderer](#html) but with an extra section, the summarizes the violations per rule. + +[Example](report-examples/pmd-report-summaryhtml.html) + +**Properties:** + +* linePrefix: Prefix for line number anchor in the source file. +* linkPrefix: Path to HTML source. +* htmlExtension: Replace file extension with .html for the links (default: false) + +## text (default) + +This is the default format. + +This format outputs one line per violation. At the end, processing errors, suppressed violations +and configuration errors are reported. + +Example: + +``` +/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java:124: Logger calls should be surrounded by log level guards. +/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java:58: This for loop can be replaced by a foreach loop +/home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java - PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java +CloseResource rule violation suppressed by Annotation in /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/PMD.java +LoosePackageCoupling - No packages or classes specified +``` + +## textcolor + +Text format, with color support (requires ANSI console support, e.g. xterm, rxvt, etc.). + +Example: + +
+* file: ./pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java
+    src:  RuleContext.java:124:125
+    rule: GuardLogStatement
+    msg:  Logger calls should be surrounded by log level guards.
+    code: LOG.warning("The method RuleContext::setSourceCodeFilename(String) has been deprecated and will be removed."
+
+* file: ./pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java
+    src:  Benchmarker.java:58:62
+    rule: ForLoopCanBeForeach
+    msg:  This for loop can be replaced by a foreach loop
+    code: for (int i = 0; i < args.length; i++) {
+
+
+
+Summary:
+
+net.sourceforge.pmd.RuleContext : 1
+net.sourceforge.pmd.benchmark.Benchmarker : 1
+* file: ./pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
+    err:  PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
+net.sourceforge.pmd.PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51)
+    at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78)
+    at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:24)
+    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
+    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
+    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
+    at java.base/java.lang.Thread.run(Thread.java:832)
+Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30.
+Was expecting one of:
+    "extends" ...
+    "implements" ...
+    "{" ...
+    "<" ...
+    
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12713)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12597)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1554)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:732)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:639)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:373)
+    at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62)
+    at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107)
+    ... 10 more
+
+
+* rule: LoosePackageCoupling
+    err:  No packages or classes specified
+
+* errors:   2
+* warnings: 2
+
+ +**Properties:** + +* color: Enables colors with anything other than `false` or `0`. Default: yes. + +## textpad + +TextPad integration. + +Example: + +``` +/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java(124, GuardLogStatement): Logger calls should be surrounded by log level guards. +/home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java(58, ForLoopCanBeForeach): This for loop can be replaced by a foreach loop +``` + +## vbhtml + +Vladimir Bossicard HTML format. + + +## xml + +XML format. + +This format is a XML document, that can be validated by a XSD schema. The schema is [report_2_0_0.xsd](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/resources/report_2_0_0.xsd). + +Example: + +```xml + + + + +Logger calls should be surrounded by log level guards. + + + + +This for loop can be replaced by a foreach loop + + + + + + + + +``` + +**Properties:** + +* encoding: XML encoding format, defaults to UTF-8. + +## xslt + +XML with a XSL transformation applied. + +PMD provides one built-in stylesheet, that is used by default, if no other +stylesheet with the property "xsltFilename" is specified. It is called [pmd-nicerhtml.xsl](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/resources/pmd-nicerhtml.xsl) and can be used for customization. + +[Example with pmd-nicerhtml.xsl](report-examples/pmd-report-pmd-nicerhtml.html) + +**Properties:** + +* encoding: XML encoding format, defaults to UTF-8. +* xsltFilename: The XSLT file name. + +## yahtml + +Yet Another HTML format. + +This renderer creates an html file per analyzed source file, hence you need to specify a output directory. +The output directory must exist. If not specified, the html files are created in the current directory. + +[Example](report-examples/pmd-report-yahtml/index.html) + +**Properties:** + +* outputDir: Output directory. diff --git a/docs/pages/pmd/userdocs/tools/tools.md b/docs/pages/pmd/userdocs/tools/tools.md index b8427311fe..b3e8d550c9 100644 --- a/docs/pages/pmd/userdocs/tools/tools.md +++ b/docs/pages/pmd/userdocs/tools/tools.md @@ -243,11 +243,11 @@ Here's how to set it up as an "External Tool": * Name: PMD * Description: PMD, good for what ails you. * Menu: Select the "Main menu", "Project views", "Editor menu", and "Search results" checkboxes. - * Program: $JDKPath$\bin\java.exe + * Program: `c:\pmd\bin\pmd.bat` * For the next parameter you'll need to plug in the location of your PMD installation and the rulesets you want to use * Parameters: - `-cp %CLASSPATH%;c:\pmd\lib\pmd-{{pmd.site.version}}.jar;c:\pmd\lib\asm-3.2.jar;c:\pmd\lib\jaxen-1.1.1.jar net.sourceforge.pmd.PMD "$FilePath$" ideaj unusedcode,imports "$Sourcepath$" $FileClass$.method $FileName$` + `-d "$FilePath$" -f ideaj -R rulesets/java/quickstart.xml -P sourcePath="$Sourcepath$" -P classAndMethodName=$FileClass$.method -P fileName=$FileName$` That's pretty much it. Now you can right click on a source directory and select PMD, it'll run recursively on the source files, and the results should diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index fa98c0332a..4cbd9d2530 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -14,6 +14,18 @@ This is a {{ site.pmd.release_type }} release. ### New and noteworthy +#### PMD adopts Contributor Code of Conduct + +To facilitate healthy and constructive community behavior PMD adopts +[Contributor Convenant](https://www.contributor-covenant.org/) as its code of +conduct. + +Please note that this project is released with a Contributor Code of Conduct. +By participating in this project you agree to abide by its terms. + +You can find the code of conduct in the file [code_of_conduct.md](https://github.com/pmd/pmd/blob/master/code_of_conduct.md) +in our repository. + #### Performance improvements for XPath 2.0 rules XPath rules written with XPath 2.0 now support conversion to a rulechain rule, which @@ -46,10 +58,16 @@ Note that XPath 1.0 support, the default XPath version, is deprecated since PMD * [#2210](https://github.com/pmd/pmd/issues/2210): \[apex] ApexCRUDViolation: Support WITH SECURITY_ENFORCED * [#2399](https://github.com/pmd/pmd/issues/2399): \[apex] ApexCRUDViolation: false positive with security enforced with line break * core + * [#2019](https://github.com/pmd/pmd/issues/2019): \[core] Insufficient deprecation warnings for XPath attributes + * [#2357](https://github.com/pmd/pmd/issues/2357): Add code of conduct: Contributor Covenant +* doc * [#2355](https://github.com/pmd/pmd/issues/2355): \[doc] Improve documentation about incremental analysis * [#2356](https://github.com/pmd/pmd/issues/2356): \[doc] Add missing doc about pmd.github.io + * [#2413](https://github.com/pmd/pmd/issues/2413): \[doc] Improve documentation about the available renderers (PMD/CPD) * java * [#2378](https://github.com/pmd/pmd/issues/2378): \[java] AbstractJUnitRule has bad performance on large code bases +* java-bestpractices + * [#2398](https://github.com/pmd/pmd/issues/2398): \[java] AbstractClassWithoutAbstractMethod false negative with inner abstract classes * java-codestyle * [#1164](https://github.com/pmd/pmd/issues/1164): \[java] ClassNamingConventions suggests to add Util for class containing only static constants * [#1723](https://github.com/pmd/pmd/issues/1723): \[java] UseDiamondOperator false-positive inside lambda @@ -80,7 +98,7 @@ You can identify them with the `@InternalApi` annotation. You'll also get a depr As part of the changes we'd like to do to AST classes for 7.0.0, we would like to hide some methods and constructors that rule writers should not have access to. -The following usages are now deprecated in the **Javascript**, **Visualforce** and **PLSQL** ASTs: +The following usages are now deprecated in the **Apex**, **Javascript**, **PL/SQL** and **Visualforce** ASTs: * Manual instantiation of nodes. **Constructors of node classes are deprecated** and marked {% jdoc core::annotation.InternalApi %}. Nodes should only be obtained from the parser, @@ -101,9 +119,10 @@ The following usages are now deprecated in the **Javascript**, **Visualforce** a These deprecations are added to the following language modules in this release. Please look at the package documentation to find out the full list of deprecations. +* Apex: **{% jdoc_package apex::lang.apex.ast %}** * Javascript: **{% jdoc_package javascript::lang.ecmascript.ast %}** -* Visualforce: **{% jdoc_package visualforce::lang.vf.ast %}** * PL/SQL: **{% jdoc_package plsql::lang.plsql.ast %}** +* Visualforce: **{% jdoc_package visualforce::lang.vf.ast %}** These deprecations have already been rolled out in a previous version for the following languages: @@ -114,17 +133,24 @@ following languages: Outside of these packages, these changes also concern the following TokenManager implementations, and their corresponding Parser if it exists (in the same package): -* {% jdoc vm::lang.vm.VmTokenManager %} +* {% jdoc cpp::lang.cpp.CppTokenManager %} * {% jdoc java::lang.java.JavaTokenManager %} +* {% jdoc javascript::lang.ecmascript5.Ecmascript5TokenManager %} +* {% jdoc jsp::lang.jsp.JspTokenManager %} +* {% jdoc matlab::lang.matlab.MatlabTokenManager %} +* {% jdoc modelica::lang.modelica.ModelicaTokenManager %} +* {% jdoc objectivec::lang.objectivec.ObjectiveCTokenManager %} +* {% jdoc plsql::lang.plsql.PLSQLTokenManager %} * {% jdoc python::lang.python.PythonTokenManager %} * {% jdoc visualforce::lang.vf.VfTokenManager %} -* {% jdoc plsql::lang.plsql.PLSQLTokenManager %} -* {% jdoc jsp::lang.jsp.JspTokenManager %} -* {% jdoc modelica::lang.modelica.ModelicaTokenManager %} -* {% jdoc cpp::lang.cpp.CppTokenManager %} -* {% jdoc javascript::lang.ecmascript5.Ecmascript5TokenManager %} -* {% jdoc matlab::lang.matlab.MatlabTokenManager %} -* {% jdoc objectivec::lang.objectivec.ObjectiveCTokenManager %} +* {% jdoc vm::lang.vm.VmTokenManager %} + + +In the **Java AST** the following attributes are deprecated and will issue a warning when used in XPath rules: + +* {% jdoc !!java::lang.java.ast.ASTAdditiveExpression#getImage() %} - use `getOperator()` instead +* {% jdoc !!java::lang.java.ast.ASTVariableDeclaratorId#getImage() %} - use `getName()` instead +* {% jdoc !!java::lang.java.ast.ASTVariableDeclaratorId#getVariableName() %} - use `getName()` instead ##### For removal @@ -151,6 +177,7 @@ implementations, and their corresponding Parser if it exists (in the same packag * [#2403](https://github.com/pmd/pmd/pull/2403): \[java] #2402 fix false-positives on Primitive Streams - [Bernd Farka](https://github.com/BerndFarkaDyna) * [#2409](https://github.com/pmd/pmd/pull/2409): \[java] ClassNamingConventions suggests to add Util for class containing only static constants, fixes #1164 - [Binu R J](https://github.com/binu-r) * [#2411](https://github.com/pmd/pmd/pull/2411): \[java] Fix UseAssertEqualsInsteadOfAssertTrue Example - [Moritz Scheve](https://github.com/Blightbuster) +* [#2423](https://github.com/pmd/pmd/pull/2423): \[core] Fix Checkstyle OperatorWrap in AbstractTokenizer - [Harsh Kukreja](https://github.com/harsh-kukreja) {% endtocmaker %} diff --git a/docs/report-examples/pmd-report-html.html b/docs/report-examples/pmd-report-html.html new file mode 100644 index 0000000000..2c1c41342d --- /dev/null +++ b/docs/report-examples/pmd-report-html.html @@ -0,0 +1,67 @@ +PMD +

PMD report

Problems found

+ + + + + + + + + + + + + +
#FileLineProblem
1pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java124Logger calls should be surrounded by log level guards.
2pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java58This for loop can be replaced by a foreach loop

Processing errors

+ + + + + +
FileProblem
pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
net.sourceforge.pmd.PMDException: Error while parsing pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51)
+    at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78)
+    at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:24)
+    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
+    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
+    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
+    at java.base/java.lang.Thread.run(Thread.java:832)
+Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30.
+Was expecting one of:
+    "extends" ...
+    "implements" ...
+    "{" ...
+    "<" ...
+    
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12713)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12597)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1554)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:732)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:639)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:373)
+    at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62)
+    at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107)
+    ... 10 more
+

Suppressed warnings

+ + + + + + + + +
FileLineRuleNOPMD or AnnotationReason
pmd-core/src/main/java/net/sourceforge/pmd/PMD.java505CloseResourceAnnotation

Configuration errors

+ + + + + +
RuleProblem
LoosePackageCouplingNo packages or classes specified
\ No newline at end of file diff --git a/docs/report-examples/pmd-report-pmd-nicerhtml.html b/docs/report-examples/pmd-report-pmd-nicerhtml.html new file mode 100644 index 0000000000..702d8b1e8f --- /dev/null +++ b/docs/report-examples/pmd-report-pmd-nicerhtml.html @@ -0,0 +1,223 @@ + + + + + PMD 6.22.0 Report + + + + + + + + +
+ +

PMD 6.22.0 Report. Generated on 2020-04-11 - 19:23:45

+
+
+

Summary

+ + + + + + + + + + + + + + + + + + + +
FilesTotal +
Priority 1
+
+
Priority 2
+
+
Priority 3
+
+
Priority 4
+
+
Priority 5
+
2201100
+
+

Rules

+ + + + + + + + + + + + + + + + +
RuleViolationsSeverity
+ [Best Practices] GuardLogStatement1 +
2
+
+ [Best Practices] ForLoopCanBeForeach1 +
3
+
+
+

Files

+ + + + + + + + + + + + + + + + + + + + + + + + + +
File +
5
+
+
4
+
+
3
+
+
2
+
+
1
+
+ /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java + 00010
+ /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java + 00100
+
+
+

File /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java

+ + + + + + + + + + + +
ViolationError DescriptionLine
+
2
+
+ [Best Practices.GuardLogStatement] + - + +Logger calls should be surrounded by log level guards. + + 124 - 125
+
Back to top + +

File /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java

+ + + + + + + + + + + +
ViolationError DescriptionLine
+
3
+
+ [Best Practices.ForLoopCanBeForeach] + - + +This for loop can be replaced by a foreach loop + + 58 - 62
+
Back to top +
+ + \ No newline at end of file diff --git a/docs/report-examples/pmd-report-summaryhtml.html b/docs/report-examples/pmd-report-summaryhtml.html new file mode 100644 index 0000000000..92dc3e1f72 --- /dev/null +++ b/docs/report-examples/pmd-report-summaryhtml.html @@ -0,0 +1,74 @@ +PMD +

Summary

+ + + + +
Rule nameNumber of violations
GuardLogStatement1
ForLoopCanBeForeach1
+

Detail

+

PMD report

Problems found

+ + + + + + + + + + + + + +
#FileLineProblem
1pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java124Logger calls should be surrounded by log level guards.
2pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java58This for loop can be replaced by a foreach loop

Processing errors

+ + + + + +
FileProblem
pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
net.sourceforge.pmd.PMDException: Error while parsing pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51)
+    at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78)
+    at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:1)
+    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
+    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
+    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
+    at java.base/java.lang.Thread.run(Thread.java:834)
+Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30.
+Was expecting one of:
+    "extends" ...
+    "implements" ...
+    "{" ...
+    "<" ...
+    
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12731)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12615)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1574)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:779)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:686)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:420)
+    at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62)
+    at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107)
+    ... 10 more
+

Suppressed warnings

+ + + + + + + + +
FileLineRuleNOPMD or AnnotationReason
pmd-core/src/main/java/net/sourceforge/pmd/PMD.java505CloseResourceAnnotation

Configuration errors

+ + + + + +
RuleProblem
LoosePackageCouplingNo packages or classes specified
\ No newline at end of file diff --git a/docs/report-examples/pmd-report-vbhtml.html b/docs/report-examples/pmd-report-vbhtml.html new file mode 100644 index 0000000000..f6ce69c610 --- /dev/null +++ b/docs/report-examples/pmd-report-vbhtml.html @@ -0,0 +1,42 @@ +PMD
+ +
 /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/RuleContext.java
124   Logger calls should be surrounded by log level guards.
+ +
 /home/pmd/source/pmd-core/src/main/java/net/sourceforge/pmd/benchmark/Benchmarker.java
58   This for loop can be replaced by a foreach loop

 Problems found
/home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
net.sourceforge.pmd.PMDException: Error while parsing /home/pmd/source/pmd-core/src/test/resources/net/sourceforge/pmd/cpd/files/file_with_ISO-8859-1_encoding.java
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:110)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:89)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCode(SourceCodeProcessor.java:51)
+    at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:78)
+    at net.sourceforge.pmd.processor.PmdRunnable.call(PmdRunnable.java:24)
+    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
+    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
+    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
+    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
+    at java.base/java.lang.Thread.run(Thread.java:832)
+Caused by: net.sourceforge.pmd.lang.java.ast.ParseException: Encountered " "-" "- "" at line 6, column 30.
+Was expecting one of:
+    "extends" ...
+    "implements" ...
+    "{" ...
+    "<" ...
+    
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.generateParseException(JavaParser.java:12713)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.jj_consume_token(JavaParser.java:12597)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceBody(JavaParser.java:1554)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.ClassOrInterfaceDeclaration(JavaParser.java:732)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.TypeDeclaration(JavaParser.java:639)
+    at net.sourceforge.pmd.lang.java.ast.JavaParser.CompilationUnit(JavaParser.java:373)
+    at net.sourceforge.pmd.lang.java.AbstractJavaParser.parse(AbstractJavaParser.java:62)
+    at net.sourceforge.pmd.SourceCodeProcessor.parse(SourceCodeProcessor.java:121)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSource(SourceCodeProcessor.java:185)
+    at net.sourceforge.pmd.SourceCodeProcessor.processSourceCodeWithoutCache(SourceCodeProcessor.java:107)
+    ... 10 more
+
 Configuration problems found
LoosePackageCouplingNo packages or classes specified
diff --git a/docs/report-examples/pmd-report-yahtml/Benchmarker.html b/docs/report-examples/pmd-report-yahtml/Benchmarker.html new file mode 100644 index 0000000000..2e0da807d1 --- /dev/null +++ b/docs/report-examples/pmd-report-yahtml/Benchmarker.html @@ -0,0 +1,15 @@ + + + + + PMD - Benchmarker + + +

Class View

+

Class: Benchmarker

+ + + +
MethodViolation
findBooleanSwitch
Rule:ForLoopCanBeForeach
Description:This for loop can be replaced by a foreach loop
Line:58 and 62
+ + diff --git a/docs/report-examples/pmd-report-yahtml/RuleContext.html b/docs/report-examples/pmd-report-yahtml/RuleContext.html new file mode 100644 index 0000000000..1f401103f4 --- /dev/null +++ b/docs/report-examples/pmd-report-yahtml/RuleContext.html @@ -0,0 +1,15 @@ + + + + + PMD - RuleContext + + +

Class View

+

Class: RuleContext

+ + + +
MethodViolation
setSourceCodeFilename
Rule:GuardLogStatement
Description:Logger calls should be surrounded by log level guards.
Line:124 and 125
+ + diff --git a/docs/report-examples/pmd-report-yahtml/index.html b/docs/report-examples/pmd-report-yahtml/index.html new file mode 100644 index 0000000000..c8a696b998 --- /dev/null +++ b/docs/report-examples/pmd-report-yahtml/index.html @@ -0,0 +1,20 @@ + + + + + PMD + + +

Package View

+ + + + + + + + + +
PackageClass#
Aggregate - 2
net - 2
net.sourceforge - 2
net.sourceforge.pmd - 2
net.sourceforge.pmd RuleContext 1
net.sourceforge.pmd.benchmark - 1
net.sourceforge.pmd.benchmark Benchmarker 1
+ + diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotation.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotation.java index 4297f536bf..3c702d517c 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotation.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotation.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -9,11 +9,14 @@ import java.util.Set; import java.util.TreeSet; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.annotation.InternalApi; import apex.jorje.semantic.ast.modifier.Annotation; public class ASTAnnotation extends AbstractApexNode { + @Deprecated + @InternalApi public ASTAnnotation(Annotation annotation) { super(annotation); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotationParameter.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotationParameter.java index 43bbc8cada..9229ac1d0c 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotationParameter.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotationParameter.java @@ -1,14 +1,18 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.modifier.AnnotationParameter; public class ASTAnnotationParameter extends AbstractApexNode { public static final String SEE_ALL_DATA = "seeAllData"; + @Deprecated + @InternalApi public ASTAnnotationParameter(AnnotationParameter annotationParameter) { super(annotationParameter); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnonymousClass.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnonymousClass.java index 4f63c004b1..549c1c3057 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnonymousClass.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnonymousClass.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.compilation.AnonymousClass; public class ASTAnonymousClass extends ApexRootNode { + @Deprecated + @InternalApi public ASTAnonymousClass(AnonymousClass anonymousClass) { super(anonymousClass); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTArrayLoadExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTArrayLoadExpression.java index d5f938bb6e..6d97d4d0a4 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTArrayLoadExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTArrayLoadExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.ArrayLoadExpression; public class ASTArrayLoadExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTArrayLoadExpression(ArrayLoadExpression arrayLoadExpression) { super(arrayLoadExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTArrayStoreExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTArrayStoreExpression.java index 0585b121f2..112e6ed729 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTArrayStoreExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTArrayStoreExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.ArrayStoreExpression; public class ASTArrayStoreExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTArrayStoreExpression(ArrayStoreExpression arrayStoreExpression) { super(arrayStoreExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAssignmentExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAssignmentExpression.java index de3531be71..64db7c1687 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAssignmentExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAssignmentExpression.java @@ -1,14 +1,18 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.data.ast.AssignmentOp; import apex.jorje.semantic.ast.expression.AssignmentExpression; public class ASTAssignmentExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTAssignmentExpression(AssignmentExpression assignmentExpression) { super(assignmentExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBinaryExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBinaryExpression.java index e0db793c28..4c90defcbc 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBinaryExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBinaryExpression.java @@ -1,14 +1,18 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.data.ast.BinaryOp; import apex.jorje.semantic.ast.expression.BinaryExpression; public class ASTBinaryExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTBinaryExpression(BinaryExpression binaryExpression) { super(binaryExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBindExpressions.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBindExpressions.java index 7501f3ab8f..21e081da87 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBindExpressions.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBindExpressions.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.BindExpressions; public class ASTBindExpressions extends AbstractApexNode { + @Deprecated + @InternalApi public ASTBindExpressions(BindExpressions bindExpressions) { super(bindExpressions); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBlockStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBlockStatement.java index ab16315554..edb175047a 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBlockStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBlockStatement.java @@ -1,14 +1,18 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.BlockStatement; public class ASTBlockStatement extends AbstractApexNode { private boolean curlyBrace; + @Deprecated + @InternalApi public ASTBlockStatement(BlockStatement blockStatement) { super(blockStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBooleanExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBooleanExpression.java index efd46f2a2b..c6ab8b415e 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBooleanExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBooleanExpression.java @@ -1,15 +1,19 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.data.ast.BooleanOp; import apex.jorje.semantic.ast.expression.BooleanExpression; public class ASTBooleanExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTBooleanExpression(BooleanExpression booleanExpression) { super(booleanExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBreakStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBreakStatement.java index 90b947d51b..726e94b662 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBreakStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBreakStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.BreakStatement; public class ASTBreakStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTBreakStatement(BreakStatement breakStatement) { super(breakStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBridgeMethodCreator.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBridgeMethodCreator.java index 29be1c20c0..94ec543685 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBridgeMethodCreator.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTBridgeMethodCreator.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.member.bridge.BridgeMethodCreator; public class ASTBridgeMethodCreator extends AbstractApexNode { + @Deprecated + @InternalApi public ASTBridgeMethodCreator(BridgeMethodCreator bridgeMethodCreator) { super(bridgeMethodCreator); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCastExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCastExpression.java index 1a534a6eac..76fb720d67 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCastExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCastExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.CastExpression; public class ASTCastExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTCastExpression(CastExpression node) { super(node); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java index 5c98af83f2..f547822f94 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.CatchBlockStatement; public class ASTCatchBlockStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTCatchBlockStatement(CatchBlockStatement catchBlockStatement) { super(catchBlockStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTClassRefExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTClassRefExpression.java index 92f4c5a51b..9ba400b634 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTClassRefExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTClassRefExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.ClassRefExpression; public class ASTClassRefExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTClassRefExpression(ClassRefExpression classRefExpression) { super(classRefExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTConstructorPreamble.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTConstructorPreamble.java index 3f532db8d6..0e546ae17c 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTConstructorPreamble.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTConstructorPreamble.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.compilation.ConstructorPreamble; public class ASTConstructorPreamble extends AbstractApexNode { + @Deprecated + @InternalApi public ASTConstructorPreamble(ConstructorPreamble node) { super(node); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTConstructorPreambleStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTConstructorPreambleStatement.java index e8613c2844..df6b61bb22 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTConstructorPreambleStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTConstructorPreambleStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.ConstructorPreambleStatement; public class ASTConstructorPreambleStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTConstructorPreambleStatement(ConstructorPreambleStatement constructorPreambleStatement) { super(constructorPreambleStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTContinueStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTContinueStatement.java index 9a5a80aeab..9a4a9a4bc2 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTContinueStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTContinueStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.ContinueStatement; public class ASTContinueStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTContinueStatement(ContinueStatement continueStatement) { super(continueStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlDeleteStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlDeleteStatement.java index d876498594..daaa487939 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlDeleteStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlDeleteStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.DmlDeleteStatement; public class ASTDmlDeleteStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTDmlDeleteStatement(DmlDeleteStatement dmlDeleteStatement) { super(dmlDeleteStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlInsertStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlInsertStatement.java index 2b818a94f4..6cd9727de2 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlInsertStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlInsertStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.DmlInsertStatement; public class ASTDmlInsertStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTDmlInsertStatement(DmlInsertStatement dmlInsertStatement) { super(dmlInsertStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlMergeStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlMergeStatement.java index 7e1bebb433..8ba9c05e5d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlMergeStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlMergeStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.DmlMergeStatement; public class ASTDmlMergeStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTDmlMergeStatement(DmlMergeStatement dmlMergeStatement) { super(dmlMergeStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUndeleteStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUndeleteStatement.java index 6e91324bd7..b37f2935e4 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUndeleteStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUndeleteStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.DmlUndeleteStatement; public class ASTDmlUndeleteStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTDmlUndeleteStatement(DmlUndeleteStatement dmlUndeleteStatement) { super(dmlUndeleteStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUpdateStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUpdateStatement.java index 587a536542..729969b608 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUpdateStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUpdateStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.DmlUpdateStatement; public class ASTDmlUpdateStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTDmlUpdateStatement(DmlUpdateStatement dmlUpdateStatement) { super(dmlUpdateStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUpsertStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUpsertStatement.java index 8f7512ec31..2cd7d0305a 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUpsertStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDmlUpsertStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.DmlUpsertStatement; public class ASTDmlUpsertStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTDmlUpsertStatement(DmlUpsertStatement dmlUpsertStatement) { super(dmlUpsertStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDoLoopStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDoLoopStatement.java index 6ac37c8bbe..33c2c2a361 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDoLoopStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTDoLoopStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.DoLoopStatement; public class ASTDoLoopStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTDoLoopStatement(DoLoopStatement doLoopStatement) { super(doLoopStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTExpression.java index 690ae31f5a..fa0f011f89 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.Expression; public class ASTExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTExpression(Expression expression) { super(expression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTExpressionStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTExpressionStatement.java index b913893a47..19a613a244 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTExpressionStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTExpressionStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.ExpressionStatement; public class ASTExpressionStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTExpressionStatement(ExpressionStatement expressionStatement) { super(expressionStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTField.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTField.java index 42b7375342..f0b2b7de1f 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTField.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTField.java @@ -1,15 +1,18 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.annotation.InternalApi; import apex.jorje.semantic.ast.member.Field; public class ASTField extends AbstractApexNode implements CanSuppressWarnings { + @Deprecated + @InternalApi public ASTField(Field field) { super(field); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java index 7198442c65..34a63873d1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.FieldDeclaration; public class ASTFieldDeclaration extends AbstractApexNode { + @Deprecated + @InternalApi public ASTFieldDeclaration(FieldDeclaration fieldDeclaration) { super(fieldDeclaration); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclarationStatements.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclarationStatements.java index 358b3fb733..d9b54d5691 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclarationStatements.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclarationStatements.java @@ -1,16 +1,27 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; -import net.sourceforge.pmd.Rule; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.annotation.InternalApi; + +import apex.jorje.data.Identifier; +import apex.jorje.data.ast.TypeRef; +import apex.jorje.data.ast.TypeRefs.ArrayTypeRef; +import apex.jorje.data.ast.TypeRefs.ClassTypeRef; import apex.jorje.semantic.ast.statement.FieldDeclarationStatements; public class ASTFieldDeclarationStatements extends AbstractApexNode implements CanSuppressWarnings { + @Deprecated + @InternalApi public ASTFieldDeclarationStatements(FieldDeclarationStatements fieldDeclarationStatements) { super(fieldDeclarationStatements); } @@ -35,4 +46,36 @@ public class ASTFieldDeclarationStatements extends AbstractApexNode names = node.getTypeName().getNames(); + return names.stream().map(Identifier::getValue).collect(Collectors.joining(".")); + } + return null; + } + + private static String identifiersToString(List identifiers) { + return identifiers.stream().map(Identifier::getValue).collect(Collectors.joining(".")); + } + + public List getTypeArguments() { + List result = new ArrayList<>(); + + if (node.getTypeName() != null) { + List typeArgs = node.getTypeName().getTypeArguments(); + for (TypeRef arg : typeArgs) { + if (arg instanceof ClassTypeRef) { + result.add(identifiersToString(arg.getNames())); + } else if (arg instanceof ArrayTypeRef) { + ArrayTypeRef atr = (ArrayTypeRef) arg; + if (atr.getHeldType() instanceof ClassTypeRef) { + result.add(identifiersToString(atr.getHeldType().getNames())); + } + } + } + } + + return result; + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTForEachStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTForEachStatement.java index cfabdcab9f..14f701551c 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTForEachStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTForEachStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.ForEachStatement; public class ASTForEachStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTForEachStatement(ForEachStatement forEachStatement) { super(forEachStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTForLoopStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTForLoopStatement.java index 8fb8b9610f..8d164ba3f9 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTForLoopStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTForLoopStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.ForLoopStatement; public class ASTForLoopStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTForLoopStatement(ForLoopStatement forLoopStatement) { super(forLoopStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFormalComment.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFormalComment.java index d9ca521600..c2a9750bfc 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFormalComment.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFormalComment.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.apex.ast; import org.antlr.runtime.Token; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.apex.ast.ASTFormalComment.AstComment; import apex.jorje.data.Location; @@ -50,6 +51,8 @@ public class ASTFormalComment extends AbstractApexNode { } + @Deprecated + @InternalApi public static final class AstComment implements AstNode { private final Location loc; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTIfBlockStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTIfBlockStatement.java index e2f633e6d2..7beca82eae 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTIfBlockStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTIfBlockStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.IfBlockStatement; public class ASTIfBlockStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTIfBlockStatement(IfBlockStatement ifBlockStatement) { super(ifBlockStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTIfElseBlockStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTIfElseBlockStatement.java index 92571c5cad..8d04a8a568 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTIfElseBlockStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTIfElseBlockStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.IfElseBlockStatement; public class ASTIfElseBlockStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTIfElseBlockStatement(IfElseBlockStatement ifElseBlockStatement) { super(ifElseBlockStatement); } @@ -16,4 +20,8 @@ public class ASTIfElseBlockStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTIllegalStoreExpression(IllegalStoreExpression node) { super(node); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTInstanceOfExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTInstanceOfExpression.java index f1e94593cd..f06a8fe277 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTInstanceOfExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTInstanceOfExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.InstanceOfExpression; public class ASTInstanceOfExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTInstanceOfExpression(InstanceOfExpression instanceOfExpression) { super(instanceOfExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTJavaMethodCallExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTJavaMethodCallExpression.java index ba8c2b56f0..3ec75ab95d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTJavaMethodCallExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTJavaMethodCallExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.JavaMethodCallExpression; public class ASTJavaMethodCallExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTJavaMethodCallExpression(JavaMethodCallExpression javaMethodCallExpression) { super(javaMethodCallExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTJavaVariableExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTJavaVariableExpression.java index 78c3f14e2d..a4a90e06b7 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTJavaVariableExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTJavaVariableExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.JavaVariableExpression; public class ASTJavaVariableExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTJavaVariableExpression(JavaVariableExpression javaVariableExpression) { super(javaVariableExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java index 23f6182e4b..18a8a7afbc 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -7,6 +7,8 @@ package net.sourceforge.pmd.lang.apex.ast; import java.lang.reflect.Field; import java.util.Optional; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.data.Identifier; import apex.jorje.data.ast.LiteralType; import apex.jorje.semantic.ast.expression.LiteralExpression; @@ -15,6 +17,8 @@ import apex.jorje.semantic.ast.expression.NewKeyValueObjectExpression.NameValueP public class ASTLiteralExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTLiteralExpression(LiteralExpression literalExpression) { super(literalExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMapEntryNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMapEntryNode.java index e5518792af..4ca122784f 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMapEntryNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMapEntryNode.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.MapEntryNode; public class ASTMapEntryNode extends AbstractApexNode { + @Deprecated + @InternalApi public ASTMapEntryNode(MapEntryNode mapEntryNode) { super(mapEntryNode); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java index 61a8f9505d..79f0e6bd88 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java @@ -1,10 +1,11 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.apex.metrics.signature.ApexOperationSignature; import net.sourceforge.pmd.lang.ast.SignedNode; @@ -13,6 +14,8 @@ import apex.jorje.semantic.ast.member.Method; public class ASTMethod extends AbstractApexNode implements ApexQualifiableNode, SignedNode, CanSuppressWarnings { + @Deprecated + @InternalApi public ASTMethod(Method method) { super(method); } @@ -27,6 +30,10 @@ public class ASTMethod extends AbstractApexNode implements ApexQualifiab return node.getMethodInfo().getName(); } + public String getCanonicalName() { + return node.getMethodInfo().getCanonicalName(); + } + @Override public int getEndLine() { ASTBlockStatement block = getFirstChildOfType(ASTBlockStatement.class); @@ -79,6 +86,10 @@ public class ASTMethod extends AbstractApexNode implements ApexQualifiab } public String getReturnType() { - return node.getReturnTypeRef().toString(); + return node.getMethodInfo().getEmitSignature().getReturnType().getApexName(); + } + + public int getArity() { + return node.getMethodInfo().getParameterTypes().size(); } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodBlockStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodBlockStatement.java index 98459d4634..008e4c817a 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodBlockStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodBlockStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.MethodBlockStatement; public class ASTMethodBlockStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTMethodBlockStatement(MethodBlockStatement node) { super(node); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodCallExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodCallExpression.java index 99bcd1a37f..f929a33916 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodCallExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodCallExpression.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -6,11 +6,15 @@ package net.sourceforge.pmd.lang.apex.ast; import java.util.Iterator; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.data.Identifier; import apex.jorje.semantic.ast.expression.MethodCallExpression; -public class ASTMethodCallExpression extends AbstractApexNode { +public class ASTMethodCallExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTMethodCallExpression(MethodCallExpression methodCallExpression) { super(methodCallExpression); } @@ -32,4 +36,8 @@ public class ASTMethodCallExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTModifier(Modifier node) { super(node); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java index 0fff8cab0b..59ce9ec6d3 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java @@ -1,14 +1,18 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.modifier.ModifierNode; import apex.jorje.semantic.symbol.type.ModifierTypeInfos; public class ASTModifierNode extends AbstractApexNode implements AccessNode { + @Deprecated + @InternalApi public ASTModifierNode(ModifierNode modifierNode) { super(modifierNode); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierOrAnnotation.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierOrAnnotation.java index 56e200334d..73f1daac17 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierOrAnnotation.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierOrAnnotation.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.modifier.ModifierOrAnnotation; public class ASTModifierOrAnnotation extends AbstractApexNode { + @Deprecated + @InternalApi public ASTModifierOrAnnotation(ModifierOrAnnotation modifierOrAnnotation) { super(modifierOrAnnotation); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMultiStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMultiStatement.java index 2b5f7e1d0e..8269e4625f 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMultiStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMultiStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.MultiStatement; public class ASTMultiStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTMultiStatement(MultiStatement node) { super(node); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNestedExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNestedExpression.java index 9042880702..da2ffbb30f 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNestedExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNestedExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.NestedExpression; public class ASTNestedExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTNestedExpression(NestedExpression node) { super(node); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNestedStoreExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNestedStoreExpression.java index 22fc1c9f96..fa7390f268 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNestedStoreExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNestedStoreExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.NestedStoreExpression; public class ASTNestedStoreExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTNestedStoreExpression(NestedStoreExpression node) { super(node); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewKeyValueObjectExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewKeyValueObjectExpression.java index 9ffa7b764e..f035763dc8 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewKeyValueObjectExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewKeyValueObjectExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.NewKeyValueObjectExpression; public class ASTNewKeyValueObjectExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTNewKeyValueObjectExpression(NewKeyValueObjectExpression node) { super(node); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewListInitExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewListInitExpression.java index 7ee5f8ef5b..696fffe383 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewListInitExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewListInitExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.NewListInitExpression; public class ASTNewListInitExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTNewListInitExpression(NewListInitExpression newListInitExpression) { super(newListInitExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewListLiteralExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewListLiteralExpression.java index 35d2f73e81..fd7cf10b55 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewListLiteralExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewListLiteralExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.NewListLiteralExpression; public class ASTNewListLiteralExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTNewListLiteralExpression(NewListLiteralExpression newListLiteralExpression) { super(newListLiteralExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewMapInitExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewMapInitExpression.java index 3b3e7eaca1..63ddf8d54f 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewMapInitExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewMapInitExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.NewMapInitExpression; public class ASTNewMapInitExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTNewMapInitExpression(NewMapInitExpression newMapInitExpression) { super(newMapInitExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewMapLiteralExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewMapLiteralExpression.java index 77cac52fa0..36bac109f7 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewMapLiteralExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewMapLiteralExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.NewMapLiteralExpression; public class ASTNewMapLiteralExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTNewMapLiteralExpression(NewMapLiteralExpression newMapLiteralExpression) { super(newMapLiteralExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java index 63c6465538..71247eea83 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.NewObjectExpression; public class ASTNewObjectExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTNewObjectExpression(NewObjectExpression newObjectExpression) { super(newObjectExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewSetInitExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewSetInitExpression.java index 130a0603fd..5302e1fc42 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewSetInitExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewSetInitExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.NewSetInitExpression; public class ASTNewSetInitExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTNewSetInitExpression(NewSetInitExpression newSetInitExpression) { super(newSetInitExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewSetLiteralExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewSetLiteralExpression.java index 43517f85c6..b01d551a68 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewSetLiteralExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewSetLiteralExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.NewSetLiteralExpression; public class ASTNewSetLiteralExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTNewSetLiteralExpression(NewSetLiteralExpression newSetLiteralExpression) { super(newSetLiteralExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPackageVersionExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPackageVersionExpression.java index 3313363370..2ddb588532 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPackageVersionExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPackageVersionExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.PackageVersionExpression; public class ASTPackageVersionExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTPackageVersionExpression(PackageVersionExpression packageVersionExpression) { super(packageVersionExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTParameter.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTParameter.java index 22c1924e65..54e7fbbebd 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTParameter.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTParameter.java @@ -1,15 +1,18 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.annotation.InternalApi; import apex.jorje.semantic.ast.member.Parameter; public class ASTParameter extends AbstractApexNode implements CanSuppressWarnings { + @Deprecated + @InternalApi public ASTParameter(Parameter parameter) { super(parameter); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPostfixExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPostfixExpression.java index 5a760da8b2..5d3c288fbc 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPostfixExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPostfixExpression.java @@ -1,15 +1,19 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.data.ast.PostfixOp; import apex.jorje.semantic.ast.expression.PostfixExpression; public class ASTPostfixExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTPostfixExpression(PostfixExpression postfixExpression) { super(postfixExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPrefixExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPrefixExpression.java index 4dd4a20cde..c79fa8214f 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPrefixExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTPrefixExpression.java @@ -1,14 +1,18 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.data.ast.PrefixOp; import apex.jorje.semantic.ast.expression.PrefixExpression; public class ASTPrefixExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTPrefixExpression(PrefixExpression prefixExpression) { super(prefixExpression); } @@ -22,5 +26,4 @@ public class ASTPrefixExpression extends AbstractApexNode { public PrefixOp getOperator() { return node.getOp(); } - } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java index f73ac2c761..415a4b73d2 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.member.Property; public class ASTProperty extends AbstractApexNode { + @Deprecated + @InternalApi public ASTProperty(Property property) { super(property); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReferenceExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReferenceExpression.java index 3d76d4f12e..197ba04899 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReferenceExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReferenceExpression.java @@ -1,9 +1,16 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import net.sourceforge.pmd.annotation.InternalApi; + +import apex.jorje.data.Identifier; import apex.jorje.semantic.ast.expression.IdentifierContext; import apex.jorje.semantic.ast.expression.ReferenceExpression; import apex.jorje.semantic.ast.expression.ReferenceType; @@ -11,6 +18,8 @@ import apex.jorje.semantic.ast.expression.ReferenceType; public class ASTReferenceExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTReferenceExpression(ReferenceExpression referenceExpression) { super(referenceExpression); } @@ -38,4 +47,12 @@ public class ASTReferenceExpression extends AbstractApexNode getNames() { + List identifiers = node.getNames(); + if (identifiers != null) { + return identifiers.stream().map(id -> id.getValue()).collect(Collectors.toList()); + } + return Collections.emptyList(); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReturnStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReturnStatement.java index dfe345408e..327737875d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReturnStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReturnStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.ReturnStatement; public class ASTReturnStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTReturnStatement(ReturnStatement returnStatement) { super(returnStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTRunAsBlockStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTRunAsBlockStatement.java index ff2b84eef4..d28a058fa0 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTRunAsBlockStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTRunAsBlockStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.RunAsBlockStatement; public class ASTRunAsBlockStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTRunAsBlockStatement(RunAsBlockStatement runAsBlockStatement) { super(runAsBlockStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSoqlExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSoqlExpression.java index 844789a8b8..2bc1e4c1b6 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSoqlExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSoqlExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.SoqlExpression; public class ASTSoqlExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTSoqlExpression(SoqlExpression soqlExpression) { super(soqlExpression); } @@ -18,6 +22,10 @@ public class ASTSoqlExpression extends AbstractApexNode { } public String getQuery() { - return getNode().getRawQuery(); + return node.getRawQuery(); + } + + public String getCanonicalQuery() { + return node.getCanonicalQuery(); } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSoslExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSoslExpression.java index b773d346aa..8c18d396ef 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSoslExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSoslExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.SoslExpression; public class ASTSoslExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTSoslExpression(SoslExpression soslExpression) { super(soslExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStandardCondition.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStandardCondition.java index 9260962ef9..b79ca67745 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStandardCondition.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStandardCondition.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.condition.StandardCondition; public class ASTStandardCondition extends AbstractApexNode { + @Deprecated + @InternalApi public ASTStandardCondition(StandardCondition standardCondition) { super(standardCondition); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStatement.java index 9fe6e7dd1c..e48abb09c5 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.Statement; public class ASTStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTStatement(Statement statement) { super(statement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStatementExecuted.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStatementExecuted.java index 0e4b865065..914e3ccf64 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStatementExecuted.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTStatementExecuted.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.StatementExecuted; public class ASTStatementExecuted extends AbstractApexNode { + @Deprecated + @InternalApi public ASTStatementExecuted(StatementExecuted node) { super(node); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSuperMethodCallExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSuperMethodCallExpression.java index 1dfbd47f46..b9a212218d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSuperMethodCallExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSuperMethodCallExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.SuperMethodCallExpression; public class ASTSuperMethodCallExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTSuperMethodCallExpression(SuperMethodCallExpression superMethodCallExpression) { super(superMethodCallExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSuperVariableExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSuperVariableExpression.java index 2b13cb7171..de53c55be1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSuperVariableExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTSuperVariableExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.SuperVariableExpression; public class ASTSuperVariableExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTSuperVariableExpression(SuperVariableExpression superVariableExpression) { super(superVariableExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTernaryExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTernaryExpression.java index 3aa5622d52..f1ae4308f1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTernaryExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTernaryExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.TernaryExpression; public class ASTTernaryExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTTernaryExpression(TernaryExpression ternaryExpression) { super(ternaryExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThisMethodCallExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThisMethodCallExpression.java index b3f1194c2e..da3fd387bb 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThisMethodCallExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThisMethodCallExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.ThisMethodCallExpression; public class ASTThisMethodCallExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTThisMethodCallExpression(ThisMethodCallExpression thisMethodCallExpression) { super(thisMethodCallExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThisVariableExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThisVariableExpression.java index d28e79a949..45e195008b 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThisVariableExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThisVariableExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.ThisVariableExpression; public class ASTThisVariableExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTThisVariableExpression(ThisVariableExpression thisVariableExpression) { super(thisVariableExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThrowStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThrowStatement.java index 00c977f9ca..3473633cf6 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThrowStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTThrowStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.ThrowStatement; public class ASTThrowStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTThrowStatement(ThrowStatement throwStatement) { super(throwStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTriggerVariableExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTriggerVariableExpression.java index 45260316cc..b1edad0a55 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTriggerVariableExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTriggerVariableExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.TriggerVariableExpression; public class ASTTriggerVariableExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTTriggerVariableExpression(TriggerVariableExpression triggerVariableExpression) { super(triggerVariableExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTryCatchFinallyBlockStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTryCatchFinallyBlockStatement.java index 07d8e8e83f..e2d81d20e1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTryCatchFinallyBlockStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTTryCatchFinallyBlockStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.TryCatchFinallyBlockStatement; public class ASTTryCatchFinallyBlockStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTTryCatchFinallyBlockStatement(TryCatchFinallyBlockStatement tryCatchFinallyBlockStatement) { super(tryCatchFinallyBlockStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClass.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClass.java index e84927e931..6f24713f30 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClass.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClass.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -8,6 +8,7 @@ import java.util.List; import java.util.stream.Collectors; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.annotation.InternalApi; import apex.jorje.data.Identifier; import apex.jorje.data.ast.TypeRef; @@ -18,6 +19,8 @@ public class ASTUserClass extends ApexRootNode implements ASTUserClas private ApexQualifiedName qname; + @Deprecated + @InternalApi public ASTUserClass(UserClass userClass) { super(userClass); } @@ -31,7 +34,7 @@ public class ASTUserClass extends ApexRootNode implements ASTUserClas @Override public String getImage() { - String apexName = node.getDefiningType().getApexName(); + String apexName = getDefiningType(); return apexName.substring(apexName.lastIndexOf('.') + 1); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClassMethods.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClassMethods.java index 0146a2d3c6..76cd5b07a7 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClassMethods.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClassMethods.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.compilation.UserClassMethods; public class ASTUserClassMethods extends AbstractApexNode { + @Deprecated + @InternalApi public ASTUserClassMethods(UserClassMethods userClassMethods) { super(userClassMethods); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClassOrInterface.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClassOrInterface.java index 467656d132..ba1004562a 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClassOrInterface.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClassOrInterface.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserEnum.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserEnum.java index 54e5034fdc..4aef1641cc 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserEnum.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserEnum.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.compilation.UserEnum; public class ASTUserEnum extends ApexRootNode { + @Deprecated + @InternalApi public ASTUserEnum(UserEnum userEnum) { super(userEnum); } @@ -19,7 +23,7 @@ public class ASTUserEnum extends ApexRootNode { @Override public String getImage() { - String apexName = node.getDefiningType().getApexName(); + String apexName = getDefiningType(); return apexName.substring(apexName.lastIndexOf('.') + 1); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserExceptionMethods.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserExceptionMethods.java index 25306a1e5c..7e64a79f7c 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserExceptionMethods.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserExceptionMethods.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.compilation.UserExceptionMethods; public class ASTUserExceptionMethods extends AbstractApexNode { + @Deprecated + @InternalApi public ASTUserExceptionMethods(UserExceptionMethods userExceptionMethods) { super(userExceptionMethods); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserInterface.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserInterface.java index fa3d25a075..0b3baa8899 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserInterface.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserInterface.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.apex.ast; import java.util.stream.Collectors; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.annotation.InternalApi; import apex.jorje.data.Identifier; import apex.jorje.data.ast.TypeRef; @@ -17,6 +18,8 @@ public class ASTUserInterface extends ApexRootNode implements AST private ApexQualifiedName qname; + @Deprecated + @InternalApi public ASTUserInterface(UserInterface userInterface) { super(userInterface); } @@ -28,7 +31,7 @@ public class ASTUserInterface extends ApexRootNode implements AST @Override public String getImage() { - String apexName = node.getDefiningType().getApexName(); + String apexName = getDefiningType(); return apexName.substring(apexName.lastIndexOf('.') + 1); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserTrigger.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserTrigger.java index 001655fed6..d956874681 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserTrigger.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserTrigger.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -7,11 +7,15 @@ package net.sourceforge.pmd.lang.apex.ast; import java.util.List; import java.util.stream.Collectors; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.data.Identifier; import apex.jorje.semantic.ast.compilation.UserTrigger; public class ASTUserTrigger extends ApexRootNode { + @Deprecated + @InternalApi public ASTUserTrigger(UserTrigger userTrigger) { super(userTrigger); } @@ -23,7 +27,7 @@ public class ASTUserTrigger extends ApexRootNode { @Override public String getImage() { - return node.getDefiningType().getApexName(); + return getDefiningType(); } public ASTModifierNode getModifiers() { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclaration.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclaration.java index 9e105150a2..3e58f0a021 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclaration.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclaration.java @@ -1,15 +1,18 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.annotation.InternalApi; import apex.jorje.semantic.ast.statement.VariableDeclaration; public class ASTVariableDeclaration extends AbstractApexNode implements CanSuppressWarnings { + @Deprecated + @InternalApi public ASTVariableDeclaration(VariableDeclaration variableDeclaration) { super(variableDeclaration); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclarationStatements.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclarationStatements.java index 77dbb33074..3d6ba600b4 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclarationStatements.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclarationStatements.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.VariableDeclarationStatements; public class ASTVariableDeclarationStatements extends AbstractApexNode { + @Deprecated + @InternalApi public ASTVariableDeclarationStatements(VariableDeclarationStatements variableDeclarationStatements) { super(variableDeclarationStatements); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableExpression.java index 146d2c0c0c..735c2839ce 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableExpression.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.VariableExpression; public class ASTVariableExpression extends AbstractApexNode { + @Deprecated + @InternalApi public ASTVariableExpression(VariableExpression variableExpression) { super(variableExpression); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTWhileLoopStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTWhileLoopStatement.java index f24d2854f8..0b2aa1c6bb 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTWhileLoopStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTWhileLoopStatement.java @@ -1,13 +1,17 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.statement.WhileLoopStatement; public class ASTWhileLoopStatement extends AbstractApexNode { + @Deprecated + @InternalApi public ASTWhileLoopStatement(WhileLoopStatement whileLoopStatement) { super(whileLoopStatement); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNode.java index 9fb1539229..42e27a12c1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNode.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -54,6 +54,8 @@ public abstract class AbstractApexNode extends AbstractApexNo // default implementation does nothing } + @Deprecated + @InternalApi @Override public T getNode() { return node; @@ -79,4 +81,20 @@ public abstract class AbstractApexNode extends AbstractApexNo return "no location"; } } + + @Override + public String getDefiningType() { + if (node.getDefiningType() != null) { + return node.getDefiningType().getApexName(); + } + return null; + } + + @Override + public String getNamespace() { + if (node.getDefiningType() != null) { + return node.getDefiningType().getNamespace().toString(); + } + return null; + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNodeBase.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNodeBase.java index c02a8a72c8..620d154409 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNodeBase.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNodeBase.java @@ -1,9 +1,10 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.AbstractNode; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.SourceCodePositioner; @@ -12,6 +13,7 @@ import net.sourceforge.pmd.lang.ast.SourceCodePositioner; * @deprecated Use {@link ApexNode} */ @Deprecated +@InternalApi public abstract class AbstractApexNodeBase extends AbstractNode { public AbstractApexNodeBase(Class klass) { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AccessNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AccessNode.java index e3016d3b86..2255a734b3 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AccessNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AccessNode.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexNode.java index c7889f6beb..a89ac64f48 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexNode.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -35,7 +35,11 @@ public interface ApexNode extends Node { /** * Get the underlying AST node. + * @deprecated the underlying AST node should not be available outside of the AST node. + * If information is needed from the underlying node, then PMD's AST node need to expose + * this information. */ + @Deprecated T getNode(); @@ -51,4 +55,8 @@ public interface ApexNode extends Node { ApexNode getParent(); boolean hasRealLoc(); + + String getDefiningType(); + + String getNamespace(); } 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 5bec6fbace..798c330966 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 @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitor.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitor.java index cb6497ce7d..bda42b7e8c 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitor.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitor.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitorAdapter.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitorAdapter.java index 3a58a233f1..45218ccd21 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitorAdapter.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitorAdapter.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitorReducedAdapter.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitorReducedAdapter.java index f989a95bde..1a55a5f148 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitorReducedAdapter.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParserVisitorReducedAdapter.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexQualifiableNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexQualifiableNode.java index 13cfb51347..b7bd43667b 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexQualifiableNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexQualifiableNode.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexQualifiedName.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexQualifiedName.java index 0757b833f6..6c8e5b48ac 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexQualifiedName.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexQualifiedName.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -133,8 +133,8 @@ public final class ApexQualifiedName implements QualifiedName { } - static ApexQualifiedName ofOuterClass(ASTUserClassOrInterface astUserClass) { - String ns = astUserClass.getNode().getDefiningType().getNamespace().toString(); + static ApexQualifiedName ofOuterClass(ASTUserClassOrInterface astUserClass) { + String ns = astUserClass.getNamespace(); String[] classes = {astUserClass.getImage()}; return new ApexQualifiedName(StringUtils.isEmpty(ns) ? "c" : ns, classes, null); } @@ -153,7 +153,7 @@ public final class ApexQualifiedName implements QualifiedName { sb.append(node.getImage()).append('('); - List paramTypes = node.getNode().getMethodInfo().getParameterTypes(); + List paramTypes = node.node.getMethodInfo().getParameterTypes(); if (!paramTypes.isEmpty()) { sb.append(paramTypes.get(0).getApexName()); @@ -174,8 +174,8 @@ public final class ApexQualifiedName implements QualifiedName { ASTUserClassOrInterface parent = node.getFirstParentOfType(ASTUserClassOrInterface.class); if (parent == null) { ASTUserTrigger trigger = node.getFirstParentOfType(ASTUserTrigger.class); - String ns = trigger.getNode().getDefiningType().getNamespace().toString(); - String targetObj = trigger.getNode().getTargetName().get(0).getValue(); + String ns = trigger.getNamespace(); + String targetObj = trigger.getTargetName(); return new ApexQualifiedName(StringUtils.isEmpty(ns) ? "c" : ns, new String[]{"trigger", targetObj}, trigger.getImage()); // uses a reserved word as a class name to prevent clashes 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 f2a0fcfa40..13f756ca1d 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 @@ -1,16 +1,21 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.RootNode; import net.sourceforge.pmd.lang.ast.SourceCodePositioner; import apex.jorje.semantic.ast.AstNode; import apex.jorje.services.Version; +@Deprecated +@InternalApi public abstract class ApexRootNode extends AbstractApexNode implements RootNode { + @Deprecated + @InternalApi public ApexRootNode(T node) { super(node); } @@ -30,6 +35,6 @@ public abstract class ApexRootNode extends AbstractApexNode { private static final Map, Constructor>> diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/CanSuppressWarnings.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/CanSuppressWarnings.java index 0aa0b9ba84..0792cacce6 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/CanSuppressWarnings.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/CanSuppressWarnings.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/CompilerService.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/CompilerService.java index 5b62b786b4..3fa0de818b 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/CompilerService.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/CompilerService.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -11,6 +11,8 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.reflect.FieldUtils; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.visitor.AdditionalPassScope; import apex.jorje.semantic.ast.visitor.AstVisitor; import apex.jorje.semantic.compiler.ApexCompiler; @@ -36,6 +38,8 @@ import com.google.common.collect.ImmutableList; * @author nchen * */ +@Deprecated +@InternalApi public class CompilerService { public static final CompilerService INSTANCE = new CompilerService(); private final SymbolProvider symbolProvider; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/EmptySymbolProvider.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/EmptySymbolProvider.java index 3a01f8925b..1f09b977f4 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/EmptySymbolProvider.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/EmptySymbolProvider.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ // Note: taken from https://github.com/forcedotcom/idecore/blob/3083815933c2d015d03417986f57bd25786d58ce/com.salesforce.ide.apex.core/src/com/salesforce/ide/apex/internal/core/EmptySymbolProvider.java @@ -21,6 +21,8 @@ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.compiler.Namespace; import apex.jorje.semantic.compiler.sfdc.SymbolProvider; import apex.jorje.semantic.symbol.resolver.SymbolResolver; @@ -29,6 +31,8 @@ import apex.jorje.semantic.symbol.type.TypeInfo; /** * @author jspagnola */ +@Deprecated +@InternalApi public final class EmptySymbolProvider implements SymbolProvider { private static final EmptySymbolProvider INSTANCE = new EmptySymbolProvider(); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TestAccessEvaluator.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TestAccessEvaluator.java index 9e22af4e7b..48e62d76fc 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TestAccessEvaluator.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TestAccessEvaluator.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ // Note: taken from https://github.com/forcedotcom/idecore/blob/3083815933c2d015d03417986f57bd25786d58ce/com.salesforce.ide.apex.core/src/apex/jorje/semantic/common/TestAccessEvaluator.java @@ -26,6 +26,8 @@ import java.util.HashSet; import java.util.Objects; import java.util.Set; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.compiler.Namespace; import apex.jorje.semantic.compiler.StructuredVersion; import apex.jorje.semantic.compiler.sfdc.AccessEvaluator; @@ -45,6 +47,8 @@ import com.google.common.collect.SetMultimap; * * @author jspagnola */ +@Deprecated +@InternalApi public class TestAccessEvaluator implements AccessEvaluator { private final SetMultimap validPageVersions; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TestQueryValidators.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TestQueryValidators.java index 5396c5bb34..3d62ce3a33 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TestQueryValidators.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TestQueryValidators.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ // Note: taken from https://github.com/forcedotcom/idecore/blob/3083815933c2d015d03417986f57bd25786d58ce/com.salesforce.ide.apex.core/src/apex/jorje/semantic/common/TestQueryValidators.java @@ -22,6 +22,8 @@ package net.sourceforge.pmd.lang.apex.ast; +import net.sourceforge.pmd.annotation.InternalApi; + import apex.jorje.semantic.ast.expression.SoqlExpression; import apex.jorje.semantic.ast.expression.SoslExpression; import apex.jorje.semantic.ast.visitor.ValidationScope; @@ -35,6 +37,8 @@ import apex.jorje.semantic.symbol.resolver.SymbolResolver; * @author jspagnola */ @SuppressWarnings("PMD.MissingStaticMethodInNonInstantiatableClass") // this class provides utility classes +@Deprecated +@InternalApi public final class TestQueryValidators { private TestQueryValidators() { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TriggerUsage.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TriggerUsage.java index 55352bc032..c64dfe54a4 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TriggerUsage.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/TriggerUsage.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/visitors/CognitiveComplexityVisitor.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/visitors/CognitiveComplexityVisitor.java index 9cfb32b325..79fdeae1c6 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/visitors/CognitiveComplexityVisitor.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/metrics/impl/visitors/CognitiveComplexityVisitor.java @@ -83,7 +83,7 @@ public class CognitiveComplexityVisitor extends ApexParserVisitorAdapter { public Object visit(ASTIfElseBlockStatement node, Object data) { State state = (State) data; - boolean hasElseStatement = node.getNode().hasElseStatement(); + boolean hasElseStatement = node.hasElseStatement(); for (ApexNode child : node.children()) { // If we don't have an else statement, we get an empty block statement which we shouldn't count if (!hasElseStatement && child instanceof ASTBlockStatement) { @@ -184,7 +184,7 @@ public class CognitiveComplexityVisitor extends ApexParserVisitorAdapter { public Object visit(ASTBooleanExpression node, Object data) { State state = (State) data; - BooleanOp op = node.getNode().getOp(); + BooleanOp op = node.getOperator(); if (op == BooleanOp.AND || op == BooleanOp.OR) { state.booleanOperation(op); } @@ -196,7 +196,7 @@ public class CognitiveComplexityVisitor extends ApexParserVisitorAdapter { public Object visit(ASTPrefixExpression node, Object data) { State state = (State) data; - PrefixOp op = node.getNode().getOp(); + PrefixOp op = node.getOperator(); if (op == PrefixOp.NOT) { state.booleanOperation(null); } @@ -222,14 +222,14 @@ public class CognitiveComplexityVisitor extends ApexParserVisitorAdapter { @Override public Object visit(ASTMethod node, Object data) { State state = (State) data; - state.setMethodName(node.getNode().getMethodInfo().getCanonicalName()); + state.setMethodName(node.getCanonicalName()); return super.visit(node, data); } @Override public Object visit(ASTMethodCallExpression node, Object data) { State state = (State) data; - state.methodCall(node.getNode().getMethodName()); + state.methodCall(node.getMethodName()); return super.visit(node, data); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/internal/Helper.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/internal/Helper.java index c2145d05c7..1901420c19 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/internal/Helper.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/internal/Helper.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.apex.rule.internal; import java.util.Arrays; import java.util.List; import java.util.Locale; -import java.util.stream.Collectors; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.apex.ast.ASTDmlDeleteStatement; @@ -30,14 +29,6 @@ import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration; import net.sourceforge.pmd.lang.apex.ast.ASTVariableExpression; import net.sourceforge.pmd.lang.apex.ast.ApexNode; -import apex.jorje.data.Identifier; -import apex.jorje.data.ast.TypeRef; -import apex.jorje.semantic.ast.expression.MethodCallExpression; -import apex.jorje.semantic.ast.expression.VariableExpression; -import apex.jorje.semantic.ast.member.Field; -import apex.jorje.semantic.ast.member.Parameter; -import apex.jorje.semantic.ast.statement.VariableDeclaration; - /** * Helper methods * @@ -60,7 +51,7 @@ public final class Helper { } } - final String className = node.getNode().getDefiningType().getApexName(); + final String className = node.getDefiningType(); return className.endsWith("Test"); } @@ -96,16 +87,12 @@ public final class Helper { final String methodName) { final ASTReferenceExpression reference = methodNode.getFirstChildOfType(ASTReferenceExpression.class); - return reference != null && reference.getNode().getNames().size() == 1 - && reference.getNode().getNames().get(0).getValue().equalsIgnoreCase(className) + return reference != null && reference.getNames().size() == 1 + && reference.getNames().get(0).equalsIgnoreCase(className) && (methodName.equals(ANY_METHOD) || isMethodName(methodNode, methodName)); } public static boolean isMethodName(final ASTMethodCallExpression m, final String methodName) { - return isMethodName(m.getNode(), methodName); - } - - static boolean isMethodName(final MethodCallExpression m, final String methodName) { return m.getMethodName().equalsIgnoreCase(methodName); } @@ -134,67 +121,54 @@ public final class Helper { public static String getFQVariableName(final ASTVariableExpression variable) { final ASTReferenceExpression ref = variable.getFirstChildOfType(ASTReferenceExpression.class); String objectName = ""; - if (ref != null && ref.getNode().getNames().size() == 1) { - objectName = ref.getNode().getNames().get(0).getValue() + "."; + if (ref != null && ref.getNames().size() == 1) { + objectName = ref.getNames().get(0) + "."; } - VariableExpression n = variable.getNode(); - StringBuilder sb = new StringBuilder().append(n.getDefiningType().getApexName()).append(":").append(objectName) - .append(n.getIdentifier().getValue()); + StringBuilder sb = new StringBuilder().append(variable.getDefiningType()).append(":").append(objectName) + .append(variable.getImage()); return sb.toString(); } public static String getFQVariableName(final ASTVariableDeclaration variable) { - VariableDeclaration n = variable.getNode(); - StringBuilder sb = new StringBuilder().append(n.getDefiningType().getApexName()).append(":") - .append(n.getLocalInfo().getName()); + StringBuilder sb = new StringBuilder().append(variable.getDefiningType()).append(":") + .append(variable.getImage()); return sb.toString(); } public static String getFQVariableName(final ASTField variable) { - Field n = variable.getNode(); StringBuilder sb = new StringBuilder() - .append(n.getDefiningType().getApexName()).append(":") - .append(n.getFieldInfo().getName()); + .append(variable.getDefiningType()).append(":") + .append(variable.getName()); return sb.toString(); } static String getVariableType(final ASTField variable) { - Field n = variable.getNode(); - StringBuilder sb = new StringBuilder().append(n.getDefiningType().getApexName()).append(":") - .append(n.getFieldInfo().getName()); + StringBuilder sb = new StringBuilder().append(variable.getDefiningType()).append(":") + .append(variable.getName()); return sb.toString(); } public static String getFQVariableName(final ASTFieldDeclaration variable) { StringBuilder sb = new StringBuilder() - .append(variable.getNode().getDefiningType().getApexName()).append(":") + .append(variable.getDefiningType()).append(":") .append(variable.getImage()); return sb.toString(); } public static String getFQVariableName(final ASTNewKeyValueObjectExpression variable) { StringBuilder sb = new StringBuilder() - .append(variable.getNode().getDefiningType().getApexName()).append(":") + .append(variable.getDefiningType()).append(":") .append(variable.getType()); return sb.toString(); } public static boolean isSystemLevelClass(ASTUserClass node) { - List interfaces = node.getNode().getDefiningType().getCodeUnitDetails().getInterfaceTypeRefs(); - - for (TypeRef intObject : interfaces) { - if (isWhitelisted(intObject.getNames())) { - return true; - } - } - - return false; + List interfaces = node.getInterfaceNames(); + return interfaces.stream().anyMatch(Helper::isWhitelisted); } - private static boolean isWhitelisted(List ids) { - String identifier = ids.stream().map(Identifier::getValue).collect(Collectors.joining(".")); - + private static boolean isWhitelisted(String identifier) { switch (identifier.toLowerCase(Locale.ROOT)) { case "queueable": case "database.batchable": @@ -206,15 +180,9 @@ public final class Helper { return false; } - public static String getFQVariableName(Parameter p) { - StringBuilder sb = new StringBuilder(); - sb.append(p.getDefiningType()).append(":").append(p.getName().getValue()); - return sb.toString(); - } - public static String getFQVariableName(ASTParameter p) { StringBuilder sb = new StringBuilder(); - sb.append(p.getNode().getDefiningType()).append(":").append(p.getImage()); + sb.append(p.getDefiningType()).append(":").append(p.getImage()); return sb.toString(); } 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 7616100ee3..90fcb023a8 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 @@ -45,10 +45,6 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; import net.sourceforge.pmd.lang.apex.rule.internal.Helper; import net.sourceforge.pmd.lang.ast.Node; -import apex.jorje.data.Identifier; -import apex.jorje.data.ast.TypeRef; -import apex.jorje.data.ast.TypeRefs.ArrayTypeRef; -import apex.jorje.data.ast.TypeRefs.ClassTypeRef; import com.google.common.base.Objects; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; @@ -108,9 +104,9 @@ public class ApexCRUDViolationRule extends AbstractApexRule { className = node.getImage(); for (ASTMethod n : node.findDescendantsOfType(ASTMethod.class)) { - StringBuilder sb = new StringBuilder().append(n.getNode().getDefiningType().getApexName()).append(":") - .append(n.getNode().getMethodInfo().getCanonicalName()).append(":") - .append(n.getNode().getMethodInfo().getParameterTypes().size()); + StringBuilder sb = new StringBuilder().append(n.getDefiningType()).append(":") + .append(n.getCanonicalName()).append(":") + .append(n.getArity()); classMethods.put(sb.toString(), n); } @@ -166,7 +162,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { @Override public Object visit(final ASTVariableDeclaration node, Object data) { - String type = node.getNode().getLocalInfo().getType().getApexName(); + String type = node.getType(); addVariableToMapping(Helper.getFQVariableName(node), type); final ASTSoqlExpression soql = node.getFirstChildOfType(ASTSoqlExpression.class); @@ -182,23 +178,18 @@ public class ApexCRUDViolationRule extends AbstractApexRule { public Object visit(final ASTFieldDeclaration node, Object data) { ASTFieldDeclarationStatements field = node.getFirstParentOfType(ASTFieldDeclarationStatements.class); if (field != null) { - TypeRef a = field.getNode().getTypeName(); - List names = a.getNames(); - List typeArgs = a.getTypeArguments(); + String namesString = field.getTypeName(); - if (!names.isEmpty()) { - String namesString = names.stream().map(Identifier::getValue).collect(Collectors.joining(".")); - - switch (namesString.toLowerCase(Locale.ROOT)) { - case "list": - case "map": - addParametersToMapping(node, typeArgs); - break; - default: - varToTypeMapping.put(Helper.getFQVariableName(node), getSimpleType(namesString)); - break; + switch (namesString.toLowerCase(Locale.ROOT)) { + case "list": + case "map": + for (String typeArg : field.getTypeArguments()) { + varToTypeMapping.put(Helper.getFQVariableName(node), typeArg); } - + break; + default: + varToTypeMapping.put(Helper.getFQVariableName(node), getSimpleType(namesString)); + break; } } final ASTSoqlExpression soql = node.getFirstChildOfType(ASTSoqlExpression.class); @@ -210,30 +201,6 @@ public class ApexCRUDViolationRule extends AbstractApexRule { } - private void addParametersToMapping(final ASTFieldDeclaration node, List typeArgs) { - for (int i = 0; i < typeArgs.size(); i++) { - if (typeArgs.get(i) instanceof ClassTypeRef) { - innerAddParametrizedClassToMapping(node, (ClassTypeRef) typeArgs.get(i)); - } - if (typeArgs.get(i) instanceof ArrayTypeRef) { - ArrayTypeRef atr = (ArrayTypeRef) typeArgs.get(i); - if (atr.getHeldType() instanceof ClassTypeRef) { - innerAddParametrizedClassToMapping(node, (ClassTypeRef) atr.getHeldType()); - } - } - } - } - - private void innerAddParametrizedClassToMapping(final ASTFieldDeclaration node, final ClassTypeRef innerClassRef) { - List ids = innerClassRef.getNames(); - StringBuffer argType = new StringBuffer(); - for (Identifier id : ids) { - argType.append(id.getValue()).append("."); - } - argType.deleteCharAt(argType.length() - 1); - addVariableToMapping(Helper.getFQVariableName(node), argType.toString()); - } - @Override public Object visit(final ASTReturnStatement node, Object data) { final ASTSoqlExpression soql = node.getFirstChildOfType(ASTSoqlExpression.class); @@ -286,9 +253,9 @@ public class ApexCRUDViolationRule extends AbstractApexRule { return; } - List a = ref.getNode().getNames(); + List a = ref.getNames(); if (!a.isEmpty()) { - extractObjectAndFields(a, method, node.getNode().getDefiningType().getApexName()); + extractObjectAndFields(a, method, node.getDefiningType()); } else { // see if ESAPI if (Helper.isMethodCallChain(node, ESAPI_ISAUTHORIZED_TO_VIEW)) { @@ -325,8 +292,8 @@ public class ApexCRUDViolationRule extends AbstractApexRule { private boolean isLastMethodName(final ASTMethodCallExpression methodNode, final String className, final String methodName) { final ASTReferenceExpression reference = methodNode.getFirstChildOfType(ASTReferenceExpression.class); - if (reference != null && reference.getNode().getNames().size() > 0) { - if (reference.getNode().getNames().get(reference.getNode().getNames().size() - 1).getValue() + if (reference != null && reference.getNames().size() > 0) { + if (reference.getNames().get(reference.getNames().size() - 1) .equalsIgnoreCase(className) && Helper.isMethodName(methodNode, methodName)) { return true; } @@ -344,20 +311,19 @@ public class ApexCRUDViolationRule extends AbstractApexRule { private String getType(final ASTMethodCallExpression methodNode) { final ASTReferenceExpression reference = methodNode.getFirstChildOfType(ASTReferenceExpression.class); - if (reference.getNode().getNames().size() > 0) { - return new StringBuilder().append(reference.getNode().getDefiningType().getApexName()).append(":") - .append(reference.getNode().getNames().get(0).getValue()).toString(); + if (reference.getNames().size() > 0) { + return new StringBuilder().append(reference.getDefiningType()).append(":") + .append(reference.getNames().get(0)).toString(); } return ""; } - private void extractObjectAndFields(final List listIdentifiers, final String method, + private void extractObjectAndFields(final List listIdentifiers, final String method, final String definingType) { - final List strings = listIdentifiers.stream().map(id -> id.getValue()).collect(Collectors.toList()); - int flsIndex = Collections.lastIndexOfSubList(strings, Arrays.asList(RESERVED_KEYS_FLS)); + int flsIndex = Collections.lastIndexOfSubList(listIdentifiers, Arrays.asList(RESERVED_KEYS_FLS)); if (flsIndex != -1) { - String objectTypeName = strings.get(flsIndex + RESERVED_KEYS_FLS.length); + String objectTypeName = listIdentifiers.get(flsIndex + RESERVED_KEYS_FLS.length); if (!typeToDMLOperationMapping.get(definingType + ":" + objectTypeName).contains(method)) { typeToDMLOperationMapping.put(definingType + ":" + objectTypeName, method); } @@ -388,7 +354,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { if (variable != null) { final String type = varToTypeMapping.get(Helper.getFQVariableName(variable)); if (type != null) { - StringBuilder typeCheck = new StringBuilder().append(node.getNode().getDefiningType().getApexName()) + StringBuilder typeCheck = new StringBuilder().append(node.getDefiningType()) .append(":").append(type); validateCRUDCheckPresent(node, data, crudMethod, typeCheck.toString()); @@ -471,8 +437,8 @@ public class ApexCRUDViolationRule extends AbstractApexRule { } private ASTMethod resolveMethodCalls(final ASTMethodCallExpression node) { - StringBuilder sb = new StringBuilder().append(node.getNode().getDefiningType().getApexName()).append(":") - .append(node.getNode().getMethodName()).append(":").append(node.getNode().getInputParameters().size()); + StringBuilder sb = new StringBuilder().append(node.getDefiningType()).append(":") + .append(node.getMethodName()).append(":").append(node.getInputParametersSize()); return classMethods.get(sb.toString()); } @@ -495,10 +461,10 @@ public class ApexCRUDViolationRule extends AbstractApexRule { if (var != null) { final ASTReferenceExpression reference = var.getFirstChildOfType(ASTReferenceExpression.class); if (reference != null) { - List identifiers = reference.getNode().getNames(); + List identifiers = reference.getNames(); if (identifiers.size() == 1) { - StringBuilder sb = new StringBuilder().append(node.getNode().getDefiningType().getApexName()) - .append(":").append(identifiers.get(0).getValue()); + StringBuilder sb = new StringBuilder().append(node.getDefiningType()) + .append(":").append(identifiers.get(0)); checkedTypeToDMLOperationViaESAPI.put(sb.toString(), dmlOperation); } @@ -540,7 +506,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule { } private void checkForAccessibility(final ASTSoqlExpression node, Object data) { - final boolean isCount = node.getNode().getCanonicalQuery().startsWith("SELECT COUNT()"); + final boolean isCount = node.getCanonicalQuery().startsWith("SELECT COUNT()"); final Set typesFromSOQL = getTypesFromSOQLQuery(node); final Set prevCalls = getPreviousMethodCalls(node); @@ -567,9 +533,9 @@ public class ApexCRUDViolationRule extends AbstractApexRule { final ASTVariableDeclaration variableDecl = node.getFirstParentOfType(ASTVariableDeclaration.class); if (variableDecl != null) { - String type = variableDecl.getNode().getLocalInfo().getType().getApexName(); + String type = variableDecl.getType(); type = getSimpleType(type); - StringBuilder typeCheck = new StringBuilder().append(variableDecl.getNode().getDefiningType().getApexName()) + StringBuilder typeCheck = new StringBuilder().append(variableDecl.getDefiningType()) .append(":").append(type); if (!isGetter) { @@ -622,25 +588,25 @@ public class ApexCRUDViolationRule extends AbstractApexRule { private Set getTypesFromSOQLQuery(final ASTSoqlExpression node) { final Set retVal = new HashSet<>(); - final String canonQuery = node.getNode().getCanonicalQuery(); + final String canonQuery = node.getCanonicalQuery(); Matcher m = SELECT_FROM_PATTERN.matcher(canonQuery); while (m.find()) { - retVal.add(new StringBuffer().append(node.getNode().getDefiningType().getApexName()).append(":") + retVal.add(new StringBuffer().append(node.getDefiningType()).append(":") .append(m.group(1)).toString()); } return retVal; } private String getReturnType(final ASTMethod method) { - return new StringBuilder().append(method.getNode().getDefiningType().getApexName()).append(":") - .append(method.getNode().getMethodInfo().getEmitSignature().getReturnType().getApexName()).toString(); + return new StringBuilder().append(method.getDefiningType()).append(":") + .append(method.getReturnType()).toString(); } private boolean isMethodAGetter(final ASTMethod method) { - final boolean startsWithGet = method.getNode().getMethodInfo().getCanonicalName().startsWith("get"); + final boolean startsWithGet = method.getCanonicalName().startsWith("get"); final boolean voidOrString = VOID_OR_STRING_PATTERN - .matcher(method.getNode().getMethodInfo().getEmitSignature().getReturnType().getApexName()).matches(); + .matcher(method.getReturnType()).matches(); final boolean noParams = method.findChildrenOfType(ASTParameter.class).isEmpty(); return startsWithGet && noParams && !voidOrString; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java index cb83f24cae..b51c0c2f68 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; import java.util.Arrays; import java.util.List; -import java.util.Locale; import net.sourceforge.pmd.lang.apex.ast.ASTDmlDeleteStatement; import net.sourceforge.pmd.lang.apex.ast.ASTDmlInsertStatement; @@ -17,7 +16,6 @@ import net.sourceforge.pmd.lang.apex.ast.ASTDmlUpsertStatement; import net.sourceforge.pmd.lang.apex.ast.ASTField; import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; -import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; import net.sourceforge.pmd.lang.apex.ast.ASTNewKeyValueObjectExpression; import net.sourceforge.pmd.lang.apex.ast.ASTParameter; import net.sourceforge.pmd.lang.apex.ast.ASTReferenceExpression; @@ -28,13 +26,7 @@ import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration; import net.sourceforge.pmd.lang.apex.ast.ASTVariableExpression; import net.sourceforge.pmd.lang.apex.ast.ApexNode; -import apex.jorje.data.Identifier; -import apex.jorje.data.ast.TypeRef; -import apex.jorje.semantic.ast.expression.MethodCallExpression; -import apex.jorje.semantic.ast.expression.VariableExpression; -import apex.jorje.semantic.ast.member.Field; import apex.jorje.semantic.ast.member.Parameter; -import apex.jorje.semantic.ast.statement.VariableDeclaration; /** * Helper methods @@ -52,15 +44,7 @@ public final class Helper { } static boolean isTestMethodOrClass(final ApexNode node) { - final List modifierNode = node.findChildrenOfType(ASTModifierNode.class); - for (final ASTModifierNode m : modifierNode) { - if (m.isTest()) { - return true; - } - } - - final String className = node.getNode().getDefiningType().getApexName(); - return className.endsWith("Test"); + return net.sourceforge.pmd.lang.apex.rule.internal.Helper.isTestMethodOrClass(node); } static boolean foundAnySOQLorSOSL(final ApexNode node) { @@ -95,16 +79,12 @@ public final class Helper { final String methodName) { final ASTReferenceExpression reference = methodNode.getFirstChildOfType(ASTReferenceExpression.class); - return reference != null && reference.getNode().getNames().size() == 1 - && reference.getNode().getNames().get(0).getValue().equalsIgnoreCase(className) + return reference != null && reference.getNames().size() == 1 + && reference.getNames().get(0).equalsIgnoreCase(className) && (methodName.equals(ANY_METHOD) || isMethodName(methodNode, methodName)); } static boolean isMethodName(final ASTMethodCallExpression m, final String methodName) { - return isMethodName(m.getNode(), methodName); - } - - static boolean isMethodName(final MethodCallExpression m, final String methodName) { return m.getMethodName().equalsIgnoreCase(methodName); } @@ -131,100 +111,44 @@ public final class Helper { } static String getFQVariableName(final ASTVariableExpression variable) { - final ASTReferenceExpression ref = variable.getFirstChildOfType(ASTReferenceExpression.class); - String objectName = ""; - if (ref != null) { - if (ref.getNode().getNames().size() == 1) { - objectName = ref.getNode().getNames().get(0).getValue() + "."; - } - } - - VariableExpression n = variable.getNode(); - StringBuilder sb = new StringBuilder().append(n.getDefiningType().getApexName()).append(":").append(objectName) - .append(n.getIdentifier().getValue()); - return sb.toString(); + return net.sourceforge.pmd.lang.apex.rule.internal.Helper.getFQVariableName(variable); } static String getFQVariableName(final ASTVariableDeclaration variable) { - VariableDeclaration n = variable.getNode(); - StringBuilder sb = new StringBuilder().append(n.getDefiningType().getApexName()).append(":") - .append(n.getLocalInfo().getName()); - return sb.toString(); + return net.sourceforge.pmd.lang.apex.rule.internal.Helper.getFQVariableName(variable); } static String getFQVariableName(final ASTField variable) { - Field n = variable.getNode(); - StringBuilder sb = new StringBuilder() - .append(n.getDefiningType().getApexName()).append(":") - .append(n.getFieldInfo().getName()); - return sb.toString(); + return net.sourceforge.pmd.lang.apex.rule.internal.Helper.getFQVariableName(variable); } static String getVariableType(final ASTField variable) { - Field n = variable.getNode(); - StringBuilder sb = new StringBuilder().append(n.getDefiningType().getApexName()).append(":") - .append(n.getFieldInfo().getName()); + StringBuilder sb = new StringBuilder().append(variable.getDefiningType()).append(":") + .append(variable.getName()); return sb.toString(); } static String getFQVariableName(final ASTFieldDeclaration variable) { - StringBuilder sb = new StringBuilder() - .append(variable.getNode().getDefiningType().getApexName()).append(":") - .append(variable.getImage()); - return sb.toString(); + return net.sourceforge.pmd.lang.apex.rule.internal.Helper.getFQVariableName(variable); } static String getFQVariableName(final ASTNewKeyValueObjectExpression variable) { - StringBuilder sb = new StringBuilder() - .append(variable.getNode().getDefiningType().getApexName()).append(":") - .append(variable.getType()); - return sb.toString(); + return net.sourceforge.pmd.lang.apex.rule.internal.Helper.getFQVariableName(variable); } static boolean isSystemLevelClass(ASTUserClass node) { - List interfaces = node.getNode().getDefiningType().getCodeUnitDetails().getInterfaceTypeRefs(); - - for (TypeRef intObject : interfaces) { - if (isWhitelisted(intObject.getNames())) { - return true; - } - } - - return false; - } - - private static boolean isWhitelisted(List ids) { - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < ids.size(); i++) { - sb.append(ids.get(i).getValue()); - - if (i != ids.size() - 1) { - sb.append("."); - } - } - - switch (sb.toString().toLowerCase(Locale.ROOT)) { - case "queueable": - case "database.batchable": - case "installhandler": - return true; - default: - break; - } - return false; + return net.sourceforge.pmd.lang.apex.rule.internal.Helper.isSystemLevelClass(node); } + @Deprecated public static String getFQVariableName(Parameter p) { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append(p.getDefiningType()).append(":").append(p.getName().getValue()); return sb.toString(); } static String getFQVariableName(ASTParameter p) { - StringBuffer sb = new StringBuffer(); - sb.append(p.getNode().getDefiningType()).append(":").append(p.getImage()); - return sb.toString(); + return net.sourceforge.pmd.lang.apex.rule.internal.Helper.getFQVariableName(p); } } diff --git a/pmd-apex/src/main/resources/category/apex/codestyle.xml b/pmd-apex/src/main/resources/category/apex/codestyle.xml index f04a7580f8..0c0ea51a4a 100644 --- a/pmd-apex/src/main/resources/category/apex/codestyle.xml +++ b/pmd-apex/src/main/resources/category/apex/codestyle.xml @@ -45,12 +45,13 @@ from the rest. 3 + 0] +//IfBlockStatement/BlockStatement[@CurlyBrace= false()][count(child::*) > 0] | -//IfElseBlockStatement/BlockStatement[@CurlyBrace='false'][count(child::*) > 0] +//IfElseBlockStatement/BlockStatement[@CurlyBrace= false()][count(child::*) > 0] ]]> @@ -82,10 +83,11 @@ controlled from the rest. 3 + @@ -163,12 +165,13 @@ from the rest. 3 + @@ -272,6 +275,7 @@ can lead to quite messy code. This rule looks for several declarations on the sa 1 + 3 + diff --git a/pmd-apex/src/main/resources/category/apex/errorprone.xml b/pmd-apex/src/main/resources/category/apex/errorprone.xml index fb4b39c19b..ecea64c472 100644 --- a/pmd-apex/src/main/resources/category/apex/errorprone.xml +++ b/pmd-apex/src/main/resources/category/apex/errorprone.xml @@ -59,6 +59,7 @@ Avoid directly accessing Trigger.old and Trigger.new as it can lead to a bug. Tr 3 + 3 + 3 + 3 + @@ -221,6 +225,7 @@ Avoid empty try or finally blocks - what's the point? 3 + 3 + methods = node.findChildrenOfType(ASTMethod.class); Assert.assertEquals("Foo", methods.get(0).getImage()); // constructor + Assert.assertEquals("", methods.get(0).getCanonicalName()); Assert.assertEquals("bar", methods.get(1).getImage()); // normal method } } 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 0cc7c50297..9e0303a41d 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 @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.apex.ast; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -127,8 +126,6 @@ public class ApexParserTest extends ApexParserTestBase { ApexNode comment = root.getChild(0); assertThat(comment, instanceOf(ASTFormalComment.class)); - assertNotEquals(comment.getNode(), null); - assertThat(comment.getNode(), instanceOf(ASTFormalComment.AstComment.class)); assertPosition(comment, 1, 9, 1, 31); assertEquals("/** Comment on Class */", ((ASTFormalComment) comment).getToken()); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java index 87c5acb924..a79aee80d4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java @@ -99,7 +99,7 @@ public abstract class AbstractTokenizer implements Tokenizer { private int parseString(StringBuilder token, int loc, char stringDelimiter) { boolean escaped = false; boolean done = false; - char tok = ' '; // this will be replaced. + char tok; while (loc < currentLine.length() && !done) { tok = currentLine.charAt(loc); if (escaped && tok == stringDelimiter) { // Found an escaped string @@ -107,30 +107,24 @@ public abstract class AbstractTokenizer implements Tokenizer { } else if (tok == stringDelimiter && token.length() > 0) { // We are done, we found the end of the string... done = true; - } else if (tok == '\\') { // Found an escaped char - escaped = true; - } else { // Adding char... - escaped = false; + } else { + // Found an escaped char? + escaped = tok == '\\'; } // Adding char to String:" + token.toString()); token.append(tok); loc++; } // Handling multiple lines string - if (!done && // ... we didn't find the end of the string - loc >= currentLine.length() && // ... we have reach the end of - // the line ( the String is - // incomplete, for the moment at - // least) - spanMultipleLinesString && // ... the language allow multiple - // line span Strings - lineNumber < code.size() - 1 // ... there is still more lines to - // parse + if (!done // ... we didn't find the end of the string (but the end of the line) + && spanMultipleLinesString // ... the language allow multiple line span Strings + && lineNumber < code.size() - 1 // ... there is still more lines to parse ) { // removes last character, if it is the line continuation (e.g. // backslash) character - if (spanMultipleLinesLineContinuationCharacter != null && token.length() > 0 - && token.charAt(token.length() - 1) == spanMultipleLinesLineContinuationCharacter.charValue()) { + if (spanMultipleLinesLineContinuationCharacter != null + && token.length() > 0 + && token.charAt(token.length() - 1) == spanMultipleLinesLineContinuationCharacter) { token.deleteCharAt(token.length() - 1); } // parsing new line diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/XPathHandler.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/XPathHandler.java index 2895550346..ebdf801d80 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/XPathHandler.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/XPathHandler.java @@ -38,7 +38,8 @@ public interface XPathHandler { * Get a Jaxen Navigator for this Language. May return null if * there is no Jaxen Navigation for this language. * - * @deprecated Support for Jaxen will be removed come 7.0.0 + * @deprecated Support for Jaxen will be removed come 7.0.0. This isn't used + * anymore */ @Deprecated Navigator getNavigator(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java index c14ede1d12..2f8d3eb78c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/AbstractNode.java @@ -25,6 +25,8 @@ import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.xpath.Attribute; import net.sourceforge.pmd.lang.ast.xpath.AttributeAxisIterator; import net.sourceforge.pmd.lang.ast.xpath.DocumentNavigator; +import net.sourceforge.pmd.lang.ast.xpath.internal.ContextualizedNavigator; +import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttrLogger; import net.sourceforge.pmd.lang.dfa.DataFlowNode; import net.sourceforge.pmd.util.DataMap; import net.sourceforge.pmd.util.DataMap.DataKey; @@ -513,7 +515,8 @@ public abstract class AbstractNode implements Node { @Override @SuppressWarnings("unchecked") public List findChildNodesWithXPath(final String xpathString) throws JaxenException { - return new BaseXPath(xpathString, new DocumentNavigator()).selectNodes(this); + return new BaseXPath(xpathString, new ContextualizedNavigator(DeprecatedAttrLogger.createAdHocLogger())) + .selectNodes(this); } @Override diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/Attribute.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/Attribute.java index cee0734a9c..7f4573ce97 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/Attribute.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/Attribute.java @@ -9,12 +9,9 @@ import java.lang.reflect.Method; import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.logging.Level; -import java.util.logging.Logger; import net.sourceforge.pmd.annotation.Experimental; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttribute; @@ -29,11 +26,6 @@ import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttribute; * @author daniels */ public class Attribute { - - - private static final Logger LOG = Logger.getLogger(Attribute.class.getName()); - static final ConcurrentMap DETECTED_DEPRECATED_ATTRIBUTES = new ConcurrentHashMap<>(); - private static final Object[] EMPTY_OBJ_ARRAY = new Object[0]; private final Node parent; @@ -73,9 +65,22 @@ public class Attribute { return method == null ? String.class : method.getReturnType(); } - private boolean isAttributeDeprecated() { - return method != null && (method.isAnnotationPresent(Deprecated.class) - || method.isAnnotationPresent(DeprecatedAttribute.class)); + /** + * Returns null for "not deprecated", empty string for "deprecated without replacement", + * otherwise name of replacement attribute. + */ + @InternalApi + public String replacementIfDeprecated() { + if (method == null) { + return null; + } else { + DeprecatedAttribute annot = method.getAnnotation(DeprecatedAttribute.class); + return annot != null + ? annot.replaceWith() + : method.isAnnotationPresent(Deprecated.class) + ? DeprecatedAttribute.NO_REPLACEMENT + : null; + } } public Object getValue() { @@ -83,12 +88,6 @@ public class Attribute { return value.get(0); } - if (LOG.isLoggable(Level.WARNING) && isAttributeDeprecated() - && DETECTED_DEPRECATED_ATTRIBUTES.putIfAbsent(getLoggableAttributeName(), Boolean.TRUE) == null) { - // this message needs to be kept in sync with PMDCoverageTest / BinaryDistributionIT - LOG.warning("Use of deprecated attribute '" + getLoggableAttributeName() + "' in XPath query"); - } - // this lazy loading reduces calls to Method.invoke() by about 90% try { value = Collections.singletonList(method.invoke(parent, EMPTY_OBJ_ARRAY)); @@ -129,11 +128,6 @@ public class Attribute { return Objects.hash(parent, name); } - - private String getLoggableAttributeName() { - return parent.getXPathNodeName() + "/@" + name; - } - @Override public String toString() { return name + ':' + getValue() + ':' + parent.getXPathNodeName(); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/ContextualizedNavigator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/ContextualizedNavigator.java new file mode 100644 index 0000000000..358d7d7ce7 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/ContextualizedNavigator.java @@ -0,0 +1,27 @@ +/* + * 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.xpath.Attribute; +import net.sourceforge.pmd.lang.ast.xpath.DocumentNavigator; + +/** + * Navigator that records attribute usages. + */ +public class ContextualizedNavigator extends DocumentNavigator { + + private final DeprecatedAttrLogger ctx; + + public ContextualizedNavigator(DeprecatedAttrLogger ctx) { + this.ctx = ctx; + } + + @Override + public String getAttributeStringValue(Object arg0) { + Attribute attr = (Attribute) arg0; + ctx.recordUsageOf(attr); + return attr.getStringValue(); + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/DeprecatedAttrLogger.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/DeprecatedAttrLogger.java new file mode 100644 index 0000000000..e6c2358a06 --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/DeprecatedAttrLogger.java @@ -0,0 +1,117 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.ast.xpath.internal; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +import net.sourceforge.pmd.lang.ast.xpath.Attribute; +import net.sourceforge.pmd.lang.rule.XPathRule; + +/** + * Records usages of deprecated attributes in XPath rules. This needs + * to be threadsafe, XPath rules have one each (and share it). + */ +public abstract class DeprecatedAttrLogger { + + private static final Logger LOG = Logger.getLogger(Attribute.class.getName()); + + + public abstract void recordUsageOf(Attribute attribute); + + /** + * Create a new context for the given rule, returns a noop implementation + * if the warnings would be ignored anyway. + */ + public static DeprecatedAttrLogger create(XPathRule rule) { + if (LOG.isLoggable(Level.WARNING)) { + return new AttrLoggerImpl(rule); + } else { + return noop(); + } + } + + public static DeprecatedAttrLogger createAdHocLogger() { + if (LOG.isLoggable(Level.WARNING)) { + return new AdhocLoggerImpl(); + } else { + return noop(); + } + } + + public static Noop noop() { + return Noop.INSTANCE; + } + + private static String getLoggableAttributeName(Attribute attr) { + return attr.getParent().getXPathNodeName() + "/@" + attr.getName(); + } + + private static class Noop extends DeprecatedAttrLogger { + + static final Noop INSTANCE = new Noop(); + + @Override + public void recordUsageOf(Attribute attribute) { + // do nothing + } + } + + private static class AttrLoggerImpl extends DeprecatedAttrLogger { + + private final ConcurrentMap deprecated = new ConcurrentHashMap<>(); + private final XPathRule rule; + + private AttrLoggerImpl(XPathRule rule) { + this.rule = rule; + } + + @Override + public void recordUsageOf(Attribute attribute) { + String replacement = attribute.replacementIfDeprecated(); + if (replacement != null) { + String name = getLoggableAttributeName(attribute); + Boolean b = deprecated.putIfAbsent(name, Boolean.TRUE); + if (b == null) { + // this message needs to be kept in sync with PMDCoverageTest / BinaryDistributionIT + String msg = "Use of deprecated attribute '" + name + "' by XPath rule " + ruleToString(); + if (!replacement.isEmpty()) { + msg += ", please use " + replacement + " instead"; + } + LOG.warning(msg); + } + } + } + + public String ruleToString() { + // we can't compute that beforehand because the name is set + // outside of the rule constructor + String name = "'" + rule.getName() + "'"; + if (rule.getRuleSetName() != null) { + name += " (in ruleset '" + rule.getRuleSetName() + "')"; + } + return name; + } + } + + private static class AdhocLoggerImpl extends DeprecatedAttrLogger { + @Override + public void recordUsageOf(Attribute attribute) { + String replacement = attribute.replacementIfDeprecated(); + if (replacement != null) { + String name = getLoggableAttributeName(attribute); + // this message needs to be kept in sync with PMDCoverageTest / BinaryDistributionIT + String msg = "Use of deprecated attribute '" + name + "' in a findChildNodesWithXPath navigation"; + if (!replacement.isEmpty()) { + msg += ", please use " + replacement + " instead"; + } + // log with execption stack trace to help figure out where exactly the xpath is used. + LOG.log(Level.WARNING, msg, new RuntimeException(msg)); + } + } + } +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/DeprecatedAttribute.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/DeprecatedAttribute.java index 75e80d4f5f..430cf5dd73 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/DeprecatedAttribute.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/DeprecatedAttribute.java @@ -22,4 +22,13 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface DeprecatedAttribute { + + String NO_REPLACEMENT = ""; + + + /** + * The simple name of the attribute to use for replacement (with '@' prefix). + * If empty, then the attribute is deprecated for removal. + */ + String replaceWith() default NO_REPLACEMENT; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AbstractNodeInfo.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AbstractNodeInfo.java index 1e7c8e0825..822bb9d797 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AbstractNodeInfo.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AbstractNodeInfo.java @@ -260,11 +260,11 @@ public class AbstractNodeInfo implements VirtualNode, SiblingCountingNode { */ @Override public AxisIterator iterateAxis(byte axisNumber, NodeTest nodeTest) { - AxisIterator axisIterator = iterateAxis(axisNumber); - if (nodeTest != null) { - axisIterator = new AxisFilter(axisIterator, nodeTest); - } - return axisIterator; + return filter(iterateAxis(axisNumber), nodeTest); + } + + protected static AxisIterator filter(AxisIterator axisIterator, NodeTest nodeTest) { + return nodeTest != null ? new AxisFilter(axisIterator, nodeTest) : axisIterator; } /** diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java index 9a0e23baf1..d22adb33ab 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeAxisIterator.java @@ -42,7 +42,7 @@ public class AttributeAxisIterator extends Navigator.BaseEnumeration { public void advance() { if (this.iterator.hasNext()) { Attribute attribute = this.iterator.next(); - super.current = new AttributeNode(attribute, super.position()); + super.current = new AttributeNode(startNodeInfo, attribute, super.position()); } else { super.current = null; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeNode.java index 528b4fc578..7a919967ef 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/AttributeNode.java @@ -8,6 +8,7 @@ import java.util.List; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.xpath.Attribute; +import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttrLogger; import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery; import net.sf.saxon.om.NodeInfo; @@ -23,7 +24,8 @@ import net.sf.saxon.value.Value; */ @Deprecated @InternalApi -public class AttributeNode extends AbstractNodeInfo { +public class AttributeNode extends BaseNodeInfo { + protected final Attribute attribute; protected final int id; protected Value value; @@ -32,30 +34,28 @@ public class AttributeNode extends AbstractNodeInfo { /** * Creates a new AttributeNode from a PMD Attribute. * - * @param id The index within the attribute order + * @param parent Parent elemtn + * @param id The index within the attribute order */ - public AttributeNode(Attribute attribute, int id) { + public AttributeNode(ElementNode parent, Attribute attribute, int id) { + super(Type.ATTRIBUTE, parent.getNamePool(), attribute.getName(), parent); this.attribute = attribute; this.id = id; } - @Override - public int getNodeKind() { - return Type.ATTRIBUTE; - } - @Override public String getLocalPart() { return attribute.getName(); } - @Override - public String getURI() { - return ""; + private DeprecatedAttrLogger getAttrCtx() { + return parent == null ? DeprecatedAttrLogger.noop() + : parent.document.getAttrCtx(); } @Override public Value atomize() { + getAttrCtx().recordUsageOf(attribute); if (value == null) { Object data = attribute.getValue(); if (data instanceof List) { @@ -79,6 +79,7 @@ public class AttributeNode extends AbstractNodeInfo { @Override public int compareOrder(NodeInfo other) { + return Integer.signum(this.id - ((AttributeNode) other).id); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/BaseNodeInfo.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/BaseNodeInfo.java new file mode 100644 index 0000000000..ea6e4477ac --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/BaseNodeInfo.java @@ -0,0 +1,76 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.ast.xpath.saxon; + + +import net.sf.saxon.om.FingerprintedNode; +import net.sf.saxon.om.NamePool; +import net.sf.saxon.om.NodeInfo; +import net.sf.saxon.om.SiblingCountingNode; +import net.sf.saxon.om.VirtualNode; + +abstract class BaseNodeInfo extends AbstractNodeInfo implements VirtualNode, SiblingCountingNode, FingerprintedNode { + + // It's important that all our NodeInfo implementations share the + // same getNodeKind implementation, otherwise NameTest spends a lot + // of time in virtual dispatch + private final int nodeKind; + private final NamePool namePool; + private final int fingerprint; + + protected final ElementNode parent; + + BaseNodeInfo(int nodeKind, NamePool namePool, String localName, ElementNode parent) { + this.nodeKind = nodeKind; + this.namePool = namePool; + this.fingerprint = namePool.allocate("", "", localName) & NamePool.FP_MASK; + this.parent = parent; + } + + @Override + public final String getURI() { + return ""; + } + + @Override + public final String getBaseURI() { + return ""; + } + + @Override + public String getPrefix() { + return ""; + } + + @Override + public final NodeInfo getParent() { + return parent; + } + + @Override + public int getNameCode() { + // note: the nameCode is only equal to the fingerprint because + // this implementation does not use namespace prefixes + // if we change that (eg for embedded language support) then + // we'll need to worry about this. See NamePool.FP_MASK + return fingerprint; + } + + @Override + public final int getFingerprint() { + return fingerprint; + } + + @Override + public final NamePool getNamePool() { + return namePool; + } + + @Override + public final int getNodeKind() { + return nodeKind; + } + +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java index f91718c816..d91f1828a6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java @@ -10,10 +10,13 @@ import java.util.Map; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttrLogger; +import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery; import net.sf.saxon.om.Axis; import net.sf.saxon.om.AxisIterator; import net.sf.saxon.om.DocumentInfo; +import net.sf.saxon.om.NamePool; import net.sf.saxon.om.Navigator; import net.sf.saxon.om.NodeInfo; import net.sf.saxon.om.SingleNodeIterator; @@ -24,7 +27,7 @@ import net.sf.saxon.type.Type; */ @Deprecated @InternalApi -public class DocumentNode extends AbstractNodeInfo implements DocumentInfo { +public class DocumentNode extends BaseNodeInfo implements DocumentInfo { /** * The root ElementNode of the DocumentNode. @@ -36,17 +39,25 @@ public class DocumentNode extends AbstractNodeInfo implements DocumentInfo { */ public final Map nodeToElementNode = new HashMap<>(); + private DeprecatedAttrLogger attrCtx; + /** * Construct a DocumentNode, with the given AST Node serving as the root * ElementNode. * - * @param node - * The root AST Node. + * @param node The root AST Node. + * @param namePool Pool to share names * * @see ElementNode */ + public DocumentNode(Node node, NamePool namePool) { + super(Type.DOCUMENT, namePool, "", null); + this.rootNode = new ElementNode(this, new IdGenerator(), null, node, -1, namePool); + } + + @Deprecated public DocumentNode(Node node) { - this.rootNode = new ElementNode(this, new IdGenerator(), null, node, -1); + this(node, SaxonXPathRuleQuery.getNamePool()); } @Override @@ -64,11 +75,6 @@ public class DocumentNode extends AbstractNodeInfo implements DocumentInfo { throw createUnsupportedOperationException("DocumentInfo.selectID(String)"); } - @Override - public int getNodeKind() { - return Type.DOCUMENT; - } - @Override public DocumentInfo getDocumentRoot() { return this; @@ -92,4 +98,12 @@ public class DocumentNode extends AbstractNodeInfo implements DocumentInfo { return super.iterateAxis(axisNumber); } } + + public DeprecatedAttrLogger getAttrCtx() { + return attrCtx == null ? DeprecatedAttrLogger.noop() : attrCtx; + } + + public void setAttrCtx(DeprecatedAttrLogger attrCtx) { + this.attrCtx = attrCtx; + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java index 4663e7f1bf..6db157eac4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java @@ -4,25 +4,41 @@ package net.sourceforge.pmd.lang.ast.xpath.saxon; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.Attribute; +import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery; import net.sf.saxon.om.Axis; import net.sf.saxon.om.AxisIterator; import net.sf.saxon.om.DocumentInfo; import net.sf.saxon.om.EmptyIterator; +import net.sf.saxon.om.NamePool; import net.sf.saxon.om.Navigator; +import net.sf.saxon.om.Navigator.BaseEnumeration; import net.sf.saxon.om.NodeArrayIterator; import net.sf.saxon.om.NodeInfo; +import net.sf.saxon.om.SequenceIterator; import net.sf.saxon.om.SingleNodeIterator; +import net.sf.saxon.om.SingletonIterator; +import net.sf.saxon.pattern.NameTest; +import net.sf.saxon.pattern.NodeTest; import net.sf.saxon.type.Type; +import net.sf.saxon.value.AtomicValue; +import net.sf.saxon.value.StringValue; +import net.sf.saxon.value.UntypedAtomicValue; +import net.sf.saxon.value.Value; /** * A Saxon OM Element type node for an AST Node. */ @Deprecated @InternalApi -public class ElementNode extends AbstractNodeInfo { +public class ElementNode extends BaseNodeInfo { protected final DocumentNode document; protected final ElementNode parent; @@ -31,17 +47,31 @@ public class ElementNode extends AbstractNodeInfo { protected final int siblingPosition; protected final NodeInfo[] children; - public ElementNode(DocumentNode document, IdGenerator idGenerator, ElementNode parent, Node node, - int siblingPosition) { + private Map attributes; + + @Deprecated + public ElementNode(DocumentNode document, IdGenerator idGenerator, ElementNode parent, Node node, int siblingPosition) { + this(document, idGenerator, parent, node, siblingPosition, SaxonXPathRuleQuery.getNamePool()); + } + + public ElementNode(DocumentNode document, + IdGenerator idGenerator, + ElementNode parent, + Node node, + int siblingPosition, + NamePool namePool) { + super(Type.ELEMENT, namePool, node.getXPathNodeName(), parent); + this.document = document; this.parent = parent; this.node = node; this.id = idGenerator.getNextId(); this.siblingPosition = siblingPosition; + if (node.getNumChildren() > 0) { this.children = new NodeInfo[node.getNumChildren()]; for (int i = 0; i < children.length; i++) { - children[i] = new ElementNode(document, idGenerator, this, node.getChild(i), i); + children[i] = new ElementNode(document, idGenerator, this, node.getChild(i), i, namePool); } } else { this.children = null; @@ -49,6 +79,20 @@ public class ElementNode extends AbstractNodeInfo { document.nodeToElementNode.put(node, this); } + private Map getAttributes() { + if (attributes == null) { + attributes = new HashMap<>(); + Iterator iter = node.getXPathAttributesIterator(); + int idx = 0; + while (iter.hasNext()) { + Attribute next = iter.next(); + AttributeNode attrNode = new AttributeNode(this, next, idx++); + attributes.put(attrNode.getFingerprint(), attrNode); + } + } + return attributes; + } + @Override public Object getUnderlyingNode() { return node; @@ -74,11 +118,6 @@ public class ElementNode extends AbstractNodeInfo { return children != null; } - @Override - public int getNodeKind() { - return Type.ELEMENT; - } - @Override public DocumentInfo getDocumentRoot() { return document; @@ -89,14 +128,26 @@ public class ElementNode extends AbstractNodeInfo { return node.getXPathNodeName(); } + @Override - public String getURI() { - return ""; + public SequenceIterator getTypedValue() { + return SingletonIterator.makeIterator((AtomicValue) atomize()); } @Override - public NodeInfo getParent() { - return parent; + public Value atomize() { + switch (getNodeKind()) { + case Type.COMMENT: + case Type.PROCESSING_INSTRUCTION: + return new StringValue(getStringValueCS()); + default: + return new UntypedAtomicValue(getStringValueCS()); + } + } + + @Override + public CharSequence getStringValueCS() { + return ""; } @Override @@ -122,16 +173,40 @@ public class ElementNode extends AbstractNodeInfo { return result; } + + @Override + public String getDisplayName() { + return getLocalPart(); + } + + + @Override + public AxisIterator iterateAxis(byte axisNumber, NodeTest nodeTest) { + if (axisNumber == Axis.ATTRIBUTE) { + if (nodeTest instanceof NameTest) { + if ((nodeTest.getNodeKindMask() & (1 << Type.ATTRIBUTE)) == 0) { + return EmptyIterator.getInstance(); + } else { + int fp = nodeTest.getFingerprint(); + if (fp != -1) { + return SingleNodeIterator.makeIterator(getAttributes().get(fp)); + } + } + } + } + return super.iterateAxis(axisNumber, nodeTest); + } + @SuppressWarnings("PMD.MissingBreakInSwitch") @Override - public AxisIterator iterateAxis(byte axisNumber) { + public AxisIterator iterateAxis(final byte axisNumber) { switch (axisNumber) { case Axis.ANCESTOR: return new Navigator.AncestorEnumeration(this, false); case Axis.ANCESTOR_OR_SELF: return new Navigator.AncestorEnumeration(this, true); case Axis.ATTRIBUTE: - return new AttributeAxisIterator(this); + return new AttributeEnumeration(); case Axis.CHILD: if (children == null) { return EmptyIterator.getInstance(); @@ -171,4 +246,22 @@ public class ElementNode extends AbstractNodeInfo { } } + private class AttributeEnumeration extends BaseEnumeration { + + private final Iterator iter = getAttributes().values().iterator(); + + @Override + public void advance() { + if (iter.hasNext()) { + current = iter.next(); + } else { + current = null; + } + } + + @Override + public SequenceIterator getAnother() { + return new AttributeEnumeration(); + } + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java index d2c438a6df..0f91715bcc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/XPathRule.java @@ -16,8 +16,10 @@ import java.util.Objects; import org.apache.commons.lang3.StringUtils; +import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttrLogger; import net.sourceforge.pmd.lang.rule.xpath.JaxenXPathRuleQuery; import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery; import net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery; @@ -68,6 +70,9 @@ public class XPathRule extends AbstractRule { */ private XPathRuleQuery xpathRuleQuery; + // this is shared with rules forked by deepCopy, used by the XPathRuleQuery + private DeprecatedAttrLogger attrLogger = DeprecatedAttrLogger.create(this); + /** * Creates a new XPathRule without the corresponding XPath query. * @@ -106,6 +111,14 @@ public class XPathRule extends AbstractRule { setVersion(version.getXmlName()); } + + @Override + public Rule deepCopy() { + XPathRule rule = (XPathRule) super.deepCopy(); + rule.attrLogger = this.attrLogger; + return rule; + } + /** * Returns the version for this rule. Returns null if this is not * set or invalid. @@ -179,9 +192,9 @@ public class XPathRule extends AbstractRule { } if (version == XPathVersion.XPATH_1_0) { - xpathRuleQuery = new JaxenXPathRuleQuery(); + xpathRuleQuery = new JaxenXPathRuleQuery(attrLogger); } else { - xpathRuleQuery = new SaxonXPathRuleQuery(); + xpathRuleQuery = new SaxonXPathRuleQuery(attrLogger); } xpathRuleQuery.setXPath(xpath); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQuery.java index 1e331a7b28..4ef992f19d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQuery.java @@ -33,6 +33,8 @@ import org.jaxen.saxpath.Axis; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.internal.ContextualizedNavigator; +import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttrLogger; import net.sourceforge.pmd.properties.PropertyDescriptor; /** @@ -46,15 +48,21 @@ public class JaxenXPathRuleQuery extends AbstractXPathRuleQuery { private static final Logger LOG = Logger.getLogger(JaxenXPathRuleQuery.class.getName()); - private enum InitializationStatus { - NONE, PARTIAL, FULL - } + static final String AST_ROOT = "_AST_ROOT_"; private InitializationStatus initializationStatus = InitializationStatus.NONE; // Mapping from Node name to applicable XPath queries Map> nodeNameToXPaths; - static final String AST_ROOT = "_AST_ROOT_"; + private final DeprecatedAttrLogger attrCtx; + + public JaxenXPathRuleQuery() { + this(DeprecatedAttrLogger.noop()); + } + + public JaxenXPathRuleQuery(DeprecatedAttrLogger attrCtx) { + this.attrCtx = attrCtx; + } @Override public boolean isSupportedVersion(String version) { @@ -66,7 +74,7 @@ public class JaxenXPathRuleQuery extends AbstractXPathRuleQuery { final List results = new ArrayList<>(); try { - initializeExpressionIfStatusIsNoneOrPartial(data.getLanguageVersion().getLanguageVersionHandler().getXPathHandler().getNavigator()); + initializeExpressionIfStatusIsNoneOrPartial(new ContextualizedNavigator(attrCtx)); List xPaths = getXPathsForNodeOrDefault(node.getXPathNodeName()); for (XPath xpath : xPaths) { @@ -266,4 +274,9 @@ public class JaxenXPathRuleQuery extends AbstractXPathRuleQuery { } return xpath; } + + + private enum InitializationStatus { + NONE, PARTIAL, FULL + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java index 231bd0a917..4bcb8f7423 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.rule.xpath; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -18,14 +17,19 @@ import java.util.regex.Pattern; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttrLogger; import net.sourceforge.pmd.lang.ast.xpath.saxon.DocumentNode; import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; import net.sourceforge.pmd.lang.rule.xpath.internal.RuleChainAnalyzer; import net.sourceforge.pmd.lang.xpath.Initializer; import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.util.DataMap; +import net.sourceforge.pmd.util.DataMap.DataKey; +import net.sourceforge.pmd.util.DataMap.SimpleDataKey; import net.sf.saxon.expr.Expression; import net.sf.saxon.om.Item; +import net.sf.saxon.om.NamePool; import net.sf.saxon.om.NamespaceConstant; import net.sf.saxon.om.SequenceIterator; import net.sf.saxon.om.ValueRepresentation; @@ -57,6 +61,7 @@ import net.sf.saxon.value.Value; @Deprecated @InternalApi public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { + /** * Special nodeName that references the root expression. */ @@ -64,15 +69,10 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { private static final Logger LOG = Logger.getLogger(SaxonXPathRuleQuery.class.getName()); - private static final int MAX_CACHE_SIZE = 20; - private static final Map CACHE = new LinkedHashMap(MAX_CACHE_SIZE) { - private static final long serialVersionUID = -7653916493967142443L; + private static final NamePool NAME_POOL = new NamePool(); - @Override - protected boolean removeEldestEntry(final Map.Entry eldest) { - return size() > MAX_CACHE_SIZE; - } - }; + /** Cache key for the wrapped tree for saxon. */ + private static final SimpleDataKey SAXON_TREE_CACHE_KEY = DataMap.simpleDataKey("saxon.tree"); /** * Contains for each nodeName a sub expression, used for implementing rule chain. @@ -91,21 +91,33 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { */ private List xpathVariables; + private final DeprecatedAttrLogger attrCtx; + + @Deprecated + public SaxonXPathRuleQuery() { + this(DeprecatedAttrLogger.noop()); + } + + public SaxonXPathRuleQuery(DeprecatedAttrLogger attrCtx) { + this.attrCtx = attrCtx; + } + @Override public boolean isSupportedVersion(String version) { return XPATH_1_0_COMPATIBILITY.equals(version) || XPATH_2_0.equals(version); } @Override - @SuppressWarnings("unchecked") public List evaluate(final Node node, final RuleContext data) { initializeXPathExpression(); try { final DocumentNode documentNode = getDocumentNodeForRootNode(node); + documentNode.setAttrCtx(attrCtx); // // Map AST Node -> Saxon Node final ElementNode rootElementNode = documentNode.nodeToElementNode.get(node); + assert rootElementNode != null : "Cannot find " + node; final XPathDynamicContext xpathDynamicContext = createDynamicContext(rootElementNode); final List nodes = new LinkedList<>(); @@ -187,15 +199,13 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { private DocumentNode getDocumentNodeForRootNode(final Node node) { final Node root = getRootNode(node); - DocumentNode documentNode; - synchronized (CACHE) { - documentNode = CACHE.get(root); - if (documentNode == null) { - documentNode = new DocumentNode(root); - CACHE.put(root, documentNode); - } + DataMap> userMap = root.getUserMap(); + DocumentNode docNode = userMap.get(SAXON_TREE_CACHE_KEY); + if (docNode == null) { + docNode = new DocumentNode(root, getNamePool()); + userMap.set(SAXON_TREE_CACHE_KEY, docNode); } - return documentNode; + return docNode; } /** @@ -229,13 +239,14 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { try { final XPathEvaluator xpathEvaluator = new XPathEvaluator(); final XPathStaticContext xpathStaticContext = xpathEvaluator.getStaticContext(); + xpathStaticContext.getConfiguration().setNamePool(getNamePool()); // Enable XPath 1.0 compatibility if (XPATH_1_0_COMPATIBILITY.equals(version)) { ((AbstractStaticContext) xpathStaticContext).setBackwardsCompatibilityMode(true); } - ((IndependentContext) xpathEvaluator.getStaticContext()).declareNamespace("fn", NamespaceConstant.FN); + ((IndependentContext) xpathStaticContext).declareNamespace("fn", NamespaceConstant.FN); // Register PMD functions Initializer.initialize((IndependentContext) xpathStaticContext); @@ -354,4 +365,8 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { initializeXPathExpression(); return super.getRuleChainVisits(); } + + public static NamePool getNamePool() { + return NAME_POOL; + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRenderer.java index 4cc5645b92..0463368e8a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/CodeClimateRenderer.java @@ -33,7 +33,7 @@ public class CodeClimateRenderer extends AbstractIncrementingRenderer { public static final int REMEDIATION_POINTS_DEFAULT = 50000; public static final String[] CODECLIMATE_DEFAULT_CATEGORIES = new String[] {"Style"}; - // Note: required by https://github.com/codeclimate/spec/blob/master/SPEC.md + // Note: required by https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md protected static final String NULL_CHARACTER = "\u0000"; protected static final List INTERNAL_DEV_PROPERTIES = Arrays.asList("version", "xpath"); private static final String PMD_PROPERTIES_URL = getPmdPropertiesURL(); @@ -146,9 +146,9 @@ public class CodeClimateRenderer extends AbstractIncrementingRenderer { private String getBody() { String result = "## " + rule.getName() + "\\n\\n" + "Since: PMD " + rule.getSince() + "\\n\\n" + "Priority: " + rule.getPriority() + "\\n\\n" - + "[Categories](https://github.com/codeclimate/spec/blob/master/SPEC.md#categories): " + + "[Categories](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#categories): " + Arrays.toString(getCategories()).replaceAll("[\\[\\]]", "") + "\\n\\n" - + "[Remediation Points](https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points): " + + "[Remediation Points](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#remediation-points): " + getRemediationPoints() + "\\n\\n" + cleaned(rule.getDescription()); if (!rule.getExamples().isEmpty()) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/AbstractNodeTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/AbstractNodeTest.java index b5ece64c46..d23db81a28 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/AbstractNodeTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/AbstractNodeTest.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -228,7 +228,6 @@ public class AbstractNodeTest { assertEquals(0, grandChild.getNumChildren()); } - @Test public void testDeprecatedAttributeXPathQuery() throws JaxenException { class MyRootNode extends DummyNode implements RootNode { @@ -238,7 +237,8 @@ public class AbstractNodeTest { } } - addChild(new MyRootNode(nextId()), new DummyNodeWithDeprecatedAttribute(2)).findChildNodesWithXPath("//dummyNode[@Size=1]"); + Node root = addChild(new MyRootNode(nextId()), new DummyNodeWithDeprecatedAttribute(2)); + root.findChildNodesWithXPath("//dummyNode[@Size=1]"); String log = loggingRule.getLog(); @@ -247,5 +247,4 @@ public class AbstractNodeTest { assertTrue(log.contains("dummyNode/@Size")); } - } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java index 8cfa55925e..10ddb52a1d 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java @@ -26,6 +26,21 @@ public class DummyNode extends AbstractNode { this.xpathName = xpathName; } + public void setBeginColumn(int i) { + beginColumn = i; + } + + public void setBeginLine(int i) { + beginLine = i; + } + + public void setCoords(int bline, int bcol, int eline, int ecol) { + beginLine = bline; + beginColumn = bcol; + endLine = eline; + endColumn = ecol; + } + @Override public String toString() { return xpathName; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNodeWithDeprecatedAttribute.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNodeWithDeprecatedAttribute.java index 7deca9984b..0e5dd20606 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNodeWithDeprecatedAttribute.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNodeWithDeprecatedAttribute.java @@ -25,7 +25,7 @@ public class DummyNodeWithDeprecatedAttribute extends DummyNode { // this is a attribute that is deprecated for xpath, because it will be removed. // it should still be available via Java. - @DeprecatedAttribute + @DeprecatedAttribute(replaceWith = "@Image") public String getName() { return "foo"; } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIteratorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIteratorTest.java index 1d9e274921..a1dda2cb58 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIteratorTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/xpath/AttributeAxisIteratorTest.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.ast.xpath; -import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -16,15 +15,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.hamcrest.Matchers; -import org.hamcrest.collection.IsMapContaining; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; -import net.sourceforge.pmd.junit.JavaUtilLoggingRule; import net.sourceforge.pmd.lang.ast.DummyNode; -import net.sourceforge.pmd.lang.ast.DummyNodeWithDeprecatedAttribute; import net.sourceforge.pmd.lang.ast.Node; @@ -33,32 +27,6 @@ import net.sourceforge.pmd.lang.ast.Node; */ public class AttributeAxisIteratorTest { - @Rule - public JavaUtilLoggingRule loggingRule = new JavaUtilLoggingRule(Attribute.class.getName()); - - /** - * Verifies that attributes are returned, even if they are deprecated. - * Deprecated attributes are still accessible, but a warning is logged, when - * the value is used. - */ - @Test - public void testAttributeDeprecation() { - // make sure, we log - Attribute.DETECTED_DEPRECATED_ATTRIBUTES.clear(); - - Node dummy = new DummyNodeWithDeprecatedAttribute(2); - Map attributes = toMap(new AttributeAxisIterator(dummy)); - assertThat(attributes, IsMapContaining.hasKey("Size")); - assertThat(attributes, IsMapContaining.hasKey("Name")); - - assertThat(attributes.get("Size").getStringValue(), Matchers.is("2")); - assertThat(attributes.get("Name").getStringValue(), Matchers.is("foo")); - - String log = loggingRule.getLog(); - assertThat(log, Matchers.containsString("Use of deprecated attribute 'dummyNode/@Size' in XPath query")); - assertThat(log, Matchers.containsString("Use of deprecated attribute 'dummyNode/@Name' in XPath query")); - } - /** * Test hasNext and next. */ diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java index e9bc85a985..07605202d5 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/XPathRuleTest.java @@ -4,18 +4,37 @@ package net.sourceforge.pmd.lang.rule; +import static java.util.Collections.singletonList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +import org.hamcrest.Matchers; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.junit.JavaUtilLoggingRule; +import net.sourceforge.pmd.lang.DummyLanguageModule; +import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.lang.ast.DummyNode; +import net.sourceforge.pmd.lang.ast.DummyNodeWithDeprecatedAttribute; +import net.sourceforge.pmd.lang.ast.xpath.Attribute; +import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; + public class XPathRuleTest { + @Rule + public JavaUtilLoggingRule loggingRule = new JavaUtilLoggingRule(Attribute.class.getName()); + /** * It's easy to forget the attribute "typeResolution=true" when * defining XPath rules in xml. Therefore we by default enable * typeresolution. For Java rules, type resolution was enabled by * default long time ago. * - * @see #2048 [core] Enable type resolution by default for XPath rules + * @see #2048 [core] Enable type resolution by default for XPath + * rules */ @Test public void typeResolutionShouldBeEnabledByDefault() { @@ -26,4 +45,75 @@ public class XPathRuleTest { Assert.assertTrue(rule2.isTypeResolution()); } + + @Test + public void testAttributeDeprecation10() { + testDeprecation(XPathVersion.XPATH_1_0); + } + + @Test + public void testAttributeDeprecation20() { + testDeprecation(XPathVersion.XPATH_2_0); + } + + public void testDeprecation(XPathVersion version) { + XPathRule xpr = makeRule(version, "SomeRule"); + + loggingRule.clear(); + + RuleContext ctx = new RuleContext(); + ctx.setLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getDefaultVersion()); + DummyNode firstNode = newNode(); + eval(ctx, xpr, firstNode); + assertEquals(1, ctx.getReport().size()); + + String log = loggingRule.getLog(); + assertThat(log, Matchers.containsString("Use of deprecated attribute 'dummyNode/@Size' by XPath rule 'SomeRule'")); + assertThat(log, Matchers.containsString("Use of deprecated attribute 'dummyNode/@Name' by XPath rule 'SomeRule', please use @Image instead")); + + + loggingRule.clear(); + + eval(ctx, xpr, newNode()); // with another node + assertEquals(2, ctx.getReport().size()); + + assertEquals("", loggingRule.getLog()); // no additional warnings + + + // with another rule forked from the same one (in multithreaded processor) + eval(ctx, xpr.deepCopy(), newNode()); + assertEquals(3, ctx.getReport().size()); + + assertEquals("", loggingRule.getLog()); // no additional warnings + + // with another rule on the same node, new warnings + XPathRule otherRule = makeRule(version, "OtherRule"); + otherRule.setRuleSetName("rset.xml"); + eval(ctx, otherRule, firstNode); + assertEquals(4, ctx.getReport().size()); + + log = loggingRule.getLog(); + assertThat(log, Matchers.containsString("Use of deprecated attribute 'dummyNode/@Size' by XPath rule 'OtherRule' (in ruleset 'rset.xml')")); + assertThat(log, Matchers.containsString("Use of deprecated attribute 'dummyNode/@Name' by XPath rule 'OtherRule' (in ruleset 'rset.xml'), please use @Image instead")); + + } + + public XPathRule makeRule(XPathVersion version, String name) { + XPathRule xpr = new XPathRule(version, "//dummyNode[@Size >= 2 and @Name='foo']"); + xpr.setName(name); + xpr.setMessage("gotcha"); + return xpr; + } + + public void eval(RuleContext ctx, net.sourceforge.pmd.Rule rule, DummyNode node) { + rule.apply(singletonList(node), ctx); + } + + public DummyNode newNode() { + DummyNode dummy = new DummyNodeWithDeprecatedAttribute(2); + dummy.setCoords(1, 1, 1, 2); + return dummy; + } + + } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java index 28ca250b06..c81b425668 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java @@ -30,8 +30,8 @@ public class CodeClimateRendererTest extends AbstractRendererTest { public String getExpected() { return "{\"type\":\"issue\",\"check_name\":\"Foo\",\"description\":\"blah\"," + "\"content\":{\"body\":\"## Foo\\n\\nSince: PMD null\\n\\nPriority: Low\\n\\n" - + "[Categories](https://github.com/codeclimate/spec/blob/master/SPEC.md#categories): Style\\n\\n" - + "[Remediation Points](https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points): 50000\\n\\n" + + "[Categories](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#categories): Style\\n\\n" + + "[Remediation Points](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#remediation-points): 50000\\n\\n" + "desc\\n\\n" + "### [PMD properties](https://pmd.github.io/latest/pmd_devdocs_working_with_properties.html)\\n\\n" + "Name | Value | Description\\n" + "--- | --- | ---\\n" @@ -45,8 +45,8 @@ public class CodeClimateRendererTest extends AbstractRendererTest { public String getExpectedWithProperties() { return "{\"type\":\"issue\",\"check_name\":\"Foo\",\"description\":\"blah\"," + "\"content\":{\"body\":\"## Foo\\n\\nSince: PMD null\\n\\nPriority: Low\\n\\n" - + "[Categories](https://github.com/codeclimate/spec/blob/master/SPEC.md#categories): Style\\n\\n" - + "[Remediation Points](https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points): 50000\\n\\n" + + "[Categories](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#categories): Style\\n\\n" + + "[Remediation Points](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#remediation-points): 50000\\n\\n" + "desc\\n\\n" + "### [PMD properties](https://pmd.github.io/latest/pmd_devdocs_working_with_properties.html)\\n\\n" + "Name | Value | Description\\n" + "--- | --- | ---\\n" @@ -67,8 +67,8 @@ public class CodeClimateRendererTest extends AbstractRendererTest { public String getExpectedMultiple() { return "{\"type\":\"issue\",\"check_name\":\"Foo\",\"description\":\"blah\"," + "\"content\":{\"body\":\"## Foo\\n\\nSince: PMD null\\n\\nPriority: Low\\n\\n" - + "[Categories](https://github.com/codeclimate/spec/blob/master/SPEC.md#categories): Style\\n\\n" - + "[Remediation Points](https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points): 50000\\n\\n" + + "[Categories](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#categories): Style\\n\\n" + + "[Remediation Points](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#remediation-points): 50000\\n\\n" + "desc\\n\\n" + "### [PMD properties](https://pmd.github.io/latest/pmd_devdocs_working_with_properties.html)\\n\\n" + "Name | Value | Description\\n" + "--- | --- | ---\\n" @@ -77,8 +77,8 @@ public class CodeClimateRendererTest extends AbstractRendererTest { + "\"},\"categories\":[\"Style\"],\"location\":{\"path\":\"" + getSourceCodeFilename() + "\",\"lines\":{\"begin\":1,\"end\":1}},\"severity\":\"info\",\"remediation_points\":50000}" + "\u0000" + PMD.EOL + "{\"type\":\"issue\",\"check_name\":\"Foo\",\"description\":\"blah\"," + "\"content\":{\"body\":\"## Foo\\n\\nSince: PMD null\\n\\nPriority: Low\\n\\n" - + "[Categories](https://github.com/codeclimate/spec/blob/master/SPEC.md#categories): Style\\n\\n" - + "[Remediation Points](https://github.com/codeclimate/spec/blob/master/SPEC.md#remediation-points): 50000\\n\\n" + + "[Categories](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#categories): Style\\n\\n" + + "[Remediation Points](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md#remediation-points): 50000\\n\\n" + "desc\\n\\n" + "### [PMD properties](https://pmd.github.io/latest/pmd_devdocs_working_with_properties.html)\\n\\n" + "Name | Value | Description\\n" + "--- | --- | ---\\n" diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/xml/j2ee.xml b/pmd-core/src/test/resources/net/sourceforge/pmd/xml/j2ee.xml index f158927f95..17443c62ab 100644 --- a/pmd-core/src/test/resources/net/sourceforge/pmd/xml/j2ee.xml +++ b/pmd-core/src/test/resources/net/sourceforge/pmd/xml/j2ee.xml @@ -20,6 +20,7 @@ 3 + 4 + 4 + 4 + 4 + 4 + 3 + 3 + @@ -355,6 +363,7 @@ public class SomeEJB extends EJBObject implements EJBLocalHome { 3 + 3 + 3 + - \ No newline at end of file + diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DeadLinksChecker.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DeadLinksChecker.java index 1ab25d40a6..66d8c45a7e 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DeadLinksChecker.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DeadLinksChecker.java @@ -177,6 +177,12 @@ public class DeadLinksChecker { } else { linkOk = linkTarget.isEmpty() || htmlPages.contains(linkTarget); } + + // maybe a local file + if (!linkOk) { + Path localResource = docsDirectory.resolve(linkTarget); + linkOk = Files.exists(localResource); + } } if (!linkOk) { diff --git a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml index 44e2bb76fb..78591da860 100644 --- a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml +++ b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml @@ -57,6 +57,7 @@ Here might be <script>alert('XSS');</script> as well. And "quotes". 3 + 3 + 3 + 3 + 0; } + /** + * @deprecated Use {@link #getName()} + * @return + */ + @Override + @DeprecatedAttribute(replaceWith = "@Name") + @Deprecated + public String getImage() { + return getName(); + } + + /** Returns the name of the variable. */ + public String getName() { + return super.getImage(); + } /** * Returns true if the declared variable has an array type. @@ -161,9 +177,13 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim /** * Returns the name of the variable. + * + * @deprecated Use {@link #getName()} */ + @Deprecated + @DeprecatedAttribute(replaceWith = "@Name") public String getVariableName() { - return getImage(); + return getName(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractAnyTypeDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractAnyTypeDeclaration.java index 4bd5fc0607..ed9076c669 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractAnyTypeDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractAnyTypeDeclaration.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.ast; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttribute; import net.sourceforge.pmd.lang.java.qname.JavaTypeQualifiedName; import net.sourceforge.pmd.lang.java.typeresolution.typedefinition.JavaTypeDefinition; @@ -37,10 +38,14 @@ public abstract class AbstractAnyTypeDeclaration extends AbstractJavaAccessTypeN || getParent() instanceof ASTRecordBody; } - @Override + /** + * @deprecated Use {@link #getSimpleName()} + */ @Deprecated + @DeprecatedAttribute(replaceWith = "@SimpleName") + @Override public String getImage() { - return super.getImage(); + return getSimpleName(); } @Override @@ -50,7 +55,7 @@ public abstract class AbstractAnyTypeDeclaration extends AbstractJavaAccessTypeN @Override public String getSimpleName() { - return getImage(); + return super.getImage(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AbstractClassWithoutAbstractMethodRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AbstractClassWithoutAbstractMethodRule.java new file mode 100644 index 0000000000..3f20b559d5 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AbstractClassWithoutAbstractMethodRule.java @@ -0,0 +1,50 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + + +package net.sourceforge.pmd.lang.java.rule.bestpractices; + +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration.DeclarationKind; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTExtendsList; +import net.sourceforge.pmd.lang.java.ast.ASTImplementsList; +import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; + +public class AbstractClassWithoutAbstractMethodRule extends AbstractJavaRule { + + public AbstractClassWithoutAbstractMethodRule() { + addRuleChainVisit(ASTClassOrInterfaceDeclaration.class); + } + + @Override + public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { + if (!node.isAbstract() || doesExtend(node) || doesImplement(node)) { + return data; + } + + int countOfAbstractMethods = 0; + for (ASTAnyTypeBodyDeclaration decl : node.getDeclarations()) { + if (decl.getKind() == DeclarationKind.METHOD) { + ASTMethodDeclaration methodDecl = (ASTMethodDeclaration) decl.getDeclarationNode(); + if (methodDecl.isAbstract()) { + countOfAbstractMethods++; + } + } + } + if (countOfAbstractMethods == 0) { + addViolation(data, node); + } + return data; + } + + private boolean doesExtend(ASTClassOrInterfaceDeclaration node) { + return node.getFirstChildOfType(ASTExtendsList.class) != null; + } + + private boolean doesImplement(ASTClassOrInterfaceDeclaration node) { + return node.getFirstChildOfType(ASTImplementsList.class) != null; + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AbstractPositionLiteralsFirstInComparisons.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AbstractPositionLiteralsFirstInComparisons.java new file mode 100644 index 0000000000..3b09462725 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AbstractPositionLiteralsFirstInComparisons.java @@ -0,0 +1,119 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.bestpractices; + +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.java.ast.ASTArgumentList; +import net.sourceforge.pmd.lang.java.ast.ASTArguments; +import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression; +import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression; +import net.sourceforge.pmd.lang.java.ast.ASTEqualityExpression; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; +import net.sourceforge.pmd.lang.java.ast.ASTLiteral; +import net.sourceforge.pmd.lang.java.ast.ASTName; +import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral; +import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; +import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; +import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; +import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; + +class AbstractPositionLiteralsFirstInComparisons extends AbstractJavaRule { + + private final String equalsImage; + + AbstractPositionLiteralsFirstInComparisons(String equalsImage) { + addRuleChainVisit(ASTPrimaryExpression.class); + this.equalsImage = equalsImage; + } + + @Override + public Object visit(ASTPrimaryExpression node, Object data) { + ASTPrimaryPrefix primaryPrefix = node.getFirstChildOfType(ASTPrimaryPrefix.class); + ASTPrimarySuffix primarySuffix = node.getFirstChildOfType(ASTPrimarySuffix.class); + if (primaryPrefix != null && primarySuffix != null) { + ASTName name = primaryPrefix.getFirstChildOfType(ASTName.class); + if (name == null || !name.getImage().endsWith(equalsImage)) { + return data; + } + if (!isSingleStringLiteralArgument(primarySuffix)) { + return data; + } + if (isWithinNullComparison(node)) { + return data; + } + addViolation(data, node); + } + return node; + } + + private boolean isWithinNullComparison(ASTPrimaryExpression node) { + for (ASTExpression parentExpr : node.getParentsOfType(ASTExpression.class)) { + if (isComparisonWithNull(parentExpr, "==", ASTConditionalOrExpression.class) + || isComparisonWithNull(parentExpr, "!=", ASTConditionalAndExpression.class)) { + return true; + } + } + return false; + } + + /* + * Expression/ConditionalAndExpression//EqualityExpression(@Image='!=']//NullLiteral + * Expression/ConditionalOrExpression//EqualityExpression(@Image='==']//NullLiteral + */ + private boolean isComparisonWithNull(ASTExpression parentExpr, String equalOperator, Class condition) { + Node condExpr = null; + ASTEqualityExpression eqExpr = null; + if (parentExpr != null) { + condExpr = parentExpr.getFirstChildOfType(condition); + } + if (condExpr != null) { + eqExpr = condExpr.getFirstDescendantOfType(ASTEqualityExpression.class); + } + if (eqExpr != null) { + return eqExpr.hasImageEqualTo(equalOperator) && eqExpr.hasDescendantOfType(ASTNullLiteral.class); + } + return false; + } + + /* + * This corresponds to the following XPath expression: + * (../PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Literal[@StringLiteral= true()]) + * and + * ( count(../PrimarySuffix/Arguments/ArgumentList/Expression) = 1 ) + */ + private boolean isSingleStringLiteralArgument(ASTPrimarySuffix primarySuffix) { + if (!primarySuffix.isArguments() || primarySuffix.getArgumentCount() != 1) { + return false; + } + Node node = primarySuffix; + node = node.getFirstChildOfType(ASTArguments.class); + if (node != null) { + node = node.getFirstChildOfType(ASTArgumentList.class); + if (node.getNumChildren() != 1) { + return false; + } + } + if (node != null) { + node = node.getFirstChildOfType(ASTExpression.class); + } + if (node != null) { + node = node.getFirstChildOfType(ASTPrimaryExpression.class); + } + if (node != null) { + node = node.getFirstChildOfType(ASTPrimaryPrefix.class); + } + if (node != null) { + node = node.getFirstChildOfType(ASTLiteral.class); + } + if (node != null) { + ASTLiteral literal = (ASTLiteral) node; + if (literal.isStringLiteral()) { + return true; + } + } + return false; + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java index fccfd94132..fb7873371d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/ForLoopCanBeForeachRule.java @@ -229,7 +229,7 @@ public class ForLoopCanBeForeachRule extends AbstractJavaRule { + "/Name[matches(@Image,'\\w+\\.(size|length)')]" + "|" + "./RelationalExpression[@Image='<=']/AdditiveExpression[count(*)=2 and " - + "@Image='-' and PrimaryExpression/PrimaryPrefix/Literal[@Image='1']]" + + "@Operator='-' and PrimaryExpression/PrimaryPrefix/Literal[@Image='1']]" + "/PrimaryExpression/PrimaryPrefix/Name[matches(@Image,'\\w+\\.(size|length)')]"); if (left.isEmpty()) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/PositionLiteralsFirstInCaseInsensitiveComparisonsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/PositionLiteralsFirstInCaseInsensitiveComparisonsRule.java new file mode 100644 index 0000000000..1c84769c01 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/PositionLiteralsFirstInCaseInsensitiveComparisonsRule.java @@ -0,0 +1,13 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.bestpractices; + +public class PositionLiteralsFirstInCaseInsensitiveComparisonsRule extends AbstractPositionLiteralsFirstInComparisons { + + public PositionLiteralsFirstInCaseInsensitiveComparisonsRule() { + super(".equalsIgnoreCase"); + } + +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/PositionLiteralsFirstInComparisonsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/PositionLiteralsFirstInComparisonsRule.java new file mode 100644 index 0000000000..2b9edd12c4 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/PositionLiteralsFirstInComparisonsRule.java @@ -0,0 +1,13 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.bestpractices; + +public class PositionLiteralsFirstInComparisonsRule extends AbstractPositionLiteralsFirstInComparisons { + + public PositionLiteralsFirstInComparisonsRule() { + super(".equals"); + } + +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/JUnitSpellingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/JUnitSpellingRule.java new file mode 100644 index 0000000000..8fd2249133 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/JUnitSpellingRule.java @@ -0,0 +1,28 @@ +/* + * 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.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.rule.AbstractJUnitRule; + +public class JUnitSpellingRule extends AbstractJUnitRule { + + @Override + public Object visit(ASTMethodDeclaration node, Object data) { + if (node.getArity() != 0) { + return super.visit(node, data); + } + + String name = node.getName(); + if (!"setUp".equals(name) && "setup".equalsIgnoreCase(name)) { + addViolation(data, node); + } + if (!"tearDown".equals(name) && "teardown".equalsIgnoreCase(name)) { + addViolation(data, node); + } + return super.visit(node, data); + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/JUnitStaticSuiteRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/JUnitStaticSuiteRule.java new file mode 100644 index 0000000000..de0f71ada6 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/JUnitStaticSuiteRule.java @@ -0,0 +1,24 @@ +/* + * 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.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.rule.AbstractJUnitRule; + +public class JUnitStaticSuiteRule extends AbstractJUnitRule { + + @Override + public Object visit(ASTMethodDeclaration node, Object data) { + if (node.getArity() != 0) { + return super.visit(node, data); + } + String name = node.getName(); + if ("suite".equals(name) && (!node.isStatic() || !node.isPublic())) { + addViolation(data, node); + } + return super.visit(node, data); + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ProperCloneImplementationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ProperCloneImplementationRule.java new file mode 100644 index 0000000000..19262a5535 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ProperCloneImplementationRule.java @@ -0,0 +1,52 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + + +package net.sourceforge.pmd.lang.java.rule.errorprone; + +import java.util.List; + +import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression; +import net.sourceforge.pmd.lang.java.ast.ASTBlock; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; +import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; + +public class ProperCloneImplementationRule extends AbstractJavaRule { + + public ProperCloneImplementationRule() { + addRuleChainVisit(ASTMethodDeclaration.class); + } + + @Override + public Object visit(ASTMethodDeclaration node, Object data) { + if (!"clone".equals(node.getName()) || node.getArity() > 0) { + return data; + } + + ASTBlock block = node.getFirstChildOfType(ASTBlock.class); + if (block == null) { + return data; + } + + String enclosingClassName = node.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class).getSimpleName(); + if (blockHasAllocations(block, enclosingClassName)) { + addViolation(data, node); + } + + return data; + } + + private boolean blockHasAllocations(ASTBlock block, String enclosingClassName) { + List allocations = block.findDescendantsOfType(ASTAllocationExpression.class); + for (ASTAllocationExpression alloc : allocations) { + ASTClassOrInterfaceType type = alloc.getFirstChildOfType(ASTClassOrInterfaceType.class); + if (type.hasImageEqualTo(enclosingClassName)) { + return true; + } + } + return false; + } +} diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index d8ebc8eb6e..3264cd40a3 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -13,7 +13,7 @@ Rules which enforce generally accepted best practices. language="java" since="3.0" message="This abstract class does not have any abstract methods" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.java.rule.bestpractices.AbstractClassWithoutAbstractMethodRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#abstractclasswithoutabstractmethod"> The abstract class does not contain any abstract methods. An abstract class suggests @@ -22,19 +22,6 @@ abstract methods. If the class is intended to be used as a base class only (not directly) a protected constructor can be provided prevent direct instantiation. 3 - - - - - - - 3 + 3 + 3 + @@ -422,12 +412,13 @@ By convention, the default label should be the last label in a switch statement. 3 + @@ -541,6 +532,7 @@ the loop iterates over. By default this rule allows a regular 'for' loop with on + //ForInit/LocalVariableDeclaration[count(VariableDeclarator) > $maximumVariables] @@ -587,12 +579,13 @@ through the @RunWith(Suite.class) annotation. 3 + @@ -628,16 +621,17 @@ JUnit 5 introduced @AfterEach and @AfterAll annotations to execute methods after 3 + @@ -672,16 +666,17 @@ JUnit 5 introduced @BeforeEach and @BeforeAll annotations to execute methods bef 3 + @@ -716,6 +711,7 @@ In JUnit 5, one of the following annotations should be used for tests: @Test, @R 3 + 3 + 4 + Position literals first in comparisons, if the second argument is null then NullPointerExceptions can be avoided, they will just return false. 3 - - - - - - - Position literals first in comparisons, if the second argument is null then NullPointerExceptions can be avoided, they will just return false. 3 - - - - - - - 3 + 3 + //Type/ReferenceType/ClassOrInterfaceType[@Image='Hashtable'] @@ -1206,6 +1166,7 @@ Consider replacing Vector usages with the newer java.util.ArrayList if expensive 3 + //Type/ReferenceType/ClassOrInterfaceType[@Image='Vector'] @@ -1267,6 +1228,7 @@ will (and by priority) and avoid clogging the Standard out log. 2 + 3 + @@ -1465,17 +1427,11 @@ more specific methods, like assertNull, assertNotNull. 3 + @@ -1519,17 +1481,11 @@ by more specific methods, like assertSame, assertNotSame. 3 + @@ -1569,6 +1531,7 @@ When asserting a value is the same as a literal or Boxed boolean, use assertTrue 3 + 3 + @@ -112,11 +113,12 @@ If the goal is to avoid defining constants in a scope smaller than the class, th 3 + 4 + @@ -210,12 +213,13 @@ Clarify your intent by using private or package access modifiers instead. 3 + @@ -244,12 +248,13 @@ visibility cannot be reduced). Clarify your intent by using private or package a 3 + @@ -276,6 +281,7 @@ and increases the maintenance burden. 2 + //Name[starts-with(@Image,'System.loadLibrary')] @@ -313,12 +319,13 @@ prefix for these methods. 4 + 3 + 0 ] +//ClassOrInterfaceDeclaration[ExtendsList/*] /ClassOrInterfaceBody /ClassOrInterfaceBodyDeclaration - /ConstructorDeclaration[ count (.//ExplicitConstructorInvocation)=0 ] + /ConstructorDeclaration[ not(.//ExplicitConstructorInvocation) ] ]]> @@ -549,16 +557,17 @@ The rule allows methods and fields annotated with Guava's @VisibleForTesting. 3 + @@ -620,23 +629,24 @@ usage by developers who should be implementing their own versions in the concret 1 + @@ -666,6 +676,7 @@ public abstract class ShouldBeAbstract { No need to explicitly extend Object. 4 + 3 + 3 + //ForStatement[not(Statement/Block)] @@ -860,13 +873,14 @@ Names for references to generic values should be limited to a single uppercase l 4 + 1 or - string:upper-case(@Image) != @Image + upper-case(@Image) != @Image ] ]]> @@ -943,11 +957,12 @@ by the rule {% rule java/codestyle/ControlStatementBraces %}. 3 + @@ -985,6 +1000,7 @@ by the rule {% rule java/codestyle/ControlStatementBraces %}. 3 + 4 + 4 + 3 + $minimum] +//VariableDeclaratorId[string-length(@Name) > $minimum] ]]> @@ -1248,6 +1267,7 @@ The EJB Specification states that any MessageDrivenBean or SessionBean should be 4 + 3 + @@ -1478,6 +1499,7 @@ Detects when a package definition contains uppercase characters. 3 + //PackageDeclaration/Name[lower-case(@Image)!=@Image] @@ -1531,6 +1553,7 @@ Remote Interface of a Session EJB should not have a suffix. 4 + 4 + 4 + 3 + 3 + @@ -1764,10 +1791,11 @@ which class a static member comes from (Sun 1.5 Language Guide). + $maximumStaticImports] +.[count(ImportDeclaration[@Static = true()]) > $maximumStaticImports] ]]> @@ -2003,6 +2031,7 @@ List stringsWithDiamond = new ArrayList<>(); // using the diamond operat Useless parentheses should be removed. 4 + stringsWithDiamond = new ArrayList<>(); // using the diamond operat | //Expression/ConditionalAndExpression/PrimaryExpression/PrimaryPrefix/Expression[ count(*)=1 and - count(./CastExpression)=0 and - count(./EqualityExpression/MultiplicativeExpression)=0 and - count(./ConditionalExpression)=0 and - count(./ConditionalOrExpression)=0] + not(./CastExpression) and + not(./EqualityExpression/MultiplicativeExpression) and + not(./ConditionalExpression) and + not(./ConditionalOrExpression)] | //Expression/ConditionalOrExpression/PrimaryExpression/PrimaryPrefix/Expression[ count(*)=1 and @@ -2034,11 +2063,11 @@ List stringsWithDiamond = new ArrayList<>(); // using the diamond operat not(./CastExpression) and not(./EqualityExpression)] | -//Expression/AdditiveExpression[not(./PrimaryExpression/PrimaryPrefix/Literal[@StringLiteral='true'])] +//Expression/AdditiveExpression[not(./PrimaryExpression/PrimaryPrefix/Literal[@StringLiteral= true()])] /PrimaryExpression[1]/PrimaryPrefix/Expression[ count(*)=1 and not(./CastExpression) and - not(./AdditiveExpression[@Image = '-']) and + not(./AdditiveExpression[@Operator = '-']) and not(./ShiftExpression) and not(./RelationalExpression) and not(./InstanceOfExpression) and @@ -2091,14 +2120,15 @@ public class Foo { 3 + @@ -2150,6 +2180,7 @@ E.g. `int[] x = new int[] { 1, 2, 3 };` can be written as `int[] x = { 1, 2, 3 } 3 + 3 + //WhileStatement[not(Statement/Block)] diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index 2fb4fe92d8..dba3f14cec 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -23,12 +23,14 @@ protected constructor in order to prevent instantiation than make the class misl 1 + @@ -55,6 +57,7 @@ Avoid catching generic exceptions such as NullPointerException, RuntimeException 3 + 3 + @@ -161,6 +165,7 @@ code size and runtime complexity. 3 + 1 + 1 + 3 + 1 + = 1 ] -[count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[(@Public = 'true') or (@Protected = 'true') or (@PackagePrivate = 'true')]) = 0 ] +//TypeDeclaration[count(../TypeDeclaration) = 1]/ClassOrInterfaceDeclaration +[@Final = false()] +[ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[@Private = true()]] +[not(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[(@Public = true()) or (@Protected = true()) or (@PackagePrivate = true())])] [not(.//ClassOrInterfaceDeclaration)] ]]> @@ -367,15 +376,16 @@ Sometimes two consecutive 'if' statements can be consolidated by separating thei 3 + @@ -532,6 +542,7 @@ Errors are system exceptions. Do not extend them. 3 + 3 + @@ -845,6 +857,7 @@ Use opposite operator instead of negating the whole expression with a logic comp 3 + 3 + 3 + @@ -1297,6 +1311,7 @@ Avoid unnecessary comparisons in boolean expressions, they serve no purpose and 3 + 3 + 3 + /Block /BlockStatement[last()] [not(Statement/StatementExpression/PrimaryExpression - [./PrimaryPrefix[@SuperModifier='true']] + [./PrimaryPrefix[@SuperModifier= true()]] [./PrimarySuffix[@Image='finalize']] ) ] [not(Statement/TryStatement/FinallyStatement /Block/BlockStatement/Statement/StatementExpression/PrimaryExpression - [./PrimaryPrefix[@SuperModifier='true']] + [./PrimaryPrefix[@SuperModifier= true()]] [./PrimarySuffix[@Image='finalize']] ) ] @@ -1917,6 +1938,7 @@ If the finalize() is implemented, it should do something besides just calling su 3 + @@ -1954,6 +1976,7 @@ Note that Oracle has declared Object.finalize() as deprecated since JDK 9. 3 + 3 + @@ -2057,6 +2081,7 @@ Avoid instantiating an object just to call getClass() on it; use the .class publ 4 + 3 + @@ -2146,37 +2172,12 @@ public class JumbledIncrementerRule1 { language="java" since="1.0" message="You may have misspelled a JUnit framework method (setUp or tearDown)" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.java.rule.errorprone.JUnitSpellingRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#junitspelling"> Some JUnit framework methods are easy to misspell. 3 - - - - - - - The suite() method in a JUnit test needs to be both public and static. 3 - - - - - - - 2 + @@ -2343,7 +2322,7 @@ Either the check is useless (the variable will never be "null") or it is incorre public class Foo { void bar() { if (a.equals(baz) && a != null) {} // a could be null, misplaced null check - + if (a != null && a.equals(baz)) {} // correct null check } } @@ -2354,7 +2333,7 @@ public class Foo { public class Foo { void bar() { if (a.equals(baz) || a == null) {} // a could be null, misplaced null check - + if (a == null || a.equals(baz)) {} // correct null check } } @@ -2374,6 +2353,7 @@ may indicate problematic behaviour. Empty cases are ignored as these indicate an 3 + @@ -2427,13 +2407,14 @@ chain needs an own serialVersionUID field. See also [Should an abstract class ha 3 + @@ -2470,14 +2451,13 @@ See the property `annotations`. 3 + //SwitchStatement//BlockStatement/Statement/LabeledStatement @@ -2684,29 +2661,12 @@ public class Foo { // perfect, both methods provided language="java" since="1.4" message="Object clone() should be implemented with super.clone()" - class="net.sourceforge.pmd.lang.rule.XPathRule" + class="net.sourceforge.pmd.lang.java.rule.errorprone.ProperCloneImplementationRule" externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#propercloneimplementation"> Object clone() should be implemented with super.clone(). 2 - - - - 0 -] -]]> - - - @@ -2793,12 +2753,13 @@ NullPointerExceptions. 1 + 3 + 3 + @@ -3024,6 +2987,7 @@ new StringBuilder("A") // 1 + 16 = 17 4 + 2 + 3 + 3 + @@ -3319,14 +3285,15 @@ After checking an object reference for null, you should invoke equals() on that 3 + @@ -3385,16 +3352,21 @@ To make sure the full stacktrace is printed out, use the logging statement with 3 + @@ -3428,14 +3400,15 @@ Use the equals() method instead. 3 + @@ -3502,6 +3475,7 @@ class Test { 3 + 3 + //PrimarySuffix[@Image='getClassLoader'] diff --git a/pmd-java/src/main/resources/category/java/multithreading.xml b/pmd-java/src/main/resources/category/java/multithreading.xml index 3a26eb7a07..b70ea643db 100644 --- a/pmd-java/src/main/resources/category/java/multithreading.xml +++ b/pmd-java/src/main/resources/category/java/multithreading.xml @@ -22,8 +22,9 @@ gets it. 3 + - //MethodDeclaration[@Synchronized='true'] + //MethodDeclaration[@Synchronized= true()] @@ -65,6 +66,7 @@ it contains methods that are not thread-safe. 3 + 2 + - //FieldDeclaration[contains(@Volatile,'true')] + //FieldDeclaration[@Volatile = true()] @@ -129,6 +132,7 @@ Also EJB's might be moved between machines in a cluster and only managed resourc 3 + 4 + 3 + 3 + - \ No newline at end of file + diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml index 7d0c75b226..8213f85f83 100644 --- a/pmd-java/src/main/resources/category/java/performance.xml +++ b/pmd-java/src/main/resources/category/java/performance.xml @@ -21,6 +21,7 @@ It is much better to use one of the type-specific toString() methods instead. 3 + 3 + 1 + 1 + 2 + 2 + 2 + 3 + 3 + 2 + 3 + 3 + 0] +//CompilationUnit[not(ImportDeclaration) or ImportDeclaration[@ImportedName='java.util.Vector']] //AllocationExpression/ClassOrInterfaceType [@Image='Vector' or @Image='java.util.Vector'] ]]> @@ -846,11 +858,12 @@ You must use new ArrayList<>(Arrays.asList(...)) if that is inconvenient for you 3 + (Arrays.asList(...)) if that is inconvenient for you @Image="ArrayList" ] )=1 - ]/@Image + ]/@Name ] and PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name [ - @Image = ancestor::MethodDeclaration[1]//LocalVariableDeclaration/VariableDeclarator/VariableDeclaratorId[@ArrayType="true"]/@Image + @Image = ancestor::MethodDeclaration[1]//LocalVariableDeclaration/VariableDeclarator/VariableDeclaratorId[@ArrayType=true()]/@Name or - @Image = ancestor::MethodDeclaration[1]//FormalParameter/VariableDeclaratorId/@Image + @Image = ancestor::MethodDeclaration[1]//FormalParameter/VariableDeclaratorId/@Name ] /../..[count(.//PrimarySuffix) =1]/PrimarySuffix/Expression/PrimaryExpression/PrimaryPrefix diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/ReportTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/ReportTest.java index cac861109b..383d64cbde 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/ReportTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/ReportTest.java @@ -40,7 +40,7 @@ public class ReportTest extends RuleTst { public void testExclusionsInReportWithRuleViolationSuppressXPath() { Report rpt = new Report(); Rule rule = new FooRule(); - rule.setProperty(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR, ".[@Image = 'Foo']"); + rule.setProperty(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR, ".[@SimpleName = 'Foo']"); runTestFromString(TEST1, rule, rpt, defaultLanguage); assertTrue(rpt.isEmpty()); assertEquals(1, rpt.getSuppressedRuleViolations().size()); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java index 10f37ebcb9..2dc75f74cc 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/metrics/xpath/XPathMetricFunctionTest.java @@ -34,6 +34,8 @@ import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; */ public class XPathMetricFunctionTest { + // TODO 7.0 when removing jaxen these tests need to be updated to use pmd-java:metric + private static final String VIOLATION_MESSAGE = "violation"; @org.junit.Rule diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java index a82c36426b..90e01fabe5 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -53,7 +53,7 @@ public class XPathRuleTest extends RuleTst { @Test public void testPluginname() throws Exception { - XPathRule rule = makeXPath("//VariableDeclaratorId[string-length(@Image) < 3]"); + XPathRule rule = makeXPath("//VariableDeclaratorId[string-length(@Name) < 3]"); rule.setMessage("{0}"); Report report = getReportForTestString(rule, TEST1); RuleViolation rv = report.iterator().next(); @@ -63,7 +63,7 @@ public class XPathRuleTest extends RuleTst { @Test public void testXPathMultiProperty() throws Exception { - XPathRule rule = makeXPath("//VariableDeclaratorId[@Image=$forbiddenNames]"); + XPathRule rule = makeXPath("//VariableDeclaratorId[@Name=$forbiddenNames]"); rule.setMessage("Avoid vars"); PropertyDescriptor> varDescriptor = PropertyFactory.stringListProperty("forbiddenNames") @@ -86,7 +86,7 @@ public class XPathRuleTest extends RuleTst { @Test public void testVariables() throws Exception { - XPathRule rule = makeXPath("//VariableDeclaratorId[@Image=$var]"); + XPathRule rule = makeXPath("//VariableDeclaratorId[@Name=$var]"); rule.setMessage("Avoid vars"); PropertyDescriptor varDescriptor = PropertyFactory.stringProperty("var").desc("Test var").defaultValue("").build(); @@ -99,7 +99,7 @@ public class XPathRuleTest extends RuleTst { @Test public void testFnPrefixOnSaxon() throws Exception { - XPathRule rule = makeXPath("//VariableDeclaratorId[fn:matches(@Image, 'fiddle')]"); + XPathRule rule = makeXPath("//VariableDeclaratorId[fn:matches(@Name, 'fiddle')]"); Report report = getReportForTestString(rule, TEST2); RuleViolation rv = report.iterator().next(); assertEquals(3, rv.getBeginLine()); @@ -107,7 +107,7 @@ public class XPathRuleTest extends RuleTst { @Test public void testNoFnPrefixOnSaxon() throws Exception { - XPathRule rule = makeXPath("//VariableDeclaratorId[matches(@Image, 'fiddle')]"); + XPathRule rule = makeXPath("//VariableDeclaratorId[matches(@Name, 'fiddle')]"); Report report = getReportForTestString(rule, TEST2); RuleViolation rv = report.iterator().next(); assertEquals(3, rv.getBeginLine()); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java index 57ae0deec3..94756287bb 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/typeresolution/ClassTypeResolverTest.java @@ -452,8 +452,7 @@ public class ClassTypeResolverTest { ASTCompilationUnit acu = java5.parseClass(Promotion.class); List expressions = convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = " - + "'unaryNumericPromotion']]//Expression[UnaryExpression]"), + "//MethodDeclaration[@Name = 'unaryNumericPromotion']/Block//Expression[UnaryExpression]"), ASTExpression.class); int index = 0; @@ -474,8 +473,7 @@ public class ClassTypeResolverTest { ASTCompilationUnit acu = java5.parseClass(Promotion.class); List expressions = convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = " - + "'binaryNumericPromotion']]//Expression[AdditiveExpression]"), + "//MethodDeclaration[@Name = 'binaryNumericPromotion']/Block//Expression[AdditiveExpression]"), ASTExpression.class); int index = 0; @@ -545,7 +543,7 @@ public class ClassTypeResolverTest { ASTCompilationUnit acu = java5.parseClass(Promotion.class); List expressions = convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = 'binaryStringPromotion']]//Expression"), + "//MethodDeclaration[@Name = 'binaryStringPromotion']/Block//Expression"), ASTExpression.class); int index = 0; @@ -564,7 +562,7 @@ public class ClassTypeResolverTest { ASTCompilationUnit acu = java5.parseClass(Operators.class); List expressions = convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = 'unaryLogicalOperators']]//Expression"), + "//MethodDeclaration[@Name = 'unaryLogicalOperators']/Block//Expression"), ASTExpression.class); int index = 0; @@ -580,7 +578,7 @@ public class ClassTypeResolverTest { ASTCompilationUnit acu = java5.parseClass(Operators.class); List expressions = convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = 'binaryLogicalOperators']]//Expression"), + "//MethodDeclaration[@Name = 'binaryLogicalOperators']/Block//Expression"), ASTExpression.class); int index = 0; @@ -606,24 +604,22 @@ public class ClassTypeResolverTest { public void testUnaryNumericOperators() throws JaxenException { ASTCompilationUnit acu = java5.parseClass(Operators.class); List expressions = new ArrayList<>(); + final String baseXPath = "//MethodDeclaration[@Name = 'unaryNumericOperators']/Block"; expressions.addAll(convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = 'unaryNumericOperators']]//Expression"), + baseXPath + "//Expression"), TypeNode.class)); expressions.addAll(convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = " - + "'unaryNumericOperators']]//PostfixExpression"), + baseXPath + "//PostfixExpression"), TypeNode.class)); expressions.addAll(convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = " - + "'unaryNumericOperators']]//PreIncrementExpression"), + baseXPath + "//PreIncrementExpression"), TypeNode.class)); expressions.addAll(convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = " - + "'unaryNumericOperators']]//PreDecrementExpression"), + baseXPath + "//PreDecrementExpression"), TypeNode.class)); int index = 0; @@ -643,7 +639,7 @@ public class ClassTypeResolverTest { ASTCompilationUnit acu = java5.parseClass(Operators.class); List expressions = convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = 'binaryNumericOperators']]//Expression"), + "//MethodDeclaration[@Name = 'binaryNumericOperators']/Block//Expression"), ASTExpression.class); int index = 0; @@ -665,8 +661,7 @@ public class ClassTypeResolverTest { ASTCompilationUnit acu = java5.parseClass(Operators.class); List expressions = convertList( acu.findChildNodesWithXPath( - "//Block[preceding-sibling::MethodDeclarator[@Image = " - + "'assignmentOperators']]//StatementExpression"), + "//MethodDeclaration[@Name = 'assignmentOperators']/Block//StatementExpression"), ASTStatementExpression.class); int index = 0; diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/ant/classpathtest/ruleset.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/ant/classpathtest/ruleset.xml index 8b3efddecc..660898adc4 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/ant/classpathtest/ruleset.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/ant/classpathtest/ruleset.xml @@ -19,6 +19,7 @@ Avoid jumbled loop incrementers - its usually a mistake, and is confusing even i 3 + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedFormalParameter.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedFormalParameter.xml index ba281bbf8a..879d7d748a 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedFormalParameter.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedFormalParameter.xml @@ -217,7 +217,7 @@ class Foo { violation suppression xpath works, by name ]]> - .[@Image = 'paramB'] + .[@Name = 'paramB'] 0 - + bad, new BigDecimal(.1) 1 - + ok, new BigDecimal(".1") 0 ok, new BigDecimal(10) 0 - + bad, same as #1 but outside an initializer context 1 #1187 double variable with AvoidDecimalLiteralsInBigDecimalConstructor 8 - 4,8,11,14,18,22,25,28 + 6,10,13,16,20,24,27,30 diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseCorrectExceptionLogging.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseCorrectExceptionLogging.xml index cc94e27c55..6722f48456 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseCorrectExceptionLogging.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/UseCorrectExceptionLogging.xml @@ -3,10 +3,9 @@ xmlns="http://pmd.sourceforge.net/rule-tests" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd"> + - + ok 0 + - + failure case - two calls 2 + - + must be in a catch block 0 + - + bug 1626232, the rule should not be confused by inner classes 0 + - + bug 1626232, should work with a static block 1 + + + XPath problem: A sequence of more than one item is not allowed as the first argument of concat() + 0 + + diff --git a/pmd-javascript/src/main/resources/category/ecmascript/bestpractices.xml b/pmd-javascript/src/main/resources/category/ecmascript/bestpractices.xml index 52cdac1822..5b39319cd2 100644 --- a/pmd-javascript/src/main/resources/category/ecmascript/bestpractices.xml +++ b/pmd-javascript/src/main/resources/category/ecmascript/bestpractices.xml @@ -18,6 +18,7 @@ Rules which enforce generally accepted best practices. Avoid using with - it's bad news 1 + 1 + @@ -116,6 +118,7 @@ is better to explicitly scope the variable name to the nearest enclosing scope w 1 + 1 + 2 + @@ -72,6 +73,7 @@ Avoid using 'for' statements without using curly braces. 3 + 3 + @@ -146,10 +149,11 @@ Avoid using if statements without using curly braces. 3 + @@ -182,10 +186,11 @@ See also: <http://eslint.org/docs/rules/no-else-return> 3 + @@ -221,6 +226,7 @@ be misleading. Considering removing this unnecessary Block. 3 + Unnecessary parentheses should be removed. 4 + 1 + 3 + 1 + @@ -57,14 +58,14 @@ same type. The === operator avoids the casting. 3 + @@ -104,10 +105,11 @@ precision in a floating point number. This may result in numeric calculations b 2 + diff --git a/pmd-jsp/src/main/resources/category/jsp/bestpractices.xml b/pmd-jsp/src/main/resources/category/jsp/bestpractices.xml index 564c645975..b98e02c1a9 100644 --- a/pmd-jsp/src/main/resources/category/jsp/bestpractices.xml +++ b/pmd-jsp/src/main/resources/category/jsp/bestpractices.xml @@ -20,6 +20,7 @@ Do not nest JSF component custom actions inside a custom action that iterates ov 3 + 2 + 2 + 3 + 3 + 2 + 3 + 3 + 2 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + " - \ No newline at end of file + diff --git a/pmd-vm/src/main/resources/category/vm/design.xml b/pmd-vm/src/main/resources/category/vm/design.xml index 7bea5920f7..d5d65f4f20 100644 --- a/pmd-vm/src/main/resources/category/vm/design.xml +++ b/pmd-vm/src/main/resources/category/vm/design.xml @@ -67,6 +67,7 @@ Avoid inline styles. Use css classes instead. 2 + 3 + 3 + diff --git a/pmd-xml/src/main/resources/category/xml/errorprone.xml b/pmd-xml/src/main/resources/category/xml/errorprone.xml index 46f598d8e4..48f7cceea2 100644 --- a/pmd-xml/src/main/resources/category/xml/errorprone.xml +++ b/pmd-xml/src/main/resources/category/xml/errorprone.xml @@ -20,6 +20,7 @@ An XML CDATA section begins with a <![CDATA[ marker, which has only one [, an 3 + 3 +