diff --git a/.all-contributorsrc b/.all-contributorsrc index 4166d23161..924c39021e 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -7462,6 +7462,78 @@ "contributions": [ "bug" ] + }, + { + "login": "BurovnikovEvgeniy", + "name": "BurovnikovEvgeniy", + "avatar_url": "https://avatars.githubusercontent.com/u/71849985?v=4", + "profile": "https://github.com/BurovnikovEvgeniy", + "contributions": [ + "bug" + ] + }, + { + "login": "kohlschuetter", + "name": "Dr. Christian Kohlschütter", + "avatar_url": "https://avatars.githubusercontent.com/u/822690?v=4", + "profile": "https://kohlschuetter.github.io/blog/", + "contributions": [ + "bug" + ] + }, + { + "login": "Luro02", + "name": "Lucas", + "avatar_url": "https://avatars.githubusercontent.com/u/24826124?v=4", + "profile": "https://github.com/Luro02", + "contributions": [ + "bug" + ] + }, + { + "login": "rs23", + "name": "Reinhard Schiedermeier", + "avatar_url": "https://avatars.githubusercontent.com/u/12321337?v=4", + "profile": "http://sol.cs.hm.edu/rs", + "contributions": [ + "bug" + ] + }, + { + "login": "andygoossens", + "name": "Andy Goossens", + "avatar_url": "https://avatars.githubusercontent.com/u/2099087?v=4", + "profile": "https://github.com/andygoossens", + "contributions": [ + "bug" + ] + }, + { + "login": "mitchspano", + "name": "Mitch Spano", + "avatar_url": "https://avatars.githubusercontent.com/u/18402464?v=4", + "profile": "https://github.com/mitchspano", + "contributions": [ + "bug" + ] + }, + { + "login": "mfvanek", + "name": "Ivan Vakhrushev", + "avatar_url": "https://avatars.githubusercontent.com/u/37612014?v=4", + "profile": "https://www.linkedin.com/in/mfvanek/", + "contributions": [ + "bug" + ] + }, + { + "login": "VishV-Android", + "name": "Vishv_Android", + "avatar_url": "https://avatars.githubusercontent.com/u/126696109?v=4", + "profile": "https://github.com/VishV-Android", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9ccf28a9a3..e37d01fa33 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,6 +48,8 @@ jobs: ~/.cache ~/work/pmd/target/repositories vendor/bundle + # avoid caching missed dependencies + !~/.m2/repository/**/*.lastUpdated key: v3-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} restore-keys: | v3-${{ runner.os }}- @@ -60,7 +62,7 @@ jobs: run: | echo "LANG=en_US.UTF-8" >> $GITHUB_ENV echo "MAVEN_OPTS=-Daether.connector.http.connectionMaxTtl=180 -DautoReleaseAfterClose=true -DstagingProgressTimeoutMinutes=30" >> $GITHUB_ENV - echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/master/scripts" >> $GITHUB_ENV + echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/24/scripts" >> $GITHUB_ENV - name: Check Environment shell: bash run: | diff --git a/.github/workflows/git-repo-sync.yml b/.github/workflows/git-repo-sync.yml index c564eeea92..d0327c4e2b 100644 --- a/.github/workflows/git-repo-sync.yml +++ b/.github/workflows/git-repo-sync.yml @@ -24,7 +24,7 @@ jobs: shell: bash run: | echo "LANG=en_US.UTF-8" >> $GITHUB_ENV - echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/master/scripts" >> $GITHUB_ENV + echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/24/scripts" >> $GITHUB_ENV - name: Sync run: .ci/git-repo-sync.sh shell: bash diff --git a/.github/workflows/troubleshooting.yml b/.github/workflows/troubleshooting.yml index 58b1c56fcc..010e2a0fc4 100644 --- a/.github/workflows/troubleshooting.yml +++ b/.github/workflows/troubleshooting.yml @@ -36,7 +36,7 @@ jobs: run: | echo "LANG=en_US.UTF-8" >> $GITHUB_ENV echo "MAVEN_OPTS=-Daether.connector.http.connectionMaxTtl=180 -DstagingProgressTimeoutMinutes=30" >> $GITHUB_ENV - echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/master/scripts" >> $GITHUB_ENV + echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/24/scripts" >> $GITHUB_ENV - name: Check Environment shell: bash run: | diff --git a/Dangerfile b/Dangerfile index 0e35809f22..97e38cf3c3 100644 --- a/Dangerfile +++ b/Dangerfile @@ -44,7 +44,7 @@ def run_pmdtester @base_branch = 'master' @logger.info "\n\n--------------------------------------" @logger.info "Run against #{@base_branch}" - @summary = PmdTester::Runner.new(get_args(@base_branch, FALSE, 'target/diff1/patch_config.xml')).run + @summary = PmdTester::Runner.new(get_args(@base_branch, false, 'target/diff1/patch_config.xml')).run # move the generated report out of the way FileUtils.mv 'target/reports/diff', 'target/diff2' @@ -53,12 +53,12 @@ def run_pmdtester tar_report - message1 += "[Download full report as build artifact](#{ENV['PMD_CI_JOB_URL']})" + message1 += "[Download full report as build artifact](#{ENV['PMD_CI_JOB_URL']}?pr=#{ENV['PMD_CI_PULL_REQUEST_NUMBER']})" # set value of sticky to true and the message is kept after new commits are submitted to the PR message(message1, sticky: true) if message2 - message2 += "[Download full report as build artifact](#{ENV['PMD_CI_JOB_URL']})" + message2 += "[Download full report as build artifact](#{ENV['PMD_CI_JOB_URL']}?pr=#{ENV['PMD_CI_PULL_REQUEST_NUMBER']})" # set value of sticky to true and the message is kept after new commits are submitted to the PR message(message2, sticky: true) end diff --git a/do-release.sh b/do-release.sh index a9ea48d7e0..03807ce8b9 100755 --- a/do-release.sh +++ b/do-release.sh @@ -204,6 +204,7 @@ echo echo "Tag has been pushed.... now check github actions: " echo echo "Now wait, until first stage of the release is finished successfully..." +echo "You don't need to wait until artifacts are in maven central, just the github action must be successful." echo echo "If it is failing, you can fix the code/scripts and force push the tag via" echo @@ -245,9 +246,6 @@ ${NEW_RELEASE_NOTES} ${OLD_RELEASE_NOTES}" > docs/pages/release_notes_old.md -# update release_notes_pmd7 with prerendered version (jdoc tags are replaced with released version) -echo "$RELEASE_NOTES_PMD7" > docs/pages/release_notes_pmd7.md - # reset release notes template cat > docs/pages/release_notes.md <" +echo "* Post this also into :" +echo " PMD ${RELEASE_VERSION} released: https://github.com/pmd/pmd/releases/tag/pmd_releases/${RELEASE_VERSION} #PMD" echo echo echo "Now waiting for the release to be finished..." diff --git a/docs/_config.yml b/docs/_config.yml index 6740ca0c9f..f53795d99a 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,9 +1,9 @@ repository: pmd/pmd pmd: - version: 7.1.0-SNAPSHOT - previous_version: 7.0.0 - date: 26-April-2024 + version: 7.2.0-SNAPSHOT + previous_version: 7.1.0 + date: 31-May-2024 release_type: minor # release types: major, minor, bugfix diff --git a/docs/images/logo/PMD_small.svg b/docs/images/logo/PMD_small.svg new file mode 100644 index 0000000000..6782d8aaa7 --- /dev/null +++ b/docs/images/logo/PMD_small.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/logo/favicon.ico b/docs/images/logo/favicon.ico index bd9e18f2a0..83d19f9d36 100644 Binary files a/docs/images/logo/favicon.ico and b/docs/images/logo/favicon.ico differ diff --git a/docs/images/logo/pmd-logo-small-300px.png b/docs/images/logo/pmd-logo-small-300px.png new file mode 100644 index 0000000000..ec14c45994 Binary files /dev/null and b/docs/images/logo/pmd-logo-small-300px.png differ diff --git a/docs/images/logo/pmd-logo-small-64px.png b/docs/images/logo/pmd-logo-small-64px.png new file mode 100644 index 0000000000..50a153c7b2 Binary files /dev/null and b/docs/images/logo/pmd-logo-small-64px.png differ diff --git a/docs/images/logo/pmd-logo-small-white-300px.png b/docs/images/logo/pmd-logo-small-white-300px.png new file mode 100644 index 0000000000..24a4550d58 Binary files /dev/null and b/docs/images/logo/pmd-logo-small-white-300px.png differ diff --git a/docs/images/logo/pmd-logo-small-white-64px.png b/docs/images/logo/pmd-logo-small-white-64px.png new file mode 100644 index 0000000000..11f8d529ca Binary files /dev/null and b/docs/images/logo/pmd-logo-small-white-64px.png differ diff --git a/docs/pages/pmd/projectdocs/committers/releasing.md b/docs/pages/pmd/projectdocs/committers/releasing.md index caa058dfec..ab36fbdea3 100644 --- a/docs/pages/pmd/projectdocs/committers/releasing.md +++ b/docs/pages/pmd/projectdocs/committers/releasing.md @@ -2,7 +2,7 @@ title: Release process permalink: pmd_projectdocs_committers_releasing.html author: Romain Pelisse , Andreas Dangel -last_updated: April 2021 +last_updated: April 2024 --- This page describes the current status of the release process. @@ -72,13 +72,13 @@ in order to release version "6.34.0", the configuration should look like this: ```yaml pmd: - version: 6.34.0 - previous_version: 6.33.0 - date: 24-April-2021 + version: 7.2.0 + previous_version: 7.1.0 + date: 31-May-2024 release_type: minor ``` -The release type could be one of "bugfix" (e.g. 6.34.x), "minor" (6.x.0), or "major" (x.0.0). +The release type could be one of "bugfix" (e.g. 7.1.x), "minor" (7.x.0), or "major" (x.0.0). The release notes usually mention any new rules that have been added since the last release. @@ -88,7 +88,7 @@ Add the new rules as comments to the quickstart rulesets: The designer lives at [pmd/pmd-designer](https://github.com/pmd/pmd-designer). Update property `pmd-designer.version` in **pom.xml** to reference the new version, that will be released -shortly. Note: This version does at the moment not exist. That means, that a full build of the sources +shortly. Note: This new version does at the moment not exist. That means, that a full build of the sources will currently fail. That's why the first phase of the release will build only pmd-core and languages but not pmd-cli and pmd-dist. @@ -97,13 +97,14 @@ Then we can skip the release of pmd-designer and immediately start the second ph 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 +on GitHub with the title of the new release is searched. It is important, that the due date of the milestone +is correctly set, as the returned milestones in the API call are sorted by due date. +Make sure, there is such 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.33.0 -NEW_VERSION=6.34.0 +LAST_VERSION=7.1.0 +NEW_VERSION=7.2.0 NEW_VERSION_COMMITISH=HEAD echo "### Stats" @@ -129,14 +130,14 @@ The new version needs to be entered into `_config.yml`, e.g.: ```yaml pmd: - latestVersion: 6.34.0 - latestVersionDate: 24-April-2021 + latestVersion: 7.2.0 + latestVersionDate: 31-May-2024 ``` Also move the previous version down into the "downloads" section. We usually keep only the last 3 versions in this list, so remove the oldest version. -Then create a new page for the new release, e.g. `_posts/2021-04-24-PMD-6.34.0.md` and copy +Then create a new page for the new release, e.g. `_posts/2024-05-31-PMD-7.2.0.md` and copy the release notes into this page. This will appear under the news section. Note: The release notes typically contain some Jekyll macros for linking to the rule pages. These macros won't @@ -164,7 +165,7 @@ Check in all (version, blog post) changes to branch master: The actual release is done by changing the versions, creating a tag and pushing this tag. Previously this was done by calling _maven-release-plugin_, but these steps are done without the plugin to have more control. And since we -might reference a not yet released pmd-designer version, the test-build will fail. +might reference a not yet released pmd-designer version, the test-build would fail. We first change the version of PMD and all modules by basically removing the "-SNAPSHOT" suffix, building the changed project locally with tests (and with skipping pmd-cli and pmd-dist) in order to be sure, everything is in working @@ -176,8 +177,8 @@ next snapshot version after the release. Skipping the builds of pmd-cli and pmd- the property `skip-cli-dist`. ```shell -RELEASE_VERSION=6.34.0 -DEVELOPMENT_VERSION=6.35.0-SNAPSHOT +RELEASE_VERSION=7.2.0 +DEVELOPMENT_VERSION=7.3.0-SNAPSHOT # Change version in the POMs to ${RELEASE_VERSION} and update build timestamp ./mvnw --quiet versions:set -DnewVersion="${RELEASE_VERSION}" -DgenerateBackupPoms=false -DupdateBuildOutputTimestampPolicy=always # Transform the SCM information in the POM @@ -218,18 +219,18 @@ Here is, what happens: * Render the documentation in `docs/` with `bundle exec jekyll build` and create a zip file from it. * Upload the doc zip file to the current (draft) GitHub Release under and to . -* Upload the documentation to , e.g. and +* Upload the documentation to , e.g. and create a symlink, so that points to the new version. -* Remove the old snapshot documentation, e.g. so that is gone. - Also create a symlink from pmd-doc-6.34.0-SNAPSHOT to pmd-doc-6.34.0, so that old references still work, e.g. - points to the released version. +* Remove the old snapshot documentation, e.g. so that is gone. + Also create a symlink from pmd-doc-7.2.0-SNAPSHOT to pmd-doc-7.2.0, so that old references still work, e.g. + points to the released version. * Deploy javadoc to "https://docs.pmd-code.org/apidocs/*/RELEASE_VERSION/", e.g. - . This is done for all modules. -* Remove old javadoc for the SNAPSHOT version, e.g. delete . + . This is done for all modules. +* Remove old javadoc for the SNAPSHOT version, e.g. delete . * Create a draft news post on for the new release. This contains the rendered release notes. * Copy the documentation to sourceforge's web space, so that it is available as - . All previously copied versions are listed + . All previously copied versions are listed under . The release on GitHub Actions currently takes about 30-45 minutes. Once this is done, you @@ -271,6 +272,7 @@ Tweet on , eg.: PMD 6.34.0 released: https://github.com/pmd/pmd/releases/tag/pmd_releases/6.34.0 #PMD +* Post the same twitter message into the gitter chat at ### Checklist @@ -289,6 +291,7 @@ Tweet on , eg.: | regression-tester | New release baseline is uploaded | | | | mailing list | announcement on mailing list is sent | | | | twitter | tweet about the new release | | | +| gitter | message about the new release | | | ## Prepare the next release @@ -302,9 +305,9 @@ There are a couple of manual steps needed to prepare the current main branch for ```yaml pmd: - version: 6.35.0-SNAPSHOT - previous_version: 6.34.0 - date: ??-??-2021 + version: 7.3.0-SNAPSHOT + previous_version: 7.2.0 + date: ??-??-2024 release_type: minor ``` @@ -329,13 +332,13 @@ This is a {{ site.pmd.release_type }} release. {% tocmaker %} -### New and noteworthy +### 🚀 New and noteworthy -### Fixed Issues +### 🐛 Fixed Issues -### API Changes +### 🚨 API Changes -### External Contributions +### ✨ External Contributions {% endtocmaker %} @@ -368,15 +371,11 @@ from there. Then merge into the `master` branch and release from there. This way automatically the latest release on and on sourceforge. -### (Optional) Create a new release branch +### (Optional) Create a new maintenance branch At some point, it might be time for a new maintenance branch. Such a branch is usually created from -the `master` branch. Here are the steps: +the tag. Here are the steps: -* Create a new branch: `git branch pmd/5.6.x master` -* Update the version in both the new branch and master, e.g. `mvn versions:set -DnewVersion=5.6.1-SNAPSHOT` - and `mvn versions:set -DnewVersion=5.7.0-SNAPSHOT`. -* Update the release notes on both the new branch and master - -The maintenance or bugfix branch could also be created later when needed from the actual tag. Then only the version on -the maintenance branch needs to be set. +* Create a new branch: `git branch pmd/7.1.x pmd_releases/7.1.0` +* Update the version in both the new branch, e.g. `mvn versions:set -DnewVersion=7.1.1-SNAPSHOT`. +* Update the release notes on both the new branch diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index 0e6b9270e0..9855a0bacd 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -81,558 +81,567 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Andro72
Andro72

🐛 Andrwyw
Andrwyw

🐛 Andrés Catalán
Andrés Catalán

🐛 + Andy Goossens
Andy Goossens

🐛 Andy Pattenden
Andy Pattenden

🐛 Andy Ray
Andy Ray

🐛 Andy Robinson
Andy Robinson

🐛 - Andy-2639
Andy-2639

🐛 + Andy-2639
Andy-2639

🐛 Ankush Somani
Ankush Somani

🐛 Anmol Kumar
Anmol Kumar

🐛 Anthony Whitford
Anthony Whitford

🐛 AnthonyKot
AnthonyKot

🐛 Aravind Hegde
Aravind Hegde

🐛 Arda Aslan
Arda Aslan

🐛 - Ari Fogel
Ari Fogel

🐛 + Ari Fogel
Ari Fogel

🐛 Arnaud Jeansen
Arnaud Jeansen

💻 🐛 Arpit Koolwal
Arpit Koolwal

🐛 Artem
Artem

💻 🐛 Artem
Artem

🐛 Artem Sheremet
Artem Sheremet

🐛 Artur
Artur

🐛 - Artur Bosch
Artur Bosch

🐛 + Artur Bosch
Artur Bosch

🐛 Artur Dryomov
Artur Dryomov

🐛 Artur Ossowski
Artur Ossowski

🐛 AshTheMash
AshTheMash

🐛 Ashish Rana
Ashish Rana

🐛 Atul Kaushal
Atul Kaushal

🐛 August Boland
August Boland

🐛 - Aurel Hudec
Aurel Hudec

🐛 + Aurel Hudec
Aurel Hudec

🐛 Austin
Austin

🐛 Austin Shalit
Austin Shalit

🐛 Austin Tice
Austin Tice

🐛 Ayoub Kaanich
Ayoub Kaanich

🐛 BBG
BBG

💻 📖 🐛 Bailey Tjiong
Bailey Tjiong

💻 - Barthélemy L.
Barthélemy L.

🐛 + Barthélemy L.
Barthélemy L.

🐛 Basavaraj K N
Basavaraj K N

🐛 Basil Peace
Basil Peace

🐛 Belle
Belle

🐛 Ben Lerner
Ben Lerner

🐛 Ben Manes
Ben Manes

🐛 Ben McCann
Ben McCann

🐛 - Bendegúz Nagy
Bendegúz Nagy

🐛 + Bendegúz Nagy
Bendegúz Nagy

🐛 Bennet S Yee
Bennet S Yee

🐛 Benoit Lacelle
Benoit Lacelle

🐛 Bernardo Macêdo
Bernardo Macêdo

🐛 Bernd Farka
Bernd Farka

🐛 Betina Cynthia Mamani
Betina Cynthia Mamani

🐛 Bhanu Prakash Pamidi
Bhanu Prakash Pamidi

💻 🐛 - Bhargav Thanki
Bhargav Thanki

🐛 + Bhargav Thanki
Bhargav Thanki

🐛 Binu R J
Binu R J

🐛 Björn Kautler
Björn Kautler

💻 🐛 Blightbuster
Blightbuster

🐛 Bo Zhang
Bo Zhang

🐛 Bob "Wombat" Hogg
Bob "Wombat" Hogg

🐛 Bobby Wertman
Bobby Wertman

🐛 - Bolarinwa Saheed Olayemi
Bolarinwa Saheed Olayemi

💻 🐛 + Bolarinwa Saheed Olayemi
Bolarinwa Saheed Olayemi

💻 🐛 Boris Petrov
Boris Petrov

🐛 Brad Kent
Brad Kent

🐛 Brandon Mikeska
Brandon Mikeska

🐛 Brian Batronis
Brian Batronis

🐛 Brian Johnson
Brian Johnson

🐛 Brice Dutheil
Brice Dutheil

💻 🐛 - Bruno Ferreira
Bruno Ferreira

🐛 + Bruno Ferreira
Bruno Ferreira

🐛 Bruno Harbulot
Bruno Harbulot

🐛 Bruno Ritz
Bruno Ritz

🐛 + BurovnikovEvgeniy
BurovnikovEvgeniy

🐛 Cameron Donaldson
Cameron Donaldson

🐛 Carlos Macasaet
Carlos Macasaet

🐛 Carsten Otto
Carsten Otto

🐛 - Charlie Housh
Charlie Housh

🐛 - Charlie Jonas
Charlie Jonas

🐛 + Charlie Housh
Charlie Housh

🐛 + Charlie Jonas
Charlie Jonas

🐛 Chas Honton
Chas Honton

🐛 Chen Yang
Chen Yang

🐛 Chotu
Chotu

🐛 Chris Smith
Chris Smith

🐛 Chris Toomey
Chris Toomey

🐛 - Christian Hujer
Christian Hujer

🐛 - Christian Pontesegger
Christian Pontesegger

🐛 + Christian Hujer
Christian Hujer

🐛 + Christian Pontesegger
Christian Pontesegger

🐛 ChristianWulf
ChristianWulf

🐛 Christofer Dutz
Christofer Dutz

💻 Christoffer Anselm
Christoffer Anselm

🐛 Christophe Vidal
Christophe Vidal

🐛 Christopher Dancy
Christopher Dancy

🐛 - Clemens Prill
Clemens Prill

🐛 - Clint Chester
Clint Chester

💻 🐛 + Clemens Prill
Clemens Prill

🐛 + Clint Chester
Clint Chester

💻 🐛 Clément Fournier
Clément Fournier

💻 📖 🐛 🚧 Codacy Badger
Codacy Badger

🐛 Code-Nil
Code-Nil

🐛 ColColonCleaner
ColColonCleaner

🐛 Colin Ingarfield
Colin Ingarfield

🐛 - Craig Andrews
Craig Andrews

🐛 - Craig Muchinsky
Craig Muchinsky

🐛 + Craig Andrews
Craig Andrews

🐛 + Craig Muchinsky
Craig Muchinsky

🐛 Cyril
Cyril

💻 🐛 Dale
Dale

💻 Damien Jiang
Damien Jiang

🐛 Dan Berindei
Dan Berindei

🐛 Dan Rollo
Dan Rollo

🐛 - Dan Ziemba
Dan Ziemba

🐛 - Daniel Gredler
Daniel Gredler

💻 🐛 + Dan Ziemba
Dan Ziemba

🐛 + Daniel Gredler
Daniel Gredler

💻 🐛 Daniel Jipa
Daniel Jipa

🐛 Daniel Paul Searles
Daniel Paul Searles

💻 Daniel Reigada
Daniel Reigada

🐛 Danilo Pianini
Danilo Pianini

🐛 Darko
Darko

🐛 - David
David

🐛 - David Atkinson
David Atkinson

🐛 + David
David

🐛 + David Atkinson
David Atkinson

🐛 David Burström
David Burström

💻 🐛 David Goaté
David Goaté

🐛 David Golpira
David Golpira

🐛 David Kovařík
David Kovařík

🐛 David M. Karr (fullname at gmail.com)
David M. Karr (fullname at gmail.com)

🐛 - David Renz
David Renz

💻 🐛 - David Renz
David Renz

🐛 + David Renz
David Renz

💻 🐛 + David Renz
David Renz

🐛 Dawid Ciok
Dawid Ciok

🐛 💻 Debamoy Datta
Debamoy Datta

💻 Deleted user
Deleted user

🐛 Dell Green
Dell Green

🐛 Dem Pilafian
Dem Pilafian

🐛 - Den
Den

🐛 - Denis Borovikov
Denis Borovikov

💻 🐛 + Den
Den

🐛 + Denis Borovikov
Denis Borovikov

💻 🐛 Dennie Reniers
Dennie Reniers

💻 🐛 Dennis Kieselhorst
Dennis Kieselhorst

🐛 Derek P. Moore
Derek P. Moore

🐛 Dichotomia
Dichotomia

🐛 Dionisio Cortés Fernández
Dionisio Cortés Fernández

💻 🐛 - Dmitri Bourlatchkov
Dmitri Bourlatchkov

🐛 - Dmitriy Kuzmin
Dmitriy Kuzmin

🐛 + Dmitri Bourlatchkov
Dmitri Bourlatchkov

🐛 + Dmitriy Kuzmin
Dmitriy Kuzmin

🐛 Dmytro Dashenkov
Dmytro Dashenkov

🐛 + Dr. Christian Kohlschütter
Dr. Christian Kohlschütter

🐛 Drew Hall
Drew Hall

🐛 Dumitru Postoronca
Dumitru Postoronca

🐛 Dylan Adams
Dylan Adams

🐛 + + Eden Hao
Eden Hao

🐛 Edward Klimoshenko
Edward Klimoshenko

🐛 💻 Egor Bredikhin
Egor Bredikhin

🐛 - - Elan P. Kugelmass
Elan P. Kugelmass

🐛 Elder S.
Elder S.

🐛 Eldrick Wega
Eldrick Wega

📖 Emile
Emile

🐛 + + Eric
Eric

🐛 Eric Kintzer
Eric Kintzer

🐛 Eric Perret
Eric Perret

🐛 - - Eric Squires
Eric Squires

🐛 Erich L Foster
Erich L Foster

🐛 Erik Bleske
Erik Bleske

🐛 Erik C. Thauvin
Erik C. Thauvin

📖 + + Ernst Reissner
Ernst Reissner

🐛 Ewan Tempero
Ewan Tempero

🐛 F.W. Dekker
F.W. Dekker

🐛 - - FSchliephacke
FSchliephacke

🐛 Facundo
Facundo

🐛 Federico Giust
Federico Giust

🐛 Fedor Sherstobitov
Fedor Sherstobitov

🐛 + + Felix Lampe
Felix Lampe

🐛 Filip Golonka
Filip Golonka

🐛 Filipe Esperandio
Filipe Esperandio

💻 🐛 - - Filippo Nova
Filippo Nova

🐛 Francesco la Torre
Francesco la Torre

🐛 Francisco Duarte
Francisco Duarte

🐛 Frieder Bluemle
Frieder Bluemle

🐛 + + Frits Jalvingh
Frits Jalvingh

💻 🐛 G. Bazior
G. Bazior

🐛 Gabe Henkes
Gabe Henkes

🐛 - - Gary Gregory
Gary Gregory

🐛 Genoud Magloire
Genoud Magloire

🐛 Geoffrey555
Geoffrey555

🐛 Georg Romstorfer
Georg Romstorfer

🐛 + + Gio
Gio

🐛 Gol
Gol

🐛 Gonzalo Exequiel Ibars Ingman
Gonzalo Exequiel Ibars Ingman

💻 🐛 - - GooDer
GooDer

🐛 Gregor Riegler
Gregor Riegler

🐛 Grzegorz Olszewski
Grzegorz Olszewski

🐛 Gunther Schrijvers
Gunther Schrijvers

💻 🐛 + + Gustavo Krieger
Gustavo Krieger

🐛 Guy Elsmore-Paddock
Guy Elsmore-Paddock

🐛 Görkem Mülayim
Görkem Mülayim

🐛 - - Hanzel Godinez
Hanzel Godinez

🐛 Haoliang Chen
Haoliang Chen

🐛 Harsh Kukreja
Harsh Kukreja

🐛 Hassan ALAMI
Hassan ALAMI

🐛 + + Heber
Heber

🐛 Henning Schmiedehausen
Henning Schmiedehausen

💻 🐛 Henning von Bargen
Henning von Bargen

💻 - - Hervé Boutemy
Hervé Boutemy

🐛 Himanshu Pandey
Himanshu Pandey

🐛 Hokwang Lee
Hokwang Lee

🐛 Hooperbloob
Hooperbloob

💻 + + Hung PHAN
Hung PHAN

🐛 IDoCodingStuffs
IDoCodingStuffs

💻 🐛 Iccen Gan
Iccen Gan

🐛 - - Ignacio Mariano Tirabasso
Ignacio Mariano Tirabasso

🐛 Igor Melnichenko
Igor Melnichenko

🐛 Igor Moreno
Igor Moreno

🐛 Intelesis-MS
Intelesis-MS

🐛 - Iroha_
Iroha_

🐛 - Ishan Srivastava
Ishan Srivastava

🐛 - Ivano Guerini
Ivano Guerini

🐛 + Iroha_
Iroha_

🐛 + Ishan Srivastava
Ishan Srivastava

🐛 + Ivan Vakhrushev
Ivan Vakhrushev

🐛 + Ivano Guerini
Ivano Guerini

🐛 Ivar Andreas Bonsaksen
Ivar Andreas Bonsaksen

🐛 Ivo Šmíd
Ivo Šmíd

🐛 JJengility
JJengility

🐛 + + Jake Hemmerle
Jake Hemmerle

🐛 James Harrison
James Harrison

🐛 💻 Jan
Jan

🐛 Jan Aertgeerts
Jan Aertgeerts

💻 🐛 - - Jan Brümmer
Jan Brümmer

🐛 Jan Tříska
Jan Tříska

🐛 Jan-Lukas Else
Jan-Lukas Else

🐛 + + Jason Qiu
Jason Qiu

💻 📖 Jason Williams
Jason Williams

🐛 Jean-Paul Mayer
Jean-Paul Mayer

🐛 Jean-Simon Larochelle
Jean-Simon Larochelle

🐛 - - Jeff Bartolotta
Jeff Bartolotta

💻 🐛 Jeff Hube
Jeff Hube

💻 🐛 Jeff Jensen
Jeff Jensen

🐛 + + Jeff May
Jeff May

🐛 Jens Gerdes
Jens Gerdes

🐛 Jeroen Borgers
Jeroen Borgers

🐛 💻 📢 Jeroen van Wilgenburg
Jeroen van Wilgenburg

📖 - - Jerome Russ
Jerome Russ

🐛 JerritEic
JerritEic

💻 📖 🐛 Jiri Pejchal
Jiri Pejchal

🐛 + + Jithin Sunny
Jithin Sunny

🐛 Jiří Škorpil
Jiří Škorpil

🐛 Joao Machado
Joao Machado

🐛 Jochen Krauss
Jochen Krauss

🐛 - - Johan Hammar
Johan Hammar

🐛 John Karp
John Karp

🐛 John Zhang
John Zhang

🐛 + + John-Teng
John-Teng

💻 🐛 Jon Moroney
Jon Moroney

💻 🐛 Jonas Geiregat
Jonas Geiregat

🐛 Jonathan Wiesel
Jonathan Wiesel

💻 🐛 - - Jordan
Jordan

🐛 Jordi Llach
Jordi Llach

🐛 Jorge Solórzano
Jorge Solórzano

🐛 + + JorneVL
JorneVL

🐛 Jose Palafox
Jose Palafox

🐛 Jose Stovall
Jose Stovall

🐛 Joseph
Joseph

💻 - - Joseph Heenan
Joseph Heenan

🐛 Josh Feingold
Josh Feingold

💻 🐛 Josh Holthaus
Josh Holthaus

🐛 + + Joshua S Arquilevich
Joshua S Arquilevich

🐛 João Dinis Ferreira
João Dinis Ferreira

📖 João Ferreira
João Ferreira

💻 🐛 João Pedro Schmitt
João Pedro Schmitt

🐛 - - Juan Martín Sotuyo Dodero
Juan Martín Sotuyo Dodero

💻 📖 🐛 🚧 Juan Pablo Civile
Juan Pablo Civile

🐛 Julian Voronetsky
Julian Voronetsky

🐛 + + Julien
Julien

🐛 Julius
Julius

🐛 JustPRV
JustPRV

🐛 Jörn Huxhorn
Jörn Huxhorn

🐛 - - KThompso
KThompso

🐛 Kai Amundsen
Kai Amundsen

🐛 Karel Vervaeke
Karel Vervaeke

🐛 + + Karl-Andero Mere
Karl-Andero Mere

🐛 Karl-Philipp Richter
Karl-Philipp Richter

🐛 Karsten Silz
Karsten Silz

🐛 Kazuma Watanabe
Kazuma Watanabe

🐛 - - Kev
Kev

🐛 Keve Müller
Keve Müller

🐛 Kevin Guerra
Kevin Guerra

💻 + + Kevin Jones
Kevin Jones

🐛 💻 Kevin Wayne
Kevin Wayne

🐛 Kieran Black
Kieran Black

🐛 Kirill Zubov
Kirill Zubov

🐛 - - Kirk Clemens
Kirk Clemens

💻 🐛 Klaus Hartl
Klaus Hartl

🐛 Koen Van Looveren
Koen Van Looveren

🐛 + + Kris Scheibe
Kris Scheibe

💻 🐛 Krystian Dabrowski
Krystian Dabrowski

🐛 💻 Kunal Thanki
Kunal Thanki

🐛 LaLucid
LaLucid

💻 - - Larry Diamond
Larry Diamond

💻 🐛 Lars Knickrehm
Lars Knickrehm

🐛 Laurent Bovet
Laurent Bovet

🐛 💻 + + Leo Gutierrez
Leo Gutierrez

🐛 LiGaOg
LiGaOg

💻 Liam Sharp
Liam Sharp

🐛 Lintsi
Lintsi

🐛 - - Linus Fernandes
Linus Fernandes

🐛 Lixon Lookose
Lixon Lookose

🐛 Logesh
Logesh

🐛 - Lorenzo Gabriele
Lorenzo Gabriele

🐛 - Loïc Ledoyen
Loïc Ledoyen

🐛 - Lucas Silva
Lucas Silva

🐛 - Lucas Soncini
Lucas Soncini

💻 🐛 + Lorenzo Gabriele
Lorenzo Gabriele

🐛 + Loïc Ledoyen
Loïc Ledoyen

🐛 + Lucas
Lucas

🐛 + Lucas Silva
Lucas Silva

🐛 + Lucas Soncini
Lucas Soncini

💻 🐛 Luis Alcantar
Luis Alcantar

💻 Lukasz Slonina
Lukasz Slonina

🐛 + + Lukebray
Lukebray

🐛 Lynn
Lynn

💻 🐛 Lyor Goldstein
Lyor Goldstein

🐛 MCMicS
MCMicS

🐛 Macarse
Macarse

🐛 - - Machine account for PMD
Machine account for PMD

💻 Maciek Siemczyk
Maciek Siemczyk

🐛 + + Maikel Steneker
Maikel Steneker

💻 🐛 Maksim Moiseikin
Maksim Moiseikin

🐛 Manfred Koch
Manfred Koch

🐛 Manuel Moya Ferrer
Manuel Moya Ferrer

💻 🐛 Manuel Ryan
Manuel Ryan

🐛 - - Marat Vyshegorodtsev
Marat Vyshegorodtsev

🐛 Marcel Härle
Marcel Härle

🐛 + + Marcello Fialho
Marcello Fialho

🐛 Marcin Dąbrowski
Marcin Dąbrowski

💻 Marcin Rataj
Marcin Rataj

🐛 Marcono1234
Marcono1234

🐛 Mark Adamcin
Mark Adamcin

🐛 - - Mark Hall
Mark Hall

💻 🐛 Mark Kolich
Mark Kolich

🐛 + + Mark Pritchard
Mark Pritchard

🐛 Markus Rathgeb
Markus Rathgeb

🐛 Marquis Wang
Marquis Wang

🐛 MartGit
MartGit

🐛 Martin Feldsztejn
Martin Feldsztejn

🐛 - - Martin Lehmann
Martin Lehmann

🐛 Martin Spamer
Martin Spamer

🐛 + + Martin Tarjányi
Martin Tarjányi

🐛 MatFl
MatFl

🐛 Mateusz Stefanski
Mateusz Stefanski

🐛 Mathieu Gouin
Mathieu Gouin

🐛 MatiasComercio
MatiasComercio

💻 🐛 - - Matt Benson
Matt Benson

🐛 Matt De Poorter
Matt De Poorter

🐛 + + Matt Hargett
Matt Hargett

💻 💵 Matt Harrah
Matt Harrah

🐛 Matt Nelson
Matt Nelson

🐛 Matthew Amos
Matthew Amos

🐛 Matthew Duggan
Matthew Duggan

🐛 - - Matthew Hall
Matthew Hall

🐛 Matías Fraga
Matías Fraga

💻 🐛 + + Maxime Robert
Maxime Robert

💻 🐛 MetaBF
MetaBF

🐛 Michael
Michael

🐛 Michael Bell
Michael Bell

🐛 Michael Bernstein
Michael Bernstein

🐛 - - Michael Clay
Michael Clay

🐛 Michael Dombrowski
Michael Dombrowski

🐛 + + Michael Hausegger
Michael Hausegger

🐛 Michael Hoefer
Michael Hoefer

🐛 Michael Kolesnikov
Michael Kolesnikov

🐛 Michael Möbius
Michael Möbius

🐛 Michael N. Lipp
Michael N. Lipp

🐛 - - Michael Pellegrini
Michael Pellegrini

🐛 Michal Kordas
Michal Kordas

🐛 + + Michał Borek
Michał Borek

🐛 Michał Kuliński
Michał Kuliński

🐛 Miguel Núñez Díaz-Montes
Miguel Núñez Díaz-Montes

🐛 Mihai Ionut
Mihai Ionut

🐛 Mikhail Kuchma
Mikhail Kuchma

🐛 + Mirek Hankus
Mirek Hankus

🐛 + Mitch Spano
Mitch Spano

🐛 - Mirek Hankus
Mirek Hankus

🐛 Mladjan Gadzic
Mladjan Gadzic

🐛 MrAngry52
MrAngry52

🐛 Muminur Choudhury
Muminur Choudhury

🐛 Mykhailo Palahuta
Mykhailo Palahuta

💻 🐛 Nagendra Kumar Singh
Nagendra Kumar Singh

🐛 Nahuel Barrios
Nahuel Barrios

🐛 + Nakul Sharma
Nakul Sharma

🐛 - Nakul Sharma
Nakul Sharma

🐛 Nathan Braun
Nathan Braun

🐛 Nathan Reynolds
Nathan Reynolds

🐛 Nathan Reynolds
Nathan Reynolds

🐛 Nathanaël
Nathanaël

🐛 Naveen
Naveen

💻 Nazdravi
Nazdravi

🐛 + Neha-Dhonde
Neha-Dhonde

🐛 - Neha-Dhonde
Neha-Dhonde

🐛 Nicholas Doyle
Nicholas Doyle

🐛 Nick Butcher
Nick Butcher

🐛 Nico Gallinal
Nico Gallinal

🐛 Nicola Dal Maso
Nicola Dal Maso

🐛 Nicolas Filotto
Nicolas Filotto

💻 Nicolas Vervelle
Nicolas Vervelle

🐛 + Nicolas Vuillamy
Nicolas Vuillamy

📖 - Nicolas Vuillamy
Nicolas Vuillamy

📖 Nikita Chursin
Nikita Chursin

🐛 Niklas Baudy
Niklas Baudy

🐛 Nikolas Havrikov
Nikolas Havrikov

🐛 Nilesh Virkar
Nilesh Virkar

🐛 Nimit Patel
Nimit Patel

🐛 Niranjan Harpale
Niranjan Harpale

🐛 + Nirvik Patel
Nirvik Patel

💻 - Nirvik Patel
Nirvik Patel

💻 Noah Sussman
Noah Sussman

🐛 Noah0120
Noah0120

🐛 Noam Tamim
Noam Tamim

🐛 Noel Grandin
Noel Grandin

🐛 Olaf Haalstra
Olaf Haalstra

🐛 Oleg Andreych
Oleg Andreych

💻 🐛 + Oleg Pavlenko
Oleg Pavlenko

🐛 - Oleg Pavlenko
Oleg Pavlenko

🐛 Oleksii Dykov
Oleksii Dykov

💻 🐛 Oliver Eikemeier
Oliver Eikemeier

🐛 Oliver Siegmar
Oliver Siegmar

💵 Olivier Parent
Olivier Parent

💻 🐛 Ollie Abbey
Ollie Abbey

💻 🐛 OverDrone
OverDrone

🐛 + Ozan Gulle
Ozan Gulle

💻 🐛 - Ozan Gulle
Ozan Gulle

💻 🐛 PUNEET JAIN
PUNEET JAIN

🐛 Parbati Bose
Parbati Bose

🐛 Paul Berg
Paul Berg

🐛 Paul Guyot
Paul Guyot

💻 Pavel Bludov
Pavel Bludov

🐛 Pavel Mička
Pavel Mička

🐛 + Pedro Nuno Santos
Pedro Nuno Santos

🐛 - Pedro Nuno Santos
Pedro Nuno Santos

🐛 Pedro Rijo
Pedro Rijo

🐛 Pelisse Romain
Pelisse Romain

💻 📖 🐛 Per Abich
Per Abich

💻 Pete Davids
Pete Davids

🐛 Peter Bruin
Peter Bruin

🐛 Peter Chittum
Peter Chittum

💻 🐛 + Peter Cudmore
Peter Cudmore

🐛 - Peter Cudmore
Peter Cudmore

🐛 Peter Kasson
Peter Kasson

🐛 Peter Kofler
Peter Kofler

🐛 Peter Paul Bakker
Peter Paul Bakker

💻 Peter Rader
Peter Rader

🐛 Pham Hai Trung
Pham Hai Trung

🐛 Philip Graf
Philip Graf

💻 🐛 + Philip Hachey
Philip Hachey

🐛 - Philip Hachey
Philip Hachey

🐛 Philippe Ozil
Philippe Ozil

🐛 Phinehas Artemix
Phinehas Artemix

🐛 Phokham Nonava
Phokham Nonava

🐛 Pim van der Loos
Pim van der Loos

💻 ⚠️ Piotr Szymański
Piotr Szymański

🐛 Piotrek Żygieło
Piotrek Żygieło

💻 🐛 📖 + Pranay Jaiswal
Pranay Jaiswal

🐛 - Pranay Jaiswal
Pranay Jaiswal

🐛 Prasad Kamath
Prasad Kamath

🐛 Prasanna
Prasanna

🐛 Presh-AR
Presh-AR

🐛 Puneet1726
Puneet1726

🐛 Rafael Cortês
Rafael Cortês

🐛 RaheemShaik999
RaheemShaik999

🐛 + RajeshR
RajeshR

💻 🐛 - RajeshR
RajeshR

💻 🐛 Ramachandra Mohan
Ramachandra Mohan

🐛 Ramel0921
Ramel0921

🐛 Raquel Pau
Raquel Pau

🐛 Ravikiran Janardhana
Ravikiran Janardhana

🐛 Reda Benhemmouche
Reda Benhemmouche

🐛 + Reinhard Schiedermeier
Reinhard Schiedermeier

🐛 Renato Oliveira
Renato Oliveira

💻 🐛 @@ -776,289 +785,290 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Vincent Maurin
Vincent Maurin

🐛 Vincent Privat
Vincent Privat

🐛 Vishhwas
Vishhwas

🐛 + Vishv_Android
Vishv_Android

🐛 Vitaly
Vitaly

🐛 - Vitaly Polonetsky
Vitaly Polonetsky

🐛 + Vitaly Polonetsky
Vitaly Polonetsky

🐛 Vojtech Polivka
Vojtech Polivka

🐛 Vsevolod Zholobov
Vsevolod Zholobov

🐛 Vyom Yadav
Vyom Yadav

💻 Wang Shidong
Wang Shidong

🐛 Waqas Ahmed
Waqas Ahmed

🐛 Wayne J. Earl
Wayne J. Earl

🐛 - Wchenghui
Wchenghui

🐛 + Wchenghui
Wchenghui

🐛 Wener
Wener

💻 Will Winder
Will Winder

🐛 William Brockhus
William Brockhus

💻 🐛 Wilson Kurniawan
Wilson Kurniawan

🐛 Wim Deblauwe
Wim Deblauwe

🐛 Woongsik Choi
Woongsik Choi

🐛 - XenoAmess
XenoAmess

💻 🐛 + XenoAmess
XenoAmess

💻 🐛 Yang
Yang

💻 YaroslavTER
YaroslavTER

🐛 Yasar Shaikh
Yasar Shaikh

💻 Young Chan
Young Chan

💻 🐛 YuJin Kim
YuJin Kim

🐛 Yuri Dolzhenko
Yuri Dolzhenko

🐛 - Yurii Dubinka
Yurii Dubinka

🐛 + Yurii Dubinka
Yurii Dubinka

🐛 Zoltan Farkas
Zoltan Farkas

🐛 Zustin
Zustin

🐛 aaronhurst-google
aaronhurst-google

🐛 💻 alexmodis
alexmodis

🐛 andreoss
andreoss

🐛 andrey81inmd
andrey81inmd

💻 🐛 - anicoara
anicoara

🐛 + anicoara
anicoara

🐛 arunprasathav
arunprasathav

🐛 asiercamara
asiercamara

🐛 astillich-igniti
astillich-igniti

💻 avesolovksyy
avesolovksyy

🐛 avishvat
avishvat

🐛 avivmu
avivmu

🐛 - axelbarfod1
axelbarfod1

🐛 + axelbarfod1
axelbarfod1

🐛 b-3-n
b-3-n

🐛 balbhadra9
balbhadra9

🐛 base23de
base23de

🐛 bergander
bergander

🐛 💻 berkam
berkam

💻 🐛 breizh31
breizh31

🐛 - caesarkim
caesarkim

🐛 + caesarkim
caesarkim

🐛 carolyujing
carolyujing

🐛 cbfiddle
cbfiddle

🐛 cesares-basilico
cesares-basilico

🐛 chrite
chrite

🐛 ciufudean
ciufudean

📖 cobratbq
cobratbq

🐛 - coladict
coladict

🐛 + coladict
coladict

🐛 cosmoJFH
cosmoJFH

🐛 cristalp
cristalp

🐛 crunsk
crunsk

🐛 cwholmes
cwholmes

🐛 cyberjj999
cyberjj999

🐛 cyw3
cyw3

🐛 📖 - d1ss0nanz
d1ss0nanz

🐛 + d1ss0nanz
d1ss0nanz

🐛 dague1
dague1

📖 dalizi007
dalizi007

💻 danbrycefairsailcom
danbrycefairsailcom

🐛 dariansanity
dariansanity

🐛 darrenmiliband
darrenmiliband

🐛 davidburstrom
davidburstrom

🐛 - dbirkman-paloalto
dbirkman-paloalto

🐛 + dbirkman-paloalto
dbirkman-paloalto

🐛 deepak-patra
deepak-patra

🐛 dependabot[bot]
dependabot[bot]

💻 🐛 dinesh150
dinesh150

🐛 diziaq
diziaq

🐛 dreaminpast123
dreaminpast123

🐛 duanyanan
duanyanan

🐛 - dutt-sanjay
dutt-sanjay

🐛 + dutt-sanjay
dutt-sanjay

🐛 dylanleung
dylanleung

🐛 dzeigler
dzeigler

🐛 eant60
eant60

🐛 ekkirala
ekkirala

🐛 emersonmoura
emersonmoura

🐛 emouty
emouty

💻 - eugenepugach
eugenepugach

🐛 + eugenepugach
eugenepugach

🐛 fairy
fairy

🐛 filiprafalowicz
filiprafalowicz

💻 flxbl-io
flxbl-io

💵 foxmason
foxmason

🐛 frankegabor
frankegabor

🐛 frankl
frankl

🐛 - freafrea
freafrea

🐛 + freafrea
freafrea

🐛 fsapatin
fsapatin

🐛 gracia19
gracia19

🐛 guo fei
guo fei

🐛 gurmsc5
gurmsc5

🐛 gwilymatgearset
gwilymatgearset

💻 🐛 haigsn
haigsn

🐛 - hemanshu070
hemanshu070

🐛 + hemanshu070
hemanshu070

🐛 henrik242
henrik242

🐛 hongpuwu
hongpuwu

🐛 hvbtup
hvbtup

💻 🐛 igniti GmbH
igniti GmbH

🐛 ilovezfs
ilovezfs

🐛 itaigilo
itaigilo

🐛 - jakivey32
jakivey32

🐛 + jakivey32
jakivey32

🐛 jbennett2091
jbennett2091

🐛 jcamerin
jcamerin

🐛 jkeener1
jkeener1

🐛 jmetertea
jmetertea

🐛 johnra2
johnra2

💻 josemanuelrolon
josemanuelrolon

💻 🐛 - kabroxiko
kabroxiko

💻 🐛 + kabroxiko
kabroxiko

💻 🐛 karwer
karwer

🐛 kaulonline
kaulonline

🐛 kdaemonv
kdaemonv

🐛 kdebski85
kdebski85

🐛 💻 kenji21
kenji21

💻 🐛 kfranic
kfranic

🐛 - khalidkh
khalidkh

🐛 + khalidkh
khalidkh

🐛 koalalam
koalalam

🐛 krzyk
krzyk

🐛 lasselindqvist
lasselindqvist

🐛 lgemeinhardt
lgemeinhardt

🐛 lihuaib
lihuaib

🐛 liqingjun123
liqingjun123

🐛 - lonelyma1021
lonelyma1021

🐛 + lonelyma1021
lonelyma1021

🐛 lpeddy
lpeddy

🐛 lujiefsi
lujiefsi

💻 lukelukes
lukelukes

💻 lyriccoder
lyriccoder

🐛 marcelmore
marcelmore

🐛 matchbox
matchbox

🐛 - matthiaskraaz
matthiaskraaz

🐛 + matthiaskraaz
matthiaskraaz

🐛 meandonlyme
meandonlyme

🐛 mikesive
mikesive

🐛 milossesic
milossesic

🐛 mluckam
mluckam

💻 mohan-chinnappan-n
mohan-chinnappan-n

💻 mriddell95
mriddell95

🐛 - mrlzh
mrlzh

🐛 + mrlzh
mrlzh

🐛 msloan
msloan

🐛 mucharlaravalika
mucharlaravalika

🐛 mvenneman
mvenneman

🐛 nareshl119
nareshl119

🐛 nicolas-harraudeau-sonarsource
nicolas-harraudeau-sonarsource

🐛 noerremark
noerremark

🐛 - novsirion
novsirion

🐛 + novsirion
novsirion

🐛 nwcm
nwcm

📖 🐛 💻 oggboy
oggboy

🐛 oinume
oinume

🐛 orimarko
orimarko

💻 🐛 pacvz
pacvz

💻 pallavi agarwal
pallavi agarwal

🐛 - parksungrin
parksungrin

🐛 + parksungrin
parksungrin

🐛 patpatpat123
patpatpat123

🐛 patriksevallius
patriksevallius

🐛 pbrajesh1
pbrajesh1

🐛 phoenix384
phoenix384

🐛 piotrszymanski-sc
piotrszymanski-sc

💻 plan3d
plan3d

🐛 - poojasix
poojasix

🐛 + poojasix
poojasix

🐛 prabhushrikant
prabhushrikant

🐛 pujitha8783
pujitha8783

🐛 r-r-a-j
r-r-a-j

🐛 raghujayjunk
raghujayjunk

🐛 rajeshveera
rajeshveera

🐛 rajeswarreddy88
rajeswarreddy88

🐛 - recdevs
recdevs

🐛 + recdevs
recdevs

🐛 reudismam
reudismam

💻 🐛 rijkt
rijkt

🐛 rillig-tk
rillig-tk

🐛 rmohan20
rmohan20

💻 🐛 rnveach
rnveach

🐛 rxmicro
rxmicro

🐛 - ryan-gustafson
ryan-gustafson

💻 🐛 + ryan-gustafson
ryan-gustafson

💻 🐛 sabi0
sabi0

🐛 scais
scais

🐛 screamingfrog
screamingfrog

💵 sebbASF
sebbASF

🐛 sergeygorbaty
sergeygorbaty

💻 shilko2013
shilko2013

🐛 - shiomiyan
shiomiyan

📖 + shiomiyan
shiomiyan

📖 simeonKondr
simeonKondr

🐛 snajberk
snajberk

🐛 sniperrifle2004
sniperrifle2004

🐛 snuyanzin
snuyanzin

🐛 💻 soyodream
soyodream

🐛 sratz
sratz

🐛 - stonio
stonio

🐛 + stonio
stonio

🐛 sturton
sturton

💻 🐛 sudharmohan
sudharmohan

🐛 suruchidawar
suruchidawar

🐛 svenfinitiv
svenfinitiv

🐛 tashiscool
tashiscool

🐛 test-git-hook
test-git-hook

🐛 - testation21
testation21

💻 🐛 + testation21
testation21

💻 🐛 thanosa
thanosa

🐛 tiandiyixian
tiandiyixian

🐛 tobwoerk
tobwoerk

🐛 tprouvot
tprouvot

🐛 💻 trentchilders
trentchilders

🐛 triandicAnt
triandicAnt

🐛 - trishul14
trishul14

🐛 + trishul14
trishul14

🐛 tsui
tsui

🐛 wangzitom12306
wangzitom12306

🐛 winhkey
winhkey

🐛 witherspore
witherspore

🐛 wjljack
wjljack

🐛 wuchiuwong
wuchiuwong

🐛 - xingsong
xingsong

🐛 + xingsong
xingsong

🐛 xioayuge
xioayuge

🐛 xnYi9wRezm
xnYi9wRezm

💻 🐛 xuanuy
xuanuy

🐛 xyf0921
xyf0921

🐛 yalechen-cyw3
yalechen-cyw3

🐛 yasuharu-sato
yasuharu-sato

🐛 - zenglian
zenglian

🐛 + zenglian
zenglian

🐛 zgrzyt93
zgrzyt93

💻 🐛 zh3ng
zh3ng

🐛 zt_soft
zt_soft

🐛 ztt79
ztt79

🐛 zzzzfeng
zzzzfeng

🐛 Árpád Magosányi
Árpád Magosányi

🐛 - 任贵杰
任贵杰

🐛 + 任贵杰
任贵杰

🐛 茅延安
茅延安

💻 diff --git a/docs/pages/pmd/projectdocs/logo.md b/docs/pages/pmd/projectdocs/logo.md index 3838039f8e..2230b37c37 100644 --- a/docs/pages/pmd/projectdocs/logo.md +++ b/docs/pages/pmd/projectdocs/logo.md @@ -24,7 +24,13 @@ The following PMD Logos and Icons are licensed under [CC BY 4.0](https://creativ * [Logo (600px, white)](images/logo/pmd-logo-white-600px.png) * [Logo (600px, white, suqare shape)](images/logo/pmd-logo-white-600px-squared.png) -* [Favicon (16x16)](images/logo/favicon.ico) +Small variants, square shaped: +* [PMD_small.svg](images/logo/PMD_small.svg) +* [Small Logo (64px, transparent)](images/logo/pmd-logo-small-64px.png) +* [Small Logo (64px, white)](images/logo/pmd-logo-small-white-64px.png) +* [Small Logo (300px, transparent)](images/logo/pmd-logo-small-300px.png) +* [Small Logo (300px, white)](images/logo/pmd-logo-small-white-300px.png) +* [Favicon (32x32)](images/logo/favicon.ico) This new greenish logo was introduced with PMD 7. diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 3d9784465e..31376368ca 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -24,70 +24,15 @@ Since this release, PMD will also expose any getter returning a collection of an /UserClass[@InterfaceNames = 'Queueable'] ``` -### ✨ New rules - -- The new Java rule {%rule java/bestpractices/UnnecessaryVarargsArrayCreation %} reports explicit array creation - when a varargs is expected. This is more heavy to read and could be simplified. - -### 🌟 Rule Changes - -* {%rule java/bestpractices/JUnitTestsShouldIncludeAssert %} and {% rule java/bestpractices/JUnitTestContainsTooManyAsserts %} - have a new property named `extraAssertMethodNames`. With this property, you can configure which additional static - methods should be considered as valid verification methods. This allows to use custom mocking or assertion libraries. - ### 🐛 Fixed Issues -* core - * [#494](https://github.com/pmd/pmd/issues/494): \[core] Adopt JApiCmp to enforce control over API changes - * [#4942](https://github.com/pmd/pmd/issues/4942): \[core] CPD: `--skip-duplicate-files` has no effect (7.0.0 regression) - * [#4959](https://github.com/pmd/pmd/pull/4959): \[core] Upgrade saxon to 12.4 -* cli - * [#4791](https://github.com/pmd/pmd/issues/4791): \[cli] Could not find or load main class - * [#4913](https://github.com/pmd/pmd/issues/4913): \[cli] cpd-gui closes immediately -* doc - * [#4901](https://github.com/pmd/pmd/issues/4901): \[doc] Improve documentation on usage of violationSuppressXPath -* apex - * [#4418](https://github.com/pmd/pmd/issues/4418): \[apex] ASTAnnotation.getImage() does not return value as written in the class -* apex-errorprone - * [#3953](https://github.com/pmd/pmd/issues/3953): \[apex] EmptyCatchBlock false positive with formal (doc) comments -* java - * [#4899](https://github.com/pmd/pmd/issues/4899): \[java] Parsing failed in ParseLock#doParse() java.io.IOException: Stream closed - * [#4902](https://github.com/pmd/pmd/issues/4902): \[java] "Bad intersection, unrelated class types" for Constable\[] and Enum\[] - * [#4947](https://github.com/pmd/pmd/issues/4947): \[java] Broken TextBlock parser + * java-bestpractices - * [#1084](https://github.com/pmd/pmd/issues/1084): \[java] Allow JUnitTestsShouldIncludeAssert to configure verification methods - * [#3216](https://github.com/pmd/pmd/issues/3216): \[java] New rule: UnnecessaryVarargsArrayCreation - * [#4435](https://github.com/pmd/pmd/issues/4435): \[java] \[7.0-rc1] UnusedAssignment for used field - * [#4569](https://github.com/pmd/pmd/issues/4569): \[java] ForLoopCanBeForeach reports on loop `for (int i = 0; i < list.size(); i += 2)` - * [#4618](https://github.com/pmd/pmd/issues/4618): \[java] UnusedAssignment false positive with conditional assignments of fields -* java-codestyle - * [#4602](https://github.com/pmd/pmd/issues/4602): \[java] UnnecessaryImport: false positives with static imports - * [#4785](https://github.com/pmd/pmd/issues/4785): \[java] False Positive: PMD Incorrectly report violation for UnnecessaryImport - * [#4779](https://github.com/pmd/pmd/issues/4779): \[java] Examples in documentation of MethodArgumentCanBeFinal do not trigger the rule - * [#4881](https://github.com/pmd/pmd/issues/4881): \[java] ClassNamingConventions: interfaces are identified as abstract classes (regression in 7.0.0) -* java-design - * [#2440](https://github.com/pmd/pmd/issues/2440): \[java] FinalFieldCouldBeStatic FN when the right side of the assignment is a constant expression - * [#3694](https://github.com/pmd/pmd/issues/3694): \[java] SingularField ignores static variables - * [#4873](https://github.com/pmd/pmd/issues/4873): \[java] AvoidCatchingGenericException: Can no longer suppress on the exception itself -* java-errorprone - * [#2056](https://github.com/pmd/pmd/issues/2056): \[java] CloseResource false-positive with URLClassLoader in cast expression - * [#4928](https://github.com/pmd/pmd/issues/4928): \[java] EmptyCatchBlock false negative when allowCommentedBlocks=true -* java-performance - * [#3845](https://github.com/pmd/pmd/issues/3845): \[java] InsufficientStringBufferDeclaration should consider literal expression - * [#4874](https://github.com/pmd/pmd/issues/4874): \[java] StringInstantiation: False-positive when using `new String(charArray)` - * [#4886](https://github.com/pmd/pmd/issues/4886): \[java] BigIntegerInstantiation: False Positive with Java 17 and BigDecimal.TWO -* pom-errorprone - * [#4388](https://github.com/pmd/pmd/issues/4388): \[pom] InvalidDependencyTypes doesn't consider dependencies at all + * [#4278](https://github.com/pmd/pmd/issues/4278): \[java] UnusedPrivateMethod FP with Junit 5 @MethodSource and default factory method name + * [#4975](https://github.com/pmd/pmd/issues/4975): \[java] UnusedPrivateMethod false positive when using @MethodSource on a @Nested test ### 🚨 API Changes -#### Deprecated methods - -* {%jdoc java::lang.java.rule.design.SingularFieldRule#mayBeSingular(java::lang.java.ast.ModifierOwner) %} has been deprecated for - removal. The method is only useful for the rule itself and shouldn't be used otherwise. - ### ✨ External Contributions -* [#4864](https://github.com/pmd/pmd/pull/4864): Fix #1084 \[Java] add extra assert method names to Junit rules - [Erwan Moutymbo](https://github.com/emouty) (@emouty) -* [#4894](https://github.com/pmd/pmd/pull/4894): Fix #4791 Error caused by space in JDK path - [Scrates1](https://github.com/Scrates1) (@Scrates1) {% endtocmaker %} diff --git a/docs/pages/release_notes_old.md b/docs/pages/release_notes_old.md index 2fedec6996..b4eaab15bd 100644 --- a/docs/pages/release_notes_old.md +++ b/docs/pages/release_notes_old.md @@ -5,6 +5,113 @@ permalink: pmd_release_notes_old.html Previous versions of PMD can be downloaded here: [Releases - pmd/pmd (GitHub)](https://github.com/pmd/pmd/releases) +## 26-April-2024 - 7.1.0 + +The PMD team is pleased to announce PMD 7.1.0. + +This is a minor release. + +### Table Of Contents + +* [🚀 New and noteworthy](#new-and-noteworthy) + * [More robust CPD reports](#more-robust-cpd-reports) + * [✨ New Rules](#new-rules) + * [🌟 Rule Changes](#rule-changes) +* [🐛 Fixed Issues](#fixed-issues) +* [🚨 API Changes](#api-changes) + * [Deprecated methods](#deprecated-methods) +* [✨ External Contributions](#external-contributions) +* [📈 Stats](#stats) + +### 🚀 New and noteworthy + +#### More robust CPD reports +There were a number of circumstances, specially around (but not limited to) literal sequences, were CPD would +report duplicate overlapping or partially overlapping matches. These have now been fixed, and CPD will report +only the longest non-overlapping duplicate. + +These improvements apply to all supported languages, irrespective of supported flags. + +#### ✨ New Rules +- The new Java rule [`UnnecessaryVarargsArrayCreation`](https://docs.pmd-code.org/pmd-doc-7.1.0/pmd_rules_java_bestpractices.html#unnecessaryvarargsarraycreation) reports explicit array creation + when a varargs is expected. This is more heavy to read and could be simplified. +- The new Java rule [`ConfusingArgumentToVarargsMethod`](https://docs.pmd-code.org/pmd-doc-7.1.0/pmd_rules_java_errorprone.html#confusingargumenttovarargsmethod) reports some confusing situations + where a varargs method is called with an inexact argument type. These may end up in a mismatch between the expected + parameter type and the actual value. +- The new Java rule [`LambdaCanBeMethodReference`](https://docs.pmd-code.org/pmd-doc-7.1.0/pmd_rules_java_codestyle.html#lambdacanbemethodreference) reports lambda expressions that can be replaced + with a method reference. Please read the documentation of the rule for more info. This rule is now part of the Quickstart + ruleset. + +#### 🌟 Rule Changes +* [`JUnitTestsShouldIncludeAssert`](https://docs.pmd-code.org/pmd-doc-7.1.0/pmd_rules_java_bestpractices.html#junittestsshouldincludeassert) and [`JUnitTestContainsTooManyAsserts`](https://docs.pmd-code.org/pmd-doc-7.1.0/pmd_rules_java_bestpractices.html#junittestcontainstoomanyasserts) + have a new property named `extraAssertMethodNames`. With this property, you can configure which additional static + methods should be considered as valid verification methods. This allows to use custom mocking or assertion libraries. + +### 🐛 Fixed Issues +* core + * [#494](https://github.com/pmd/pmd/issues/494): \[core] Adopt JApiCmp to enforce control over API changes + * [#4942](https://github.com/pmd/pmd/issues/4942): \[core] CPD: `--skip-duplicate-files` has no effect (7.0.0 regression) + * [#4959](https://github.com/pmd/pmd/pull/4959): \[core] Upgrade saxon to 12.4 +* cli + * [#4791](https://github.com/pmd/pmd/issues/4791): \[cli] Could not find or load main class + * [#4913](https://github.com/pmd/pmd/issues/4913): \[cli] cpd-gui closes immediately +* doc + * [#4901](https://github.com/pmd/pmd/issues/4901): \[doc] Improve documentation on usage of violationSuppressXPath +* apex + * [#4418](https://github.com/pmd/pmd/issues/4418): \[apex] ASTAnnotation.getImage() does not return value as written in the class +* apex-errorprone + * [#3953](https://github.com/pmd/pmd/issues/3953): \[apex] EmptyCatchBlock false positive with formal (doc) comments +* cpp + * [#2438](https://github.com/pmd/pmd/issues/2438): \[cpp] Repeated Duplication blocks +* java + * [#4899](https://github.com/pmd/pmd/issues/4899): \[java] Parsing failed in ParseLock#doParse() java.io.IOException: Stream closed + * [#4902](https://github.com/pmd/pmd/issues/4902): \[java] "Bad intersection, unrelated class types" for Constable\[] and Enum\[] + * [#4947](https://github.com/pmd/pmd/issues/4947): \[java] Broken TextBlock parser +* java-bestpractices + * [#1084](https://github.com/pmd/pmd/issues/1084): \[java] Allow JUnitTestsShouldIncludeAssert to configure verification methods + * [#3216](https://github.com/pmd/pmd/issues/3216): \[java] New rule: UnnecessaryVarargsArrayCreation + * [#4435](https://github.com/pmd/pmd/issues/4435): \[java] \[7.0-rc1] UnusedAssignment for used field + * [#4569](https://github.com/pmd/pmd/issues/4569): \[java] ForLoopCanBeForeach reports on loop `for (int i = 0; i < list.size(); i += 2)` + * [#4618](https://github.com/pmd/pmd/issues/4618): \[java] UnusedAssignment false positive with conditional assignments of fields +* java-codestyle + * [#4602](https://github.com/pmd/pmd/issues/4602): \[java] UnnecessaryImport: false positives with static imports + * [#4785](https://github.com/pmd/pmd/issues/4785): \[java] False Positive: PMD Incorrectly report violation for UnnecessaryImport + * [#4779](https://github.com/pmd/pmd/issues/4779): \[java] Examples in documentation of MethodArgumentCanBeFinal do not trigger the rule + * [#4881](https://github.com/pmd/pmd/issues/4881): \[java] ClassNamingConventions: interfaces are identified as abstract classes (regression in 7.0.0) +* java-design + * [#2440](https://github.com/pmd/pmd/issues/2440): \[java] FinalFieldCouldBeStatic FN when the right side of the assignment is a constant expression + * [#3694](https://github.com/pmd/pmd/issues/3694): \[java] SingularField ignores static variables + * [#4873](https://github.com/pmd/pmd/issues/4873): \[java] AvoidCatchingGenericException: Can no longer suppress on the exception itself +* java-errorprone + * [#2056](https://github.com/pmd/pmd/issues/2056): \[java] CloseResource false-positive with URLClassLoader in cast expression + * [#4751](https://github.com/pmd/pmd/issues/4751): \[java] PMD crashes when analyzing CloseResource Rule + * [#4928](https://github.com/pmd/pmd/issues/4928): \[java] EmptyCatchBlock false negative when allowCommentedBlocks=true + * [#4948](https://github.com/pmd/pmd/issues/4948): \[java] ImplicitSwitchFallThrough: False-positive with nested switch statements +* java-performance + * [#3845](https://github.com/pmd/pmd/issues/3845): \[java] InsufficientStringBufferDeclaration should consider literal expression + * [#4874](https://github.com/pmd/pmd/issues/4874): \[java] StringInstantiation: False-positive when using `new String(charArray)` + * [#4886](https://github.com/pmd/pmd/issues/4886): \[java] BigIntegerInstantiation: False Positive with Java 17 and BigDecimal.TWO +* pom-errorprone + * [#4388](https://github.com/pmd/pmd/issues/4388): \[pom] InvalidDependencyTypes doesn't consider dependencies at all +* misc + * [#4967](https://github.com/pmd/pmd/pull/4967): Fix reproducible build issues with 7.0.0 + +### 🚨 API Changes +#### Deprecated methods +* pmd-java + * ASTLambdaExpression#getBlock and ASTLambdaExpression#getExpression + * SingularFieldRule#mayBeSingular has been deprecated for + removal. The method is only useful for the rule itself and shouldn't be used otherwise. + +### ✨ External Contributions +* [#4864](https://github.com/pmd/pmd/pull/4864): Fix #1084 \[Java] add extra assert method names to Junit rules - [Erwan Moutymbo](https://github.com/emouty) (@emouty) +* [#4894](https://github.com/pmd/pmd/pull/4894): Fix #4791 Error caused by space in JDK path - [Scrates1](https://github.com/Scrates1) (@Scrates1) + +### 📈 Stats +* 205 commits +* 71 closed tickets & PRs +* Days since last release: 34 + ## 22-March-2024 - 7.0.0 diff --git a/docs/pages/release_notes_pmd7.md b/docs/pages/release_notes_pmd7.md index 3b7f58f544..b8024d9779 100644 --- a/docs/pages/release_notes_pmd7.md +++ b/docs/pages/release_notes_pmd7.md @@ -492,13 +492,13 @@ If you import rules, you also need to adjust the paths, e.g. new property `forbiddenRegex` can be used now to define the disallowed terms with a single regular expression. * [`CommentRequired`](https://docs.pmd-code.org/pmd-doc-7.0.0/pmd_rules_java_documentation.html#commentrequired): - * Overridden methods are now detected even without the `@Override` - annotation. This is relevant for the property `methodWithOverrideCommentRequirement`. - See also [pull request #3757](https://github.com/pmd/pmd/pull/3757). - * Elements in annotation types are now detected as well. This might lead to an increased number of violations - for missing public method comments. - * The deprecated property `headerCommentRequirement` has been removed. Use the property `classCommentRequirement` - instead. + * Overridden methods are now detected even without the `@Override` + annotation. This is relevant for the property `methodWithOverrideCommentRequirement`. + See also [pull request #3757](https://github.com/pmd/pmd/pull/3757). + * Elements in annotation types are now detected as well. This might lead to an increased number of violations + for missing public method comments. + * The deprecated property `headerCommentRequirement` has been removed. Use the property `classCommentRequirement` + instead. * [`CommentSize`](https://docs.pmd-code.org/pmd-doc-7.0.0/pmd_rules_java_documentation.html#commentsize): When determining the line-length of a comment, the leading comment prefix markers (e.g. `*` or `//`) are ignored and don't add up to the line-length. See also [pull request #4369](https://github.com/pmd/pmd/pull/4369). @@ -738,13 +738,13 @@ See [ADR 3 - API evolution principles](pmd_projectdocs_decisions_adr_3.html) and This includes ClasspathClassLoader, FileFinder, FileUtil, and IOUtil. * The following utility classes in net.sourceforge.pmd.util are now considered public API: - * AssertionUtil - * CollectionUtil - * ContextedAssertionError - * ContextedStackOverflowError - * GraphUtil - * IteratorUtil - * StringUtil + * AssertionUtil + * CollectionUtil + * ContextedAssertionError + * ContextedStackOverflowError + * GraphUtil + * IteratorUtil + * StringUtil * Moved the two classes AntlrCpdLexer and JavaccCpdLexer from `internal` package into package net.sourceforge.pmd.cpd.impl. These two classes are part of the API and @@ -829,9 +829,9 @@ The metrics framework has been made simpler and more general. ### Testing framework * PMD 7 has been upgraded to use JUnit 5 only. That means, that JUnit4 related classes have been removed, namely - * `net.sourceforge.pmd.testframework.PMDTestRunner` - * `net.sourceforge.pmd.testframework.RuleTestRunner` - * `net.sourceforge.pmd.testframework.TestDescriptor` + * `net.sourceforge.pmd.testframework.PMDTestRunner` + * `net.sourceforge.pmd.testframework.RuleTestRunner` + * `net.sourceforge.pmd.testframework.TestDescriptor` * Rule tests, that use SimpleAggregatorTst or PmdRuleTst work as before without change, but use now JUnit5 under the hood. If you added additional JUnit4 tests to your rule test classes, then you'll @@ -904,7 +904,7 @@ These are the changes between 7.0.0-rc4 and final 7.0.0. * Support for Java 20 preview language features have been removed. The version "20-preview" is no longer available. * ASTPattern, ASTRecordPattern, ASTTypePattern, ASTUnnamedPattern - - method `getParenthesisDepth()` has been removed. + - method `getParenthesisDepth()` has been removed. * ASTTemplateFragment: To get the content of the template, use now getContent or `@Content` instead of `getImage()`/`@Image`. * ASTUnnamedPattern is not experimental anymore. The language feature @@ -930,56 +930,56 @@ in the migration guide for details. **Moved classes/consolidated packages** * pmd-core - * Many types have been moved from the base package `net.sourceforge.pmd` into subpackage net.sourceforge.pmd.lang.rule - * Rule - * RulePriority - * RuleSet - * `RuleSetFactory` - * RuleSetLoader - * RuleSetLoadException - * RuleSetWriter - * Many types have been moved from the base package `net.sourceforge.pmd` into subpackage net.sourceforge.pmd.reporting - * Report - * RuleContext - * RuleViolation - * ViolationSuppressor - * XPathRule has been moved into subpackage net.sourceforge.pmd.lang.rule.xpath. + * Many types have been moved from the base package `net.sourceforge.pmd` into subpackage net.sourceforge.pmd.lang.rule + * Rule + * RulePriority + * RuleSet + * `RuleSetFactory` + * RuleSetLoader + * RuleSetLoadException + * RuleSetWriter + * Many types have been moved from the base package `net.sourceforge.pmd` into subpackage net.sourceforge.pmd.reporting + * Report + * RuleContext + * RuleViolation + * ViolationSuppressor + * XPathRule has been moved into subpackage net.sourceforge.pmd.lang.rule.xpath. * pmd-html - * `net.sourceforge.pmd.lang.html.ast.HtmlCpdLexer` moved into package `cpd`: HtmlCpdLexer. + * `net.sourceforge.pmd.lang.html.ast.HtmlCpdLexer` moved into package `cpd`: HtmlCpdLexer. * pmd-lang-test: All types have been moved under the new base package net.sourceforge.pmd.lang.test: - * AbstractMetricTestRule (moved from `net.sourceforge.pmd.test.AbstractMetricTestRule`) - * BaseTextComparisonTest (moved from `net.sourceforge.pmd.test.BaseTextComparisonTest`) - * CpdTextComparisonTest (moved from `net.sourceforge.pmd.cpd.test.CpdTextComparisonTest`) - * BaseTreeDumpTest (moved from `net.sourceforge.pmd.lang.ast.test.BaseTreeDumpTest`) - * And many other types have been moved from `net.sourceforge.pmd.lang.ast.test` to `net.sourceforge.pmd.lang.test`. + * AbstractMetricTestRule (moved from `net.sourceforge.pmd.test.AbstractMetricTestRule`) + * BaseTextComparisonTest (moved from `net.sourceforge.pmd.test.BaseTextComparisonTest`) + * CpdTextComparisonTest (moved from `net.sourceforge.pmd.cpd.test.CpdTextComparisonTest`) + * BaseTreeDumpTest (moved from `net.sourceforge.pmd.lang.ast.test.BaseTreeDumpTest`) + * And many other types have been moved from `net.sourceforge.pmd.lang.ast.test` to `net.sourceforge.pmd.lang.test`. * pmd-scala - * ScalaCpdLexer (moved from `net.sourceforge.pmd.lang.scala.cpd.ScalaCpdLexer`) - * ScalaTokenAdapter (moved from `net.sourceforge.pmd.lang.scala.cpd.ScalaTokenAdapter`) + * ScalaCpdLexer (moved from `net.sourceforge.pmd.lang.scala.cpd.ScalaCpdLexer`) + * ScalaTokenAdapter (moved from `net.sourceforge.pmd.lang.scala.cpd.ScalaTokenAdapter`) * pmd-test - * AbstractRuleSetFactoryTest (moved from `net.sourceforge.pmd.lang.rule.AbstractRuleSetFactoryTest`) - * AbstractAntTestHelper (moved from `net.sourceforge.pmd.ant.AbstractAntTestHelper`) - * AbstractLanguageVersionTest (moved from `net.sourceforge.pmd.AbstractLanguageVersionTest`) - * PmdRuleTst (moved from `net.sourceforge.pmd.testframework.PmdRuleTst`) - * RuleTst (moved from `net.sourceforge.pmd.testframework.RuleTst`) - * SimpleAggregatorTst (moved from `net.sourceforge.pmd.testframework.SimpleAggregatorTst`) + * AbstractRuleSetFactoryTest (moved from `net.sourceforge.pmd.lang.rule.AbstractRuleSetFactoryTest`) + * AbstractAntTestHelper (moved from `net.sourceforge.pmd.ant.AbstractAntTestHelper`) + * AbstractLanguageVersionTest (moved from `net.sourceforge.pmd.AbstractLanguageVersionTest`) + * PmdRuleTst (moved from `net.sourceforge.pmd.testframework.PmdRuleTst`) + * RuleTst (moved from `net.sourceforge.pmd.testframework.RuleTst`) + * SimpleAggregatorTst (moved from `net.sourceforge.pmd.testframework.SimpleAggregatorTst`) * pmd-xml - * PomLanguageModule (moved from `net.sourceforge.pmd.lang.pom.PomLanguageModule`) - * WsdlLanguageModule (moved from `net.sourceforge.pmd.lang.wsdl.WsdlLanguageModule`) - * XslLanguageModule (moved from `net.sourceforge.pmd.lang.xsl.XslLanguageModule`) + * PomLanguageModule (moved from `net.sourceforge.pmd.lang.pom.PomLanguageModule`) + * WsdlLanguageModule (moved from `net.sourceforge.pmd.lang.wsdl.WsdlLanguageModule`) + * XslLanguageModule (moved from `net.sourceforge.pmd.lang.xsl.XslLanguageModule`) * pmd-visualforce - * The package `net.sourceforge.pmd.lang.vf` has been renamed to net.sourceforge.pmd.lang.visualforce. - * The language id of visualforce has been changed to `visualforce` (it was previously just "vf") - * The ruleset changed: `category/vf/security.xml` ➡️ `category/visualforce/security.xml` + * The package `net.sourceforge.pmd.lang.vf` has been renamed to net.sourceforge.pmd.lang.visualforce. + * The language id of visualforce has been changed to `visualforce` (it was previously just "vf") + * The ruleset changed: `category/vf/security.xml` ➡️ `category/visualforce/security.xml` * pmd-velocity (renamed from pmd-vm) - * The package `net.sourceforge.pmd.lang.vm` has been renamed to net.sourceforge.pmd.lang.velocity. - * The language id of the Velocity module has been changed to `velocity` (it was previously just "vm") - * The rulesets changed: `category/vm/...` ➡️ `category/velocity/...` - * Many classes used the prefix `Vm`, e.g. `VmLanguageModule`. This has been changed to be `Vtl`: - * VtlLanguageModule - * VtlNode - * VtlParser - * VtlCpdLexer - * AbstractVtlRule + * The package `net.sourceforge.pmd.lang.vm` has been renamed to net.sourceforge.pmd.lang.velocity. + * The language id of the Velocity module has been changed to `velocity` (it was previously just "vm") + * The rulesets changed: `category/vm/...` ➡️ `category/velocity/...` + * Many classes used the prefix `Vm`, e.g. `VmLanguageModule`. This has been changed to be `Vtl`: + * VtlLanguageModule + * VtlNode + * VtlParser + * VtlCpdLexer + * AbstractVtlRule **Internalized classes and interfaces and methods** @@ -987,465 +987,465 @@ The following classes/methods have been marked as @InternalApi before an package or made (package) private and are _not accessible_ anymore. * pmd-core - * `net.sourceforge.pmd.cache.AbstractAnalysisCache` (moved to internal, now package private) - * `net.sourceforge.pmd.cache.AnalysisCache` (moved to internal) - * `net.sourceforge.pmd.cache.AnalysisCacheListener` (moved to internal) - * `net.sourceforge.pmd.cache.AnalysisResult` (moved to internal) - * `net.sourceforge.pmd.cache.CachedRuleMapper` (moved to internal, now package private) - * `net.sourceforge.pmd.cache.CachedRuleViolation` (moved to internal, now package private) - * `net.sourceforge.pmd.cache.ChecksumAware` (moved to internal) - * `net.sourceforge.pmd.cache.FileAnalysisCache` (moved to internal) - * `net.sourceforge.pmd.cache.NoopAnalysisCache` (moved to internal) - * `net.sourceforge.pmd.util.ResourceLoader` (moved to internal) - * net.sourceforge.pmd.cpd.Tokens - * Constructor is now package private. - * net.sourceforge.pmd.lang.LanguageProcessor.AnalysisTask - * Constructor is now package private. - * Method `withFiles(java.util.List)` is now package private. Note: it was not previously marked with @InternalApi. - * net.sourceforge.pmd.lang.rule.RuleTargetSelector - * Method `isRuleChain()` has been removed. - * net.sourceforge.pmd.renderers.AbstractAccumulatingRenderer - * renderFileReport - this method is now final - and can't be overridden anymore. - * net.sourceforge.pmd.reporting.Report - * Constructor as well as the methods `addRuleViolation`, `addConfigError`, `addError` are now private. - * net.sourceforge.pmd.reporting.RuleContext - * Method `getRule()` is now package private. - * Method `create(FileAnalysisListener listener, Rule rule)` has been removed. - * `net.sourceforge.pmd.rules.RuleFactory`: moved into subpackage `lang.rule` and made package private. - It has now been hidden completely from public API. - * Many types have been moved from into subpackage `lang.rule.internal`. - * `net.sourceforge.pmd.RuleSetReference` - * `net.sourceforge.pmd.RuleSetReferenceId` - * `net.sourceforge.pmd.RuleSets` - * `net.sourceforge.pmd.lang.rule.ParametricRuleViolation` is now package private and moved to `net.sourceforge.pmd.reporting.ParametricRuleViolation`. - The only public API is RuleViolation. - * net.sourceforge.pmd.lang.rule.RuleSet - * Method `applies(Rule,LanguageVersion)` is now package private. - * Method `applies(TextFile)` has been removed. - * Method `applies(FileId)` is now package private. - * net.sourceforge.pmd.lang.rule.RuleSetLoader - * Method `loadRuleSetsWithoutException(java.util.List)` is now package private. - * net.sourceforge.pmd.lang.rule.RuleSetLoadException - * All constructors are package private now. - * net.sourceforge.pmd.lang.ast.LexException - the constructor `LexException(boolean, String, int, int, String, char)` is now package private. - It is only used by JavaCC-generated token managers. - * net.sourceforge.pmd.PMDConfiguration - * Method `setAnalysisCache(AnalysisCache)` is now package private. Use setAnalysisCacheLocation instead. - * Method `getAnalysisCache()` is now package private. - * net.sourceforge.pmd.lang.document.FileCollector - * Method `newCollector(LanguageVersionDiscoverer, PmdReporter)` is now package private. - * Method `newCollector(PmdReporter)` is now package private. - * In order to create a FileCollector, use files instead. - * net.sourceforge.pmd.lang.rule.xpath.Attribute - * Method `replacementIfDeprecated()` is now package private. - * `net.sourceforge.pmd.properties.PropertyTypeId` - moved in subpackage `internal`. - * net.sourceforge.pmd.properties.PropertyDescriptor - method `getTypeId()` is now package private. + * `net.sourceforge.pmd.cache.AbstractAnalysisCache` (moved to internal, now package private) + * `net.sourceforge.pmd.cache.AnalysisCache` (moved to internal) + * `net.sourceforge.pmd.cache.AnalysisCacheListener` (moved to internal) + * `net.sourceforge.pmd.cache.AnalysisResult` (moved to internal) + * `net.sourceforge.pmd.cache.CachedRuleMapper` (moved to internal, now package private) + * `net.sourceforge.pmd.cache.CachedRuleViolation` (moved to internal, now package private) + * `net.sourceforge.pmd.cache.ChecksumAware` (moved to internal) + * `net.sourceforge.pmd.cache.FileAnalysisCache` (moved to internal) + * `net.sourceforge.pmd.cache.NoopAnalysisCache` (moved to internal) + * `net.sourceforge.pmd.util.ResourceLoader` (moved to internal) + * net.sourceforge.pmd.cpd.Tokens + * Constructor is now package private. + * net.sourceforge.pmd.lang.LanguageProcessor.AnalysisTask + * Constructor is now package private. + * Method `withFiles(java.util.List)` is now package private. Note: it was not previously marked with @InternalApi. + * net.sourceforge.pmd.lang.rule.RuleTargetSelector + * Method `isRuleChain()` has been removed. + * net.sourceforge.pmd.renderers.AbstractAccumulatingRenderer + * renderFileReport - this method is now final + and can't be overridden anymore. + * net.sourceforge.pmd.reporting.Report + * Constructor as well as the methods `addRuleViolation`, `addConfigError`, `addError` are now private. + * net.sourceforge.pmd.reporting.RuleContext + * Method `getRule()` is now package private. + * Method `create(FileAnalysisListener listener, Rule rule)` has been removed. + * `net.sourceforge.pmd.rules.RuleFactory`: moved into subpackage `lang.rule` and made package private. + It has now been hidden completely from public API. + * Many types have been moved from into subpackage `lang.rule.internal`. + * `net.sourceforge.pmd.RuleSetReference` + * `net.sourceforge.pmd.RuleSetReferenceId` + * `net.sourceforge.pmd.RuleSets` + * `net.sourceforge.pmd.lang.rule.ParametricRuleViolation` is now package private and moved to `net.sourceforge.pmd.reporting.ParametricRuleViolation`. + The only public API is RuleViolation. + * net.sourceforge.pmd.lang.rule.RuleSet + * Method `applies(Rule,LanguageVersion)` is now package private. + * Method `applies(TextFile)` has been removed. + * Method `applies(FileId)` is now package private. + * net.sourceforge.pmd.lang.rule.RuleSetLoader + * Method `loadRuleSetsWithoutException(java.util.List)` is now package private. + * net.sourceforge.pmd.lang.rule.RuleSetLoadException + * All constructors are package private now. + * net.sourceforge.pmd.lang.ast.LexException - the constructor `LexException(boolean, String, int, int, String, char)` is now package private. + It is only used by JavaCC-generated token managers. + * net.sourceforge.pmd.PMDConfiguration + * Method `setAnalysisCache(AnalysisCache)` is now package private. Use setAnalysisCacheLocation instead. + * Method `getAnalysisCache()` is now package private. + * net.sourceforge.pmd.lang.document.FileCollector + * Method `newCollector(LanguageVersionDiscoverer, PmdReporter)` is now package private. + * Method `newCollector(PmdReporter)` is now package private. + * In order to create a FileCollector, use files instead. + * net.sourceforge.pmd.lang.rule.xpath.Attribute + * Method `replacementIfDeprecated()` is now package private. + * `net.sourceforge.pmd.properties.PropertyTypeId` - moved in subpackage `internal`. + * net.sourceforge.pmd.properties.PropertyDescriptor - method `getTypeId()` is now package private. * pmd-doc - * The whole maven module `pmd-doc` is now considered internal API even though it was not declared so before. - It's used to generate the rule documentation for the built-in rules. - * All the classes have been moved into package `net.sourceforge.pmd.doc.internal`. + * The whole maven module `pmd-doc` is now considered internal API even though it was not declared so before. + It's used to generate the rule documentation for the built-in rules. + * All the classes have been moved into package `net.sourceforge.pmd.doc.internal`. * pmd-ant - * net.sourceforge.pmd.ant.Formatter - * Method `getRenderer()` has been removed. - * Method `start(String)` is private now. - * Method `end(Report)` has been removed. - * Method `isNoOutputSupplied()` is now package private. - * Method `newListener(Project)` is now package private. - * net.sourceforge.pmd.ant.PMDTask - * Method `getRelativizeRoots()` has been removed. - * `net.sourceforge.pmd.ant.ReportException` is now package private. Note: It was not marked with @InternalApi before. + * net.sourceforge.pmd.ant.Formatter + * Method `getRenderer()` has been removed. + * Method `start(String)` is private now. + * Method `end(Report)` has been removed. + * Method `isNoOutputSupplied()` is now package private. + * Method `newListener(Project)` is now package private. + * net.sourceforge.pmd.ant.PMDTask + * Method `getRelativizeRoots()` has been removed. + * `net.sourceforge.pmd.ant.ReportException` is now package private. Note: It was not marked with @InternalApi before. * pmd-apex - * net.sourceforge.pmd.lang.apex.ast.ApexNode - * Method `getNode()` has been removed. It was only deprecated before and not marked with @InternalApi. - However, it gave access to the wrapped Jorje node and was thus internal API. - * `net.sourceforge.pmd.lang.apex.ast.AbstractApexNode` - * Method `getNode()` is now package private. - * net.sourceforge.pmd.lang.apex.multifile.ApexMultifileAnalysis - * Constructor is now package private. - * `net.sourceforge.pmd.lang.apex.rule.design.AbstractNcssCountRule` (now package private) - * `net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule` (moved to package `net.sourceforge.pmd.apex.rule.bestpractices`, now package private) + * net.sourceforge.pmd.lang.apex.ast.ApexNode + * Method `getNode()` has been removed. It was only deprecated before and not marked with @InternalApi. + However, it gave access to the wrapped Jorje node and was thus internal API. + * `net.sourceforge.pmd.lang.apex.ast.AbstractApexNode` + * Method `getNode()` is now package private. + * net.sourceforge.pmd.lang.apex.multifile.ApexMultifileAnalysis + * Constructor is now package private. + * `net.sourceforge.pmd.lang.apex.rule.design.AbstractNcssCountRule` (now package private) + * `net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule` (moved to package `net.sourceforge.pmd.apex.rule.bestpractices`, now package private) * pmd-java - * `net.sourceforge.pmd.lang.java.rule.AbstractIgnoredAnnotationRule` (moved to internal) - * `net.sourceforge.pmd.lang.java.types.ast.LazyTypeResolver` (moved to internal) - * net.sourceforge.pmd.lang.java.types.JMethodSig - * Method `internalApi()` has been removed. - * net.sourceforge.pmd.lang.java.types.TypeOps - * Method `isSameTypeInInference(JTypeMirror,JTypeMirror)` is now package private. + * `net.sourceforge.pmd.lang.java.rule.AbstractIgnoredAnnotationRule` (moved to internal) + * `net.sourceforge.pmd.lang.java.types.ast.LazyTypeResolver` (moved to internal) + * net.sourceforge.pmd.lang.java.types.JMethodSig + * Method `internalApi()` has been removed. + * net.sourceforge.pmd.lang.java.types.TypeOps + * Method `isSameTypeInInference(JTypeMirror,JTypeMirror)` is now package private. * pmd-jsp - * net.sourceforge.pmd.lang.jsp.ast.JspParser - * Method `getTokenBehavior()` has been removed. + * net.sourceforge.pmd.lang.jsp.ast.JspParser + * Method `getTokenBehavior()` has been removed. * pmd-modelica - * net.sourceforge.pmd.lang.modelica.ast.InternalApiBridge renamed from `InternalModelicaNodeApi`. - * net.sourceforge.pmd.lang.modelica.resolver.InternalApiBridge renamed from `InternalModelicaResolverApi`. - * `net.sourceforge.pmd.lang.modelica.resolver.ModelicaSymbolFacade` has been removed. - * `net.sourceforge.pmd.lang.modelica.resolver.ResolutionContext` (moved to internal) - * `net.sourceforge.pmd.lang.modelica.resolver.ResolutionState` (moved to internal). Note: it was not previously marked with @InternalApi. - * `net.sourceforge.pmd.lang.modelica.resolver.Watchdog` (moved to internal). Note: it was not previously marked with @InternalApi. + * net.sourceforge.pmd.lang.modelica.ast.InternalApiBridge renamed from `InternalModelicaNodeApi`. + * net.sourceforge.pmd.lang.modelica.resolver.InternalApiBridge renamed from `InternalModelicaResolverApi`. + * `net.sourceforge.pmd.lang.modelica.resolver.ModelicaSymbolFacade` has been removed. + * `net.sourceforge.pmd.lang.modelica.resolver.ResolutionContext` (moved to internal) + * `net.sourceforge.pmd.lang.modelica.resolver.ResolutionState` (moved to internal). Note: it was not previously marked with @InternalApi. + * `net.sourceforge.pmd.lang.modelica.resolver.Watchdog` (moved to internal). Note: it was not previously marked with @InternalApi. * pmd-plsql - * `net.sourceforge.pmd.lang.plsql.rule.design.AbstractNcssCountRule` is now package private. + * `net.sourceforge.pmd.lang.plsql.rule.design.AbstractNcssCountRule` is now package private. * pmd-scala - * net.sourceforge.pmd.lang.scala.ScalaLanguageModule - * Method `dialectOf(LanguageVersion)` has been removed. + * net.sourceforge.pmd.lang.scala.ScalaLanguageModule + * Method `dialectOf(LanguageVersion)` has been removed. **Removed classes and members (previously deprecated)** The annotation `@DeprecatedUntil700` has been removed. * pmd-core - * CpdLanguageProperties. The field `DEFAULT_SKIP_BLOCKS_PATTERN` has been removed. - * BaseAntlrNode - method `joinTokenText()` has been removed. - * Node - many methods have been removed: - * `getNthParent(int)` - Use ancestors instead, e.g. `node.ancestors().get(n-1)` - * `getFirstParentOfType(Class)` - Use ancestors instead, e.g. `node.ancestors(parentType).first()` - * `getParentsOfType(Class)` - Use ancestors instead, e.g. `node.ancestors(parentType).toList()` - * `findChildrenOfType(Class)` - Use children instead, e.g. `node.children(childType).toList()` - * `findDescendantsOfType(Class)` - Use descendants instead, e.g. `node.descendants(targetType).toList()` - * `findDescendantsOfType(Class,boolean)` - Use descendants instead, e.g. `node.descendants(targetType).crossFindBoundaries(b).toList()` - * `getFirstChildOfType(Class)` - Use firstChild instead - * `getFirstDescendantOfType(Class)` - Use descendants instead, e.g. `node.descendants(targetType).first()` - * `hasDescendantOfType(Class)` - Use descendants instead, e.g. `node.descendants(targetType).nonEmpty()` - * `findChildNodesWithXPath(String)` - Use the NodeStream API instead. - * GenericNode - method `getNthParent(int)` has been removed. Use ancestors instead, e.g. `node.ancestors().get(n-1)` - * FileCollector - method `addZipFile(java.nio.file.Path)` has been removed. Use addZipFileWithContent instead - * TextDocument - method `readOnlyString(CharSequence,String,LanguageVersion)` has been removed. - Use readOnlyString instead. - * TextFile - method `dataSourceCompat(DataSource,PMDConfiguration)` has been removed. - Use TextFile directly, e.g. forPath - * XPathVersion - * `XPATH_1_0` - * `XPATH_1_0_COMPATIBILITY` - * `XPATH_2_0` - * Only XPath version 3.1 is now supported. This version of the XPath language is mostly identical to - XPath 2.0. XPath rules by default use now XPATH_3_1. - * `net.sourceforge.pmd.lang.rule.AbstractDelegateRule` removed. It has been merged with RuleReference. - * AbstractRule - the following methods have been removed: - * `deepCopyValuesTo(AbstractRule)` - use deepCopy instead. - * `addRuleChainVisit(Class)` - override buildTargetSelector in order to register nodes for rule chain visits. - * `addViolation(...)` - use addViolation instead, e.g. via `asCtx(data).addViolation(...)`. - Note: These methods were only marked as deprecated in javadoc. - * `addViolationWithMessage(...)` - use addViolationWithMessage instead, e.g. via - `asCtx(data).addViolationWithMessage(...)`. Note: These methods were only marked as deprecated in javadoc. - * RuleReference - the following methods have been removed: - * `setRuleSetReference(RuleSetReference)` - without replacement. Just construct new RuleReference instead. - * `hasOverriddenProperty(PropertyDescriptor)` - use isPropertyOverridden instead. - * XPathRule - * The constant `XPATH_DESCRIPTOR` has been made private and is not accessible anymore. - * The default constructor has been made package-private and is not accessible anymore. - * Language - method `getTerseName()` removed. Use getId instead. - * LanguageModuleBase - method `getTerseName()` removed. Use getId instead. - * LanguageRegistry - the following methods have been removed: - * `getLanguage(String)` - use getLanguageByFullName - via PMD or CPD instead. - * `findLanguageByTerseName(String)` - use getLanguageById - via PMD or CPD instead. - * `findByExtension(String)` - removed without replacement. - * LanguageVersionDiscoverer - method `getLanguagesForFile(java.io.File)` removed. - Use getLanguagesForFile instead. - * AbstractPropertySource - * field `propertyDescriptors` has been made private and is not accessible anymore. - Use getPropertyDescriptors instead. - * field `propertyValuesByDescriptor` has been made private and is not accessible anymore. - Use getPropertiesByPropertyDescriptor - or getOverriddenPropertiesByPropertyDescriptor instead. - * method `copyPropertyDescriptors()` has been removed. Use getPropertyDescriptors instead. - * method `copyPropertyValues()` has been removed. Use getPropertiesByPropertyDescriptor - or getOverriddenPropertiesByPropertyDescriptor instead. - * Reportable - the following methods have been removed. Use getReportLocation instead - * `getBeginLine()` - * `getBeginColumn()` - * `getEndLine()` - * `getEndColumn()` - * `net.sourceforge.pmd.util.datasource.DataSource` - use TextFile instead. - * `net.sourceforge.pmd.util.datasource.FileDataSource` - * `net.sourceforge.pmd.util.datasource.ReaderDataSource` - * `net.sourceforge.pmd.util.datasource.ZipDataSource` - * CollectionUtil - * method `invertedMapFrom(...)` has been removed. - * method `mapFrom(...)` has been removed. - * AbstractConfiguration - the following methods have been removed: - * `setIgnoreFilePath(String)` - use setIgnoreFilePath instead. - * `setInputFilePath(String)` - use setInputFilePath instead. - * `setInputPaths(String)` - use setInputPathList or - addInputPath instead. - * `setInputUri(String)` - use setInputUri instead. - * PMDConfiguration - the following methods have been removed - * `prependClasspath(String)` - use prependAuxClasspath instead. - * `getRuleSets()` - use getRuleSetPaths instead. - * `setRuleSets(String)` - use setRuleSets or - addRuleSet instead. - * `setReportFile(String)` - use setReportFile instead. - * `getReportFile()` - use getReportFilePath instead. - * Report - method `merge(Report)` has been removed. Use union instead. - * RuleSetLoader - method `toFactory()` has been made package private and is not accessible anymore. - * RuleViolation - the following methods have been removed: - * `getPackageName()` - use getAdditionalInfo with PACKAGE_NAME instead, e.g. `getAdditionalInfo().get(PACKAGE_NAME)`. - * `getClassName()` - use getAdditionalInfo with CLASS_NAME instead, e.g. `getAdditionalInfo().get(CLASS_NAME)`. - * `getMethodName()` - use getAdditionalInfo with METHOD_NAME instead, e.g. `getAdditionalInfo().get(METHOD_NAME)`. - * `getVariableName()` - use getAdditionalInfo with VARIABLE_NAME instead, e.g. `getAdditionalInfo().get(VARIABLE_NAME)`. + * CpdLanguageProperties. The field `DEFAULT_SKIP_BLOCKS_PATTERN` has been removed. + * BaseAntlrNode - method `joinTokenText()` has been removed. + * Node - many methods have been removed: + * `getNthParent(int)` - Use ancestors instead, e.g. `node.ancestors().get(n-1)` + * `getFirstParentOfType(Class)` - Use ancestors instead, e.g. `node.ancestors(parentType).first()` + * `getParentsOfType(Class)` - Use ancestors instead, e.g. `node.ancestors(parentType).toList()` + * `findChildrenOfType(Class)` - Use children instead, e.g. `node.children(childType).toList()` + * `findDescendantsOfType(Class)` - Use descendants instead, e.g. `node.descendants(targetType).toList()` + * `findDescendantsOfType(Class,boolean)` - Use descendants instead, e.g. `node.descendants(targetType).crossFindBoundaries(b).toList()` + * `getFirstChildOfType(Class)` - Use firstChild instead + * `getFirstDescendantOfType(Class)` - Use descendants instead, e.g. `node.descendants(targetType).first()` + * `hasDescendantOfType(Class)` - Use descendants instead, e.g. `node.descendants(targetType).nonEmpty()` + * `findChildNodesWithXPath(String)` - Use the NodeStream API instead. + * GenericNode - method `getNthParent(int)` has been removed. Use ancestors instead, e.g. `node.ancestors().get(n-1)` + * FileCollector - method `addZipFile(java.nio.file.Path)` has been removed. Use addZipFileWithContent instead + * TextDocument - method `readOnlyString(CharSequence,String,LanguageVersion)` has been removed. + Use readOnlyString instead. + * TextFile - method `dataSourceCompat(DataSource,PMDConfiguration)` has been removed. + Use TextFile directly, e.g. forPath + * XPathVersion + * `XPATH_1_0` + * `XPATH_1_0_COMPATIBILITY` + * `XPATH_2_0` + * Only XPath version 3.1 is now supported. This version of the XPath language is mostly identical to + XPath 2.0. XPath rules by default use now XPATH_3_1. + * `net.sourceforge.pmd.lang.rule.AbstractDelegateRule` removed. It has been merged with RuleReference. + * AbstractRule - the following methods have been removed: + * `deepCopyValuesTo(AbstractRule)` - use deepCopy instead. + * `addRuleChainVisit(Class)` - override buildTargetSelector in order to register nodes for rule chain visits. + * `addViolation(...)` - use addViolation instead, e.g. via `asCtx(data).addViolation(...)`. + Note: These methods were only marked as deprecated in javadoc. + * `addViolationWithMessage(...)` - use addViolationWithMessage instead, e.g. via + `asCtx(data).addViolationWithMessage(...)`. Note: These methods were only marked as deprecated in javadoc. + * RuleReference - the following methods have been removed: + * `setRuleSetReference(RuleSetReference)` - without replacement. Just construct new RuleReference instead. + * `hasOverriddenProperty(PropertyDescriptor)` - use isPropertyOverridden instead. + * XPathRule + * The constant `XPATH_DESCRIPTOR` has been made private and is not accessible anymore. + * The default constructor has been made package-private and is not accessible anymore. + * Language - method `getTerseName()` removed. Use getId instead. + * LanguageModuleBase - method `getTerseName()` removed. Use getId instead. + * LanguageRegistry - the following methods have been removed: + * `getLanguage(String)` - use getLanguageByFullName + via PMD or CPD instead. + * `findLanguageByTerseName(String)` - use getLanguageById + via PMD or CPD instead. + * `findByExtension(String)` - removed without replacement. + * LanguageVersionDiscoverer - method `getLanguagesForFile(java.io.File)` removed. + Use getLanguagesForFile instead. + * AbstractPropertySource + * field `propertyDescriptors` has been made private and is not accessible anymore. + Use getPropertyDescriptors instead. + * field `propertyValuesByDescriptor` has been made private and is not accessible anymore. + Use getPropertiesByPropertyDescriptor + or getOverriddenPropertiesByPropertyDescriptor instead. + * method `copyPropertyDescriptors()` has been removed. Use getPropertyDescriptors instead. + * method `copyPropertyValues()` has been removed. Use getPropertiesByPropertyDescriptor + or getOverriddenPropertiesByPropertyDescriptor instead. + * Reportable - the following methods have been removed. Use getReportLocation instead + * `getBeginLine()` + * `getBeginColumn()` + * `getEndLine()` + * `getEndColumn()` + * `net.sourceforge.pmd.util.datasource.DataSource` - use TextFile instead. + * `net.sourceforge.pmd.util.datasource.FileDataSource` + * `net.sourceforge.pmd.util.datasource.ReaderDataSource` + * `net.sourceforge.pmd.util.datasource.ZipDataSource` + * CollectionUtil + * method `invertedMapFrom(...)` has been removed. + * method `mapFrom(...)` has been removed. + * AbstractConfiguration - the following methods have been removed: + * `setIgnoreFilePath(String)` - use setIgnoreFilePath instead. + * `setInputFilePath(String)` - use setInputFilePath instead. + * `setInputPaths(String)` - use setInputPathList or + addInputPath instead. + * `setInputUri(String)` - use setInputUri instead. + * PMDConfiguration - the following methods have been removed + * `prependClasspath(String)` - use prependAuxClasspath instead. + * `getRuleSets()` - use getRuleSetPaths instead. + * `setRuleSets(String)` - use setRuleSets or + addRuleSet instead. + * `setReportFile(String)` - use setReportFile instead. + * `getReportFile()` - use getReportFilePath instead. + * Report - method `merge(Report)` has been removed. Use union instead. + * RuleSetLoader - method `toFactory()` has been made package private and is not accessible anymore. + * RuleViolation - the following methods have been removed: + * `getPackageName()` - use getAdditionalInfo with PACKAGE_NAME instead, e.g. `getAdditionalInfo().get(PACKAGE_NAME)`. + * `getClassName()` - use getAdditionalInfo with CLASS_NAME instead, e.g. `getAdditionalInfo().get(CLASS_NAME)`. + * `getMethodName()` - use getAdditionalInfo with METHOD_NAME instead, e.g. `getAdditionalInfo().get(METHOD_NAME)`. + * `getVariableName()` - use getAdditionalInfo with VARIABLE_NAME instead, e.g. `getAdditionalInfo().get(VARIABLE_NAME)`. * pmd-apex - * ApexNode and ASTApexFile - * `#getApexVersion()`: In PMD 6, this method has been deprecated but was defined in the class `ApexRootNode`. - The version returned is always "Version.CURRENT", as the apex compiler integration - doesn't use additional information which Apex version actually is used. Therefore, this method can't be - used to determine the Apex version of the project that is being analyzed. + * ApexNode and ASTApexFile + * `#getApexVersion()`: In PMD 6, this method has been deprecated but was defined in the class `ApexRootNode`. + The version returned is always "Version.CURRENT", as the apex compiler integration + doesn't use additional information which Apex version actually is used. Therefore, this method can't be + used to determine the Apex version of the project that is being analyzed. - If the current version is needed, then `Node.getTextDocument().getLanguageVersion()` can be used. This - is the version that has been selected via CLI `--use-version` parameter. - * ApexNode - * method `jjtAccept()` has been removed. - Use acceptVisitor instead. - * method `getNode()` has been removed. The underlying node is only available in AST nodes, but not in rule implementations. - * AbstractApexNode - method `getNode()` is now package private. - AST nodes still have access to the underlying Jorje node via the protected property `node`. - * `net.sourceforge.pmd.lang.apex.ast.ApexParserVisitor` - Use ApexVisitor or ApexVisitorBase instead. - * `net.sourceforge.pmd.lang.apex.ast.ApexParserVisitorAdapter` - * ASTAssignmentExpression - method `getOperator()` removed. - Use getOp instead. - * ASTBinaryExpression - method `getOperator()` removed. - Use getOp instead. - * ASTBooleanExpression - method `getOperator()` removed. - Use getOp instead. - * ASTPostfixExpression - method `getOperator()` removed. - Use getOp instead. - * ASTPrefixExpression - method `getOperator()` removed. - Use getOp instead. - * `net.sourceforge.pmd.lang.apex.rule.security.Helper` removed. This was actually internal API. + If the current version is needed, then `Node.getTextDocument().getLanguageVersion()` can be used. This + is the version that has been selected via CLI `--use-version` parameter. + * ApexNode + * method `jjtAccept()` has been removed. + Use acceptVisitor instead. + * method `getNode()` has been removed. The underlying node is only available in AST nodes, but not in rule implementations. + * AbstractApexNode - method `getNode()` is now package private. + AST nodes still have access to the underlying Jorje node via the protected property `node`. + * `net.sourceforge.pmd.lang.apex.ast.ApexParserVisitor` + Use ApexVisitor or ApexVisitorBase instead. + * `net.sourceforge.pmd.lang.apex.ast.ApexParserVisitorAdapter` + * ASTAssignmentExpression - method `getOperator()` removed. + Use getOp instead. + * ASTBinaryExpression - method `getOperator()` removed. + Use getOp instead. + * ASTBooleanExpression - method `getOperator()` removed. + Use getOp instead. + * ASTPostfixExpression - method `getOperator()` removed. + Use getOp instead. + * ASTPrefixExpression - method `getOperator()` removed. + Use getOp instead. + * `net.sourceforge.pmd.lang.apex.rule.security.Helper` removed. This was actually internal API. * pmd-java - * AbstractPackageNameModuleDirective - method `getImage()` has been removed. - Use getPackageName instead. - * `AbstractTypeDeclaration` - method `getImage()` has been removed. - Use `getSimpleName()` instead. - * ASTAnnotation - method `getAnnotationName()` has been removed. - * ASTClassType - * constructor `ASTClassType(java.lang.String)` has been removed. - * method `getImage()` has been removed. - * method `isReferenceToClassSameCompilationUnit()` has been removed. - * ASTFieldDeclaration - method `getVariableName()` has been removed. - * ASTLiteral - the following methods have been removed: - * `isStringLiteral()` - use `node instanceof ASTStringLiteral` instead. - * `isCharLiteral()` - use `node instanceof ASTCharLiteral` instead. - * `isNullLiteral()` - use `node instanceof ASTNullLiteral` instead. - * `isBooleanLiteral()` - use `node instanceof ASTBooleanLiteral` instead. - * `isNumericLiteral()` - use `node instanceof ASTNumericLiteral` instead. - * `isIntLiteral()` - use isIntLiteral instead. - * `isLongLiteral()` - use isLongLiteral instead. - * `isFloatLiteral()` - use isFloatLiteral instead. - * `isDoubleLiteral()` - use isDoubleLiteral instead. - * ASTMethodDeclaration - methods `getImage()` and `getMethodName()` have been removed. - Use getName instead. - * ASTMethodReference - method `getImage()` has been removed. - * ASTModuleName - method `getImage()` has been removed. - * ASTPrimitiveType - method `getImage()` has been removed. - * ASTType - * `getTypeImage()` has been removed. - * `getArrayDepth()` has been removed. It's only available for arrays: getArrayDepth. - * `isPrimitiveType()` - use `node instanceof ASTPrimitiveType` instead. - * `isArrayType()` - use `node instanceof ASTArrayType` instead. - * `isClassOrInterfaceType()` - use `node instanceof ASTClassType` instead. - * ASTTypeDeclaration - method `getImage()` has been removed. - * ASTUnaryExpression - method `isPrefix()` has been removed. - Use getOperator`.isPrefix()` instead. - * ASTVariableId - methods `getImage()` and `getVariableName()` have been removed. - Use getName instead. - * JavaComment - method `getImage()` has been removed. - Use getText instead. - * JavaNode - method `jjtAccept()` has been removed. - Use acceptVisitor instead. - * `net.sourceforge.pmd.lang.java.ast.JavaParserVisitor` - Use JavaVisitor or JavaVisitorBase instead. - * `net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter` - * ModifierOwner - * `isFinal()` - This is still available in various subtypes, where it makes sense, e.g. isFinal. - * `isAbstract()` - This is still available in subtypes, e.g. isAbstract. - * `isStrictfp()` - Use hasModifiers instead, e.g. `hasModifiers(STRICTFP)`. - * `isSynchronized()` - Use hasModifiers instead, e.g. `hasModifiers(SYNCHRONIZED)`. - * `isNative()` - Use hasModifiers instead, e.g. `hasModifiers(NATIVE)`. - * `isStatic()` - This is still available in subtypes, e.g. isStatic. - * `isVolatile()` - Use hasModifiers instead, e.g. `hasModifiers(VOLATILE)`. - * `isTransient()` - Use hasModifiers instead, e.g. `hasModifiers(TRANSIENT)`. - * `isPrivate()` - Use getVisibility instead, e.g. `getVisibility() == Visibility.V_PRIVATE`. - * `isPublic()` - Use getVisibility instead, e.g. `getVisibility() == Visibility.V_PUBLIC`. - * `isProtected()` - Use getVisibility instead, e.g. `getVisibility() == Visibility.V_PROTECTED`. - * `isPackagePrivate()` - Use getVisibility instead, e.g. `getVisibility() == Visibility.V_PACKAGE`. - * `isSyntacticallyAbstract()` - Use hasExplicitModifiers instead, e.g. `hasExplicitModifiers(ABSTRACT)`. - * `isSyntacticallyPublic()` - Use hasExplicitModifiers instead, e.g. `hasExplicitModifiers(PUBLIC)`. - * `isSyntacticallyStatic()` - Use hasExplicitModifiers instead, e.g. `hasExplicitModifiers(STATIC)`. - * `isSyntacticallyFinal()` - Use hasExplicitModifiers instead, e.g. `hasExplicitModifiers(FINAL)`. - * TypeNode - method `getType()` has been removed. Use getTypeMirror instead. + * AbstractPackageNameModuleDirective - method `getImage()` has been removed. + Use getPackageName instead. + * `AbstractTypeDeclaration` - method `getImage()` has been removed. + Use `getSimpleName()` instead. + * ASTAnnotation - method `getAnnotationName()` has been removed. + * ASTClassType + * constructor `ASTClassType(java.lang.String)` has been removed. + * method `getImage()` has been removed. + * method `isReferenceToClassSameCompilationUnit()` has been removed. + * ASTFieldDeclaration - method `getVariableName()` has been removed. + * ASTLiteral - the following methods have been removed: + * `isStringLiteral()` - use `node instanceof ASTStringLiteral` instead. + * `isCharLiteral()` - use `node instanceof ASTCharLiteral` instead. + * `isNullLiteral()` - use `node instanceof ASTNullLiteral` instead. + * `isBooleanLiteral()` - use `node instanceof ASTBooleanLiteral` instead. + * `isNumericLiteral()` - use `node instanceof ASTNumericLiteral` instead. + * `isIntLiteral()` - use isIntLiteral instead. + * `isLongLiteral()` - use isLongLiteral instead. + * `isFloatLiteral()` - use isFloatLiteral instead. + * `isDoubleLiteral()` - use isDoubleLiteral instead. + * ASTMethodDeclaration - methods `getImage()` and `getMethodName()` have been removed. + Use getName instead. + * ASTMethodReference - method `getImage()` has been removed. + * ASTModuleName - method `getImage()` has been removed. + * ASTPrimitiveType - method `getImage()` has been removed. + * ASTType + * `getTypeImage()` has been removed. + * `getArrayDepth()` has been removed. It's only available for arrays: getArrayDepth. + * `isPrimitiveType()` - use `node instanceof ASTPrimitiveType` instead. + * `isArrayType()` - use `node instanceof ASTArrayType` instead. + * `isClassOrInterfaceType()` - use `node instanceof ASTClassType` instead. + * ASTTypeDeclaration - method `getImage()` has been removed. + * ASTUnaryExpression - method `isPrefix()` has been removed. + Use getOperator`.isPrefix()` instead. + * ASTVariableId - methods `getImage()` and `getVariableName()` have been removed. + Use getName instead. + * JavaComment - method `getImage()` has been removed. + Use getText instead. + * JavaNode - method `jjtAccept()` has been removed. + Use acceptVisitor instead. + * `net.sourceforge.pmd.lang.java.ast.JavaParserVisitor` + Use JavaVisitor or JavaVisitorBase instead. + * `net.sourceforge.pmd.lang.java.ast.JavaParserVisitorAdapter` + * ModifierOwner + * `isFinal()` - This is still available in various subtypes, where it makes sense, e.g. isFinal. + * `isAbstract()` - This is still available in subtypes, e.g. isAbstract. + * `isStrictfp()` - Use hasModifiers instead, e.g. `hasModifiers(STRICTFP)`. + * `isSynchronized()` - Use hasModifiers instead, e.g. `hasModifiers(SYNCHRONIZED)`. + * `isNative()` - Use hasModifiers instead, e.g. `hasModifiers(NATIVE)`. + * `isStatic()` - This is still available in subtypes, e.g. isStatic. + * `isVolatile()` - Use hasModifiers instead, e.g. `hasModifiers(VOLATILE)`. + * `isTransient()` - Use hasModifiers instead, e.g. `hasModifiers(TRANSIENT)`. + * `isPrivate()` - Use getVisibility instead, e.g. `getVisibility() == Visibility.V_PRIVATE`. + * `isPublic()` - Use getVisibility instead, e.g. `getVisibility() == Visibility.V_PUBLIC`. + * `isProtected()` - Use getVisibility instead, e.g. `getVisibility() == Visibility.V_PROTECTED`. + * `isPackagePrivate()` - Use getVisibility instead, e.g. `getVisibility() == Visibility.V_PACKAGE`. + * `isSyntacticallyAbstract()` - Use hasExplicitModifiers instead, e.g. `hasExplicitModifiers(ABSTRACT)`. + * `isSyntacticallyPublic()` - Use hasExplicitModifiers instead, e.g. `hasExplicitModifiers(PUBLIC)`. + * `isSyntacticallyStatic()` - Use hasExplicitModifiers instead, e.g. `hasExplicitModifiers(STATIC)`. + * `isSyntacticallyFinal()` - Use hasExplicitModifiers instead, e.g. `hasExplicitModifiers(FINAL)`. + * TypeNode - method `getType()` has been removed. Use getTypeMirror instead. * pmd-javascript - * AbstractEcmascriptNode - method `getNode()` has been removed. - AST nodes still have access to the underlying Rhino node via the protected property `node`. - * ASTFunctionNode - method `getBody(int)` removed. - Use getBody instead. - * ASTTryStatement - * method `isCatch()` has been removed. Use hasCatch instead. - * method `isFinally()` has been removed. Use hasFinally instead. - * EcmascriptNode - * method `jjtAccept()` has been removed. Use acceptVisitor instead. - * method `getNode()` has been removed. The underlying node is only available in AST nodes, but not in rule implementations. - * `net.sourceforge.pmd.lang.ecmascript.ast.EcmascriptParserVisitor` - Use EcmascriptVisitor or EcmascriptVisitorBase instead. - * `net.sourceforge.pmd.lang.ecmascript.ast.EcmascriptParserVisitorAdapter` + * AbstractEcmascriptNode - method `getNode()` has been removed. + AST nodes still have access to the underlying Rhino node via the protected property `node`. + * ASTFunctionNode - method `getBody(int)` removed. + Use getBody instead. + * ASTTryStatement + * method `isCatch()` has been removed. Use hasCatch instead. + * method `isFinally()` has been removed. Use hasFinally instead. + * EcmascriptNode + * method `jjtAccept()` has been removed. Use acceptVisitor instead. + * method `getNode()` has been removed. The underlying node is only available in AST nodes, but not in rule implementations. + * `net.sourceforge.pmd.lang.ecmascript.ast.EcmascriptParserVisitor` + Use EcmascriptVisitor or EcmascriptVisitorBase instead. + * `net.sourceforge.pmd.lang.ecmascript.ast.EcmascriptParserVisitorAdapter` * pmd-jsp - * `net.sourceforge.pmd.lang.jsp.ast.JspParserVisitor` - Use JspVisitor or JspVisitorBase instead. - * `net.sourceforge.pmd.lang.jsp.ast.JspParserVisitorAdapter` - * JspNode - method `jjtAccept()` has been removed. - Use acceptVisitor instead. + * `net.sourceforge.pmd.lang.jsp.ast.JspParserVisitor` + Use JspVisitor or JspVisitorBase instead. + * `net.sourceforge.pmd.lang.jsp.ast.JspParserVisitorAdapter` + * JspNode - method `jjtAccept()` has been removed. + Use acceptVisitor instead. * pmd-modelica - * `net.sourceforge.pmd.lang.modelica.ast.ModelicaParserVisitor` - Use ModelicaVisitor or ModelicaVisitorBase instead. - * `net.sourceforge.pmd.lang.modelica.ast.ModelicaParserVisitorAdapter` - * ModelicaNode - method `jjtAccept()` has been removed. - Use acceptVisitor instead. - * `net.sourceforge.pmd.lang.modelica.rule.AmbiguousResolutionRule` - Use AmbiguousResolutionRule instead. - * `net.sourceforge.pmd.lang.modelica.rule.ConnectUsingNonConnector` - Use ConnectUsingNonConnectorRule + * `net.sourceforge.pmd.lang.modelica.ast.ModelicaParserVisitor` + Use ModelicaVisitor or ModelicaVisitorBase instead. + * `net.sourceforge.pmd.lang.modelica.ast.ModelicaParserVisitorAdapter` + * ModelicaNode - method `jjtAccept()` has been removed. + Use acceptVisitor instead. + * `net.sourceforge.pmd.lang.modelica.rule.AmbiguousResolutionRule` + Use AmbiguousResolutionRule instead. + * `net.sourceforge.pmd.lang.modelica.rule.ConnectUsingNonConnector` + Use ConnectUsingNonConnectorRule * pmd-plsql - * `net.sourceforge.pmd.lang.plsql.ast.PLSQLParserVisitor` - Use PlsqlVisitor or PlsqlVisitorBase instead. - * `net.sourceforge.pmd.lang.plsql.ast.PLSQLParserVisitorAdapter` - * PLSQLNode - method `jjtAccept()` has been removed. - Use acceptVisitor instead. + * `net.sourceforge.pmd.lang.plsql.ast.PLSQLParserVisitor` + Use PlsqlVisitor or PlsqlVisitorBase instead. + * `net.sourceforge.pmd.lang.plsql.ast.PLSQLParserVisitorAdapter` + * PLSQLNode - method `jjtAccept()` has been removed. + Use acceptVisitor instead. * pmd-scala - * The maven module `pmd-scala` has been removed. Use `pmd-scala_2.13` or `pmd-scala_2.12` instead. - * ScalaNode - * Method `accept()` has been removed. Use acceptVisitor instead. - * Method `getNode()` has been removed. The underlying node is only available in AST nodes, but not in rule implementations. - * `AbstractScalaNode` - method `getNode()` has been removed. AST nodes still have access - to the underlying Scala node via the protected property `node`. + * The maven module `pmd-scala` has been removed. Use `pmd-scala_2.13` or `pmd-scala_2.12` instead. + * ScalaNode + * Method `accept()` has been removed. Use acceptVisitor instead. + * Method `getNode()` has been removed. The underlying node is only available in AST nodes, but not in rule implementations. + * `AbstractScalaNode` - method `getNode()` has been removed. AST nodes still have access + to the underlying Scala node via the protected property `node`. * pmd-visualforce - * VfNode - method `jjtAccept()` has been removed. - Use acceptVisitor instead. - * `net.sourceforge.pmd.lang.vf.ast.VfParserVisitor` - Use VfVisitor or VfVisitorBase instead. - * `net.sourceforge.pmd.lang.vf.ast.VfParserVisitorAdapter` - * DataType - method `fromBasicType(BasicType)` has been removed. - Use fromTypeName instead. + * VfNode - method `jjtAccept()` has been removed. + Use acceptVisitor instead. + * `net.sourceforge.pmd.lang.vf.ast.VfParserVisitor` + Use VfVisitor or VfVisitorBase instead. + * `net.sourceforge.pmd.lang.vf.ast.VfParserVisitorAdapter` + * DataType - method `fromBasicType(BasicType)` has been removed. + Use fromTypeName instead. * pmd-velocity (previously pmd-vm) - * VtlNode - method `jjtAccept()` has been removed. - Use acceptVisitor instead. - * `net.sourceforge.pmd.lang.vm.ast.VmParserVisitor` - Use VtlVisitor or VtlVisitorBase instead. - * `net.sourceforge.pmd.lang.vm.ast.VmParserVisitorAdapter` + * VtlNode - method `jjtAccept()` has been removed. + Use acceptVisitor instead. + * `net.sourceforge.pmd.lang.vm.ast.VmParserVisitor` + Use VtlVisitor or VtlVisitorBase instead. + * `net.sourceforge.pmd.lang.vm.ast.VmParserVisitorAdapter` **Removed classes, interfaces and methods (not previously deprecated)** * pmd-apex - * The method `isSynthetic()` in ASTMethod has been removed. - With the switch from Jorje to Summit AST as underlying parser, no synthetic methods are generated by the - parser anymore. This also means, that there is no XPath attribute `@Synthetic` anymore. - * The constant `STATIC_INITIALIZER_METHOD_NAME` in FieldDeclarationsShouldBeAtStartRule - has been removed. It was used to filter out synthetic methods, but these are not generated anymore with the - new parser. - * The method `getContext()` in ASTReferenceExpression has been removed. - It was not used and always returned `null`. - * The method `getNamespace()` in all AST nodes (defined in ApexNode) has - been removed, as it was never fully implemented. It always returned an empty string. - * The method `getNameSpace()` in ApexQualifiedName has been removed. - * The class `net.sourceforge.pmd.lang.apex.ast.ASTBridgeMethodCreator` has been removed. This was a node that has - been generated by the old Jorje parser only. + * The method `isSynthetic()` in ASTMethod has been removed. + With the switch from Jorje to Summit AST as underlying parser, no synthetic methods are generated by the + parser anymore. This also means, that there is no XPath attribute `@Synthetic` anymore. + * The constant `STATIC_INITIALIZER_METHOD_NAME` in FieldDeclarationsShouldBeAtStartRule + has been removed. It was used to filter out synthetic methods, but these are not generated anymore with the + new parser. + * The method `getContext()` in ASTReferenceExpression has been removed. + It was not used and always returned `null`. + * The method `getNamespace()` in all AST nodes (defined in ApexNode) has + been removed, as it was never fully implemented. It always returned an empty string. + * The method `getNameSpace()` in ApexQualifiedName has been removed. + * The class `net.sourceforge.pmd.lang.apex.ast.ASTBridgeMethodCreator` has been removed. This was a node that has + been generated by the old Jorje parser only. * pmd-apex-jorje - * With the switch from Jorje to Summit AST, this maven module is no longer needed and has been removed. + * With the switch from Jorje to Summit AST, this maven module is no longer needed and has been removed. * pmd-core - * `net.sourceforge.pmd.util.Predicate` has been removed. It was marked as Experimental before. Use - `java.util.function.Predicate` instead. + * `net.sourceforge.pmd.util.Predicate` has been removed. It was marked as Experimental before. Use + `java.util.function.Predicate` instead. * pmd-java - * The interface `FinalizableNode` (introduced in 7.0.0-rc1) has been removed. - Its method `isFinal()` has been moved down to the - nodes where needed, e.g. ASTLocalVariableDeclaration#isFinal. - * The method `isPackagePrivate()` in ASTClassDeclaration (formerly ASTClassOrInterfaceDeclaration) - has been removed. - Use hasVisibility instead, - which can correctly differentiate between local and package private classes. + * The interface `FinalizableNode` (introduced in 7.0.0-rc1) has been removed. + Its method `isFinal()` has been moved down to the + nodes where needed, e.g. ASTLocalVariableDeclaration#isFinal. + * The method `isPackagePrivate()` in ASTClassDeclaration (formerly ASTClassOrInterfaceDeclaration) + has been removed. + Use hasVisibility instead, + which can correctly differentiate between local and package private classes. **Renamed classes, interfaces, methods** * pmd-core - * MessageReporter has been renamed to PmdReporter - * TokenMgrError has been renamed to LexException - * Tokenizer has been renamed to CpdLexer. Along with this rename, - all the implementations have been renamed as well (`Tokenizer` -> `CpdLexer`), e.g. "CppCpdLexer", "JavaCpdLexer". - This affects all language modules. - * AnyTokenizer has been renamed to AnyCpdLexer. + * MessageReporter has been renamed to PmdReporter + * TokenMgrError has been renamed to LexException + * Tokenizer has been renamed to CpdLexer. Along with this rename, + all the implementations have been renamed as well (`Tokenizer` -> `CpdLexer`), e.g. "CppCpdLexer", "JavaCpdLexer". + This affects all language modules. + * AnyTokenizer has been renamed to AnyCpdLexer. * pmd-java - * The interface `AccessNode` has been renamed to ModifierOwner. This is only relevant - for Java rules, which use that type directly e.g. through downcasting. - Or when using the XPath function `pmd-java:nodeIs()`. - * The node `ASTClassOrInterfaceType` has been renamed to ASTClassType. XPath rules - need to be adjusted. - * The node `ASTClassOrInterfaceDeclaration` has been renamed to ASTClassDeclaration. - XPath rules need to be adjusted. - * The interface `ASTAnyTypeDeclaration` has been renamed to ASTTypeDeclaration. - This is only relevant for Java rules, which use that type directly, e.g. through downcasting. - Or when using the XPath function `pmd-java:nodeIs()`. - * The interface `ASTMethodOrConstructorDeclaration` has been renamed to - ASTExecutableDeclaration. This is only relevant for Java rules, which use that type - directly, e.g. through downcasting. Or when using the XPath function `pmd-java:nodeIs()`. - * The node `ASTVariableDeclaratorId` has been renamed to ASTVariableId. XPath rules - need to be adjusted. - * The node `ASTClassOrInterfaceBody` has been renamed to ASTClassBody. XPath rules - need to be adjusted. + * The interface `AccessNode` has been renamed to ModifierOwner. This is only relevant + for Java rules, which use that type directly e.g. through downcasting. + Or when using the XPath function `pmd-java:nodeIs()`. + * The node `ASTClassOrInterfaceType` has been renamed to ASTClassType. XPath rules + need to be adjusted. + * The node `ASTClassOrInterfaceDeclaration` has been renamed to ASTClassDeclaration. + XPath rules need to be adjusted. + * The interface `ASTAnyTypeDeclaration` has been renamed to ASTTypeDeclaration. + This is only relevant for Java rules, which use that type directly, e.g. through downcasting. + Or when using the XPath function `pmd-java:nodeIs()`. + * The interface `ASTMethodOrConstructorDeclaration` has been renamed to + ASTExecutableDeclaration. This is only relevant for Java rules, which use that type + directly, e.g. through downcasting. Or when using the XPath function `pmd-java:nodeIs()`. + * The node `ASTVariableDeclaratorId` has been renamed to ASTVariableId. XPath rules + need to be adjusted. + * The node `ASTClassOrInterfaceBody` has been renamed to ASTClassBody. XPath rules + need to be adjusted. * pmd-scala - * The interface `ScalaParserVisitor` has been renamed to ScalaVisitor in order - to align the naming scheme for the different language modules. - * The class `ScalaParserVisitorAdapter` has been renamed to ScalaVisitorBase in order - to align the naming scheme for the different language modules. + * The interface `ScalaParserVisitor` has been renamed to ScalaVisitor in order + to align the naming scheme for the different language modules. + * The class `ScalaParserVisitorAdapter` has been renamed to ScalaVisitorBase in order + to align the naming scheme for the different language modules. **New API** These were annotated with `@Experimental`, but can now be considered stable. * pmd-apex - * ASTCommentContainer - * ApexMultifileAnalysis + * ASTCommentContainer + * ApexMultifileAnalysis * pmd-core - * CPDReport#filterMatches - * AntlrToken#getKind - * AbstractJjtreeNode - * TokenDocument - * AstInfo#getSuppressionComments - * AstInfo#withSuppressMap - * GenericToken#getKind - * FileCollector#addZipFileWithContent - * net.sourceforge.pmd.lang.document - * LanguageVersionHandler#getLanguageMetricsProvider - * LanguageVersionHandler#getDesignerBindings - * PlainTextLanguage - * PropertyConstraint#getXmlConstraint - * PropertyConstraint#toOptionalConstraint - * PropertyConstraint#fromPredicate - * PropertyConstraint#fromPredicate - * AbstractRenderer#setReportFile - * Renderer#setReportFile - * DesignerBindings - * DesignerBindings.TreeIconId - * RelatedNodesSelector - * Report#filterViolations - * Report#union + * CPDReport#filterMatches + * AntlrToken#getKind + * AbstractJjtreeNode + * TokenDocument + * AstInfo#getSuppressionComments + * AstInfo#withSuppressMap + * GenericToken#getKind + * FileCollector#addZipFileWithContent + * net.sourceforge.pmd.lang.document + * LanguageVersionHandler#getLanguageMetricsProvider + * LanguageVersionHandler#getDesignerBindings + * PlainTextLanguage + * PropertyConstraint#getXmlConstraint + * PropertyConstraint#toOptionalConstraint + * PropertyConstraint#fromPredicate + * PropertyConstraint#fromPredicate + * AbstractRenderer#setReportFile + * Renderer#setReportFile + * DesignerBindings + * DesignerBindings.TreeIconId + * RelatedNodesSelector + * Report#filterViolations + * Report#union * pmd-groovy - * GroovyToken#getKind + * GroovyToken#getKind * pmd-html - * net.sourceforge.pmd.lang.html + * net.sourceforge.pmd.lang.html * pmd-java - * ASTExpression#getConversionContext - * AbstractJavaRulechainRule#<init> - * JSymbolTable - * JElementSymbol - * net.sourceforge.pmd.lang.java.symbols - * ExprContext - * JIntersectionType#getInducedClassType - * JTypeMirror#streamMethods - * JTypeMirror#streamDeclaredMethods - * JTypeMirror#getConstructors + * ASTExpression#getConversionContext + * AbstractJavaRulechainRule#<init> + * JSymbolTable + * JElementSymbol + * net.sourceforge.pmd.lang.java.symbols + * ExprContext + * JIntersectionType#getInducedClassType + * JTypeMirror#streamMethods + * JTypeMirror#streamDeclaredMethods + * JTypeMirror#getConstructors * pmd-kotlin - * KotlinLanguageModule + * KotlinLanguageModule * pmd-test-schema - * TestSchemaParser + * TestSchemaParser **Removed functionality** @@ -1485,135 +1485,135 @@ and [PR #4397](https://github.com/pmd/pmd/pull/4397) for details. The following previously deprecated classes have been removed: * pmd-core - * `net.sourceforge.pmd.cpd.AbstractTokenizer` ➡️ use AnyCpdLexer instead (previously known as AnyTokenizer) - * `net.sourceforge.pmd.cpd.CPD` ➡️ use PmdCli from `pmd-cli` module for CLI support or use - CpdAnalysis for programmatic API - * `net.sourceforge.pmd.cpd.GridBagHelper` (now package private) - * `net.sourceforge.pmd.cpd.TokenEntry.State` - * `net.sourceforge.pmd.lang.document.CpdCompat` - * `net.sourceforge.pmd.properties.BooleanMultiProperty` - * `net.sourceforge.pmd.properties.BooleanProperty` - * `net.sourceforge.pmd.properties.CharacterMultiProperty` - * `net.sourceforge.pmd.properties.CharacterProperty` - * `net.sourceforge.pmd.properties.DoubleMultiProperty` - * `net.sourceforge.pmd.properties.DoubleProperty` - * `net.sourceforge.pmd.properties.EnumeratedMultiProperty` - * `net.sourceforge.pmd.properties.EnumeratedProperty` - * `net.sourceforge.pmd.properties.EnumeratedPropertyDescriptor` - * `net.sourceforge.pmd.properties.FileProperty` (note: without replacement) - * `net.sourceforge.pmd.properties.FloatMultiProperty` - * `net.sourceforge.pmd.properties.FloatProperty` - * `net.sourceforge.pmd.properties.IntegerMultiProperty` - * `net.sourceforge.pmd.properties.IntegerProperty` - * `net.sourceforge.pmd.properties.LongMultiProperty` - * `net.sourceforge.pmd.properties.LongProperty` - * `net.sourceforge.pmd.properties.MultiValuePropertyDescriptor` - * `net.sourceforge.pmd.properties.NumericPropertyDescriptor` - * `net.sourceforge.pmd.properties.PropertyDescriptorField` - * `net.sourceforge.pmd.properties.RegexProperty` - * `net.sourceforge.pmd.properties.SingleValuePropertyDescriptor` - * `net.sourceforge.pmd.properties.StringMultiProperty` - * `net.sourceforge.pmd.properties.StringProperty` - * `net.sourceforge.pmd.properties.ValueParser` - * `net.sourceforge.pmd.properties.ValueParserConstants` - * `net.sourceforge.pmd.properties.builders.MultiNumericPropertyBuilder` - * `net.sourceforge.pmd.properties.builders.MultiPackagedPropertyBuilder` - * `net.sourceforge.pmd.properties.builders.MultiValuePropertyBuilder` - * `net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilder` - * `net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper` - * `net.sourceforge.pmd.properties.builders.PropertyDescriptorExternalBuilder` - * `net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder` - * `net.sourceforge.pmd.properties.builders.SinglePackagedPropertyBuilder` - * `net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder` - * `net.sourceforge.pmd.properties.modules.EnumeratedPropertyModule` - * `net.sourceforge.pmd.properties.modules.NumericPropertyModule` + * `net.sourceforge.pmd.cpd.AbstractTokenizer` ➡️ use AnyCpdLexer instead (previously known as AnyTokenizer) + * `net.sourceforge.pmd.cpd.CPD` ➡️ use PmdCli from `pmd-cli` module for CLI support or use + CpdAnalysis for programmatic API + * `net.sourceforge.pmd.cpd.GridBagHelper` (now package private) + * `net.sourceforge.pmd.cpd.TokenEntry.State` + * `net.sourceforge.pmd.lang.document.CpdCompat` + * `net.sourceforge.pmd.properties.BooleanMultiProperty` + * `net.sourceforge.pmd.properties.BooleanProperty` + * `net.sourceforge.pmd.properties.CharacterMultiProperty` + * `net.sourceforge.pmd.properties.CharacterProperty` + * `net.sourceforge.pmd.properties.DoubleMultiProperty` + * `net.sourceforge.pmd.properties.DoubleProperty` + * `net.sourceforge.pmd.properties.EnumeratedMultiProperty` + * `net.sourceforge.pmd.properties.EnumeratedProperty` + * `net.sourceforge.pmd.properties.EnumeratedPropertyDescriptor` + * `net.sourceforge.pmd.properties.FileProperty` (note: without replacement) + * `net.sourceforge.pmd.properties.FloatMultiProperty` + * `net.sourceforge.pmd.properties.FloatProperty` + * `net.sourceforge.pmd.properties.IntegerMultiProperty` + * `net.sourceforge.pmd.properties.IntegerProperty` + * `net.sourceforge.pmd.properties.LongMultiProperty` + * `net.sourceforge.pmd.properties.LongProperty` + * `net.sourceforge.pmd.properties.MultiValuePropertyDescriptor` + * `net.sourceforge.pmd.properties.NumericPropertyDescriptor` + * `net.sourceforge.pmd.properties.PropertyDescriptorField` + * `net.sourceforge.pmd.properties.RegexProperty` + * `net.sourceforge.pmd.properties.SingleValuePropertyDescriptor` + * `net.sourceforge.pmd.properties.StringMultiProperty` + * `net.sourceforge.pmd.properties.StringProperty` + * `net.sourceforge.pmd.properties.ValueParser` + * `net.sourceforge.pmd.properties.ValueParserConstants` + * `net.sourceforge.pmd.properties.builders.MultiNumericPropertyBuilder` + * `net.sourceforge.pmd.properties.builders.MultiPackagedPropertyBuilder` + * `net.sourceforge.pmd.properties.builders.MultiValuePropertyBuilder` + * `net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilder` + * `net.sourceforge.pmd.properties.builders.PropertyDescriptorBuilderConversionWrapper` + * `net.sourceforge.pmd.properties.builders.PropertyDescriptorExternalBuilder` + * `net.sourceforge.pmd.properties.builders.SingleNumericPropertyBuilder` + * `net.sourceforge.pmd.properties.builders.SinglePackagedPropertyBuilder` + * `net.sourceforge.pmd.properties.builders.SingleValuePropertyBuilder` + * `net.sourceforge.pmd.properties.modules.EnumeratedPropertyModule` + * `net.sourceforge.pmd.properties.modules.NumericPropertyModule` The following previously deprecated methods have been removed: * pmd-core - * `net.sourceforge.pmd.properties.PropertyBuilder.GenericCollectionPropertyBuilder#delim(char)` - * `net.sourceforge.pmd.properties.PropertySource#setProperty(...)` - * `net.sourceforge.pmd.properties.internal.PropertyTypeId#factoryFor(...)` - * `net.sourceforge.pmd.properties.internal.PropertyTypeId#typeIdFor(...)` - * `net.sourceforge.pmd.properties.PropertyDescriptor`: removed methods errorFor, type, isMultiValue, - uiOrder, compareTo, isDefinedExternally, valueFrom, asDelimitedString + * `net.sourceforge.pmd.properties.PropertyBuilder.GenericCollectionPropertyBuilder#delim(char)` + * `net.sourceforge.pmd.properties.PropertySource#setProperty(...)` + * `net.sourceforge.pmd.properties.internal.PropertyTypeId#factoryFor(...)` + * `net.sourceforge.pmd.properties.internal.PropertyTypeId#typeIdFor(...)` + * `net.sourceforge.pmd.properties.PropertyDescriptor`: removed methods errorFor, type, isMultiValue, + uiOrder, compareTo, isDefinedExternally, valueFrom, asDelimitedString The following methods have been removed: * pmd-core - * CPDConfiguration - * `#sourceCodeFor(File)`, `#postConstruct()`, `#tokenizer()`, `#filenameFilter()` removed - * Mark - * `#getSourceSlice()`, `#setLineCount(int)`, `#getLineCount()`, `#setSourceCode(SourceCode)` removed - * `#getBeginColumn()`, `#getBeginLine()`, `#getEndLine()`, `#getEndColumn()` removed - ➡️ use getLocation instead - * Match - * `#LABEL_COMPARATOR` removed - * `#setMarkSet(...)`, `#setLabel(...)`, `#getLabel()`, `#addTokenEntry(...)` removed - * `#getSourceCodeSlice()` removed - ➡️ use CPDReport#getSourceCodeSlice instead - * TokenEntry - * `#getEOF()`, `#clearImages()`, `#getIdentifier()`, `#getIndex()`, `#setHashCode(int)` removed - * `#EOF` removed ➡️ use isEof instead - * Parser.ParserTask - * `#getFileDisplayName()` removed ➡️ use getFileId instead - (`getFileId().getAbsolutePath()`) + * CPDConfiguration + * `#sourceCodeFor(File)`, `#postConstruct()`, `#tokenizer()`, `#filenameFilter()` removed + * Mark + * `#getSourceSlice()`, `#setLineCount(int)`, `#getLineCount()`, `#setSourceCode(SourceCode)` removed + * `#getBeginColumn()`, `#getBeginLine()`, `#getEndLine()`, `#getEndColumn()` removed + ➡️ use getLocation instead + * Match + * `#LABEL_COMPARATOR` removed + * `#setMarkSet(...)`, `#setLabel(...)`, `#getLabel()`, `#addTokenEntry(...)` removed + * `#getSourceCodeSlice()` removed + ➡️ use CPDReport#getSourceCodeSlice instead + * TokenEntry + * `#getEOF()`, `#clearImages()`, `#getIdentifier()`, `#getIndex()`, `#setHashCode(int)` removed + * `#EOF` removed ➡️ use isEof instead + * Parser.ParserTask + * `#getFileDisplayName()` removed ➡️ use getFileId instead + (`getFileId().getAbsolutePath()`) The following classes have been removed: * pmd-core - * `net.sourceforge.pmd.cpd.AbstractLanguage` - * `net.sourceforge.pmd.cpd.AnyLanguage` - * `net.sourceforge.pmd.cpd.Language` - * `net.sourceforge.pmd.cpd.LanguageFactory` - * `net.sourceforge.pmd.cpd.MatchAlgorithm` (now package private) - * `net.sourceforge.pmd.cpd.MatchCollector` (now package private) - * `net.sourceforge.pmd.cpd.SourceCode` (and all inner classes like `FileCodeLoader`, ...) - * `net.sourceforge.pmd.cpd.token.TokenFilter` + * `net.sourceforge.pmd.cpd.AbstractLanguage` + * `net.sourceforge.pmd.cpd.AnyLanguage` + * `net.sourceforge.pmd.cpd.Language` + * `net.sourceforge.pmd.cpd.LanguageFactory` + * `net.sourceforge.pmd.cpd.MatchAlgorithm` (now package private) + * `net.sourceforge.pmd.cpd.MatchCollector` (now package private) + * `net.sourceforge.pmd.cpd.SourceCode` (and all inner classes like `FileCodeLoader`, ...) + * `net.sourceforge.pmd.cpd.token.TokenFilter` **Moved packages** * pmd-core - * NumericConstraints (old package: `net.sourceforge.pmd.properties.constraints.NumericConstraints`) - * PropertyConstraint (old package: `net.sourceforge.pmd.properties.constraints.PropertyConstraint`) - * not experimental anymore - * ReportException (old package: `net.sourceforge.pmd.cpd`, moved to module `pmd-ant`) - * it is now a RuntimeException - * CPDReportRenderer (old package: `net.sourceforge.pmd.cpd.renderer`) - * AntlrTokenFilter (old package: `net.sourceforge.pmd.cpd.token`) - * BaseTokenFilter (old package: `net.sourceforge.pmd.cpd.token.internal`) - * JavaCCTokenFilter (old package: `net.sourceforge.pmd.cpd.token`) + * NumericConstraints (old package: `net.sourceforge.pmd.properties.constraints.NumericConstraints`) + * PropertyConstraint (old package: `net.sourceforge.pmd.properties.constraints.PropertyConstraint`) + * not experimental anymore + * ReportException (old package: `net.sourceforge.pmd.cpd`, moved to module `pmd-ant`) + * it is now a RuntimeException + * CPDReportRenderer (old package: `net.sourceforge.pmd.cpd.renderer`) + * AntlrTokenFilter (old package: `net.sourceforge.pmd.cpd.token`) + * BaseTokenFilter (old package: `net.sourceforge.pmd.cpd.token.internal`) + * JavaCCTokenFilter (old package: `net.sourceforge.pmd.cpd.token`) **Changed types and other changes** * pmd-core - * PropertyDescriptor is now a class (was an interface) - and it is not comparable anymore. - * AbstractConfiguration#setSourceEncoding - * previously this method took a simple String for the encoding. - * PMDConfiguration and CPDConfiguration - * many getters and setters have been moved to the parent class AbstractConfiguration - * CPDListener#addedFile - * no `File` parameter anymore - * CPDReport#getNumberOfTokensPerFile returns a `Map` of `FileId,Integer` instead of `String` - * CPDReport#filterMatches now takes a `java.util.function.Predicate` - as parameter - * CpdLexer - * Note: CpdLexer was previously named Tokenizer. - * constants are now PropertyDescriptor instead of `String`, - to be used as language properties - * tokenize - changed parameters. Now takes a TextDocument and a TokenFactory - (instead of `SourceCode` and `Tokens`). - * Language - * method `#createProcessor(LanguagePropertyBundle)` moved to PmdCapableLanguage - * StringUtil#linesWithTrimIndent now takes a `Chars` - instead of a `String`. + * PropertyDescriptor is now a class (was an interface) + and it is not comparable anymore. + * AbstractConfiguration#setSourceEncoding + * previously this method took a simple String for the encoding. + * PMDConfiguration and CPDConfiguration + * many getters and setters have been moved to the parent class AbstractConfiguration + * CPDListener#addedFile + * no `File` parameter anymore + * CPDReport#getNumberOfTokensPerFile returns a `Map` of `FileId,Integer` instead of `String` + * CPDReport#filterMatches now takes a `java.util.function.Predicate` + as parameter + * CpdLexer + * Note: CpdLexer was previously named Tokenizer. + * constants are now PropertyDescriptor instead of `String`, + to be used as language properties + * tokenize + changed parameters. Now takes a TextDocument and a TokenFactory + (instead of `SourceCode` and `Tokens`). + * Language + * method `#createProcessor(LanguagePropertyBundle)` moved to PmdCapableLanguage + * StringUtil#linesWithTrimIndent now takes a `Chars` + instead of a `String`. * All language modules (like pmd-apex, pmd-cpp, ...) - * consistent package naming: `net.sourceforge.pmd.lang..cpd` - * adapted to use CpdCapableLanguage - * consistent static method `#getInstance()` - * removed constants like `ID`, `TERSE_NAME` or `NAME`. Use `getInstance().getName()` etc. instead + * consistent package naming: `net.sourceforge.pmd.lang..cpd` + * adapted to use CpdCapableLanguage + * consistent static method `#getInstance()` + * removed constants like `ID`, `TERSE_NAME` or `NAME`. Use `getInstance().getName()` etc. instead **Internal APIs** @@ -1631,14 +1631,14 @@ The following classes have been removed: * To support the Java preview language features "String Templates" and "Unnamed Patterns and Variables", the following AST nodes have been introduced as experimental: - * ASTTemplateExpression - * ASTTemplate - * ASTTemplateFragment - * ASTUnnamedPattern + * ASTTemplateExpression + * ASTTemplate + * ASTTemplateFragment + * ASTUnnamedPattern * The AST nodes for supporting "Record Patterns" and "Pattern Matching for switch" are not experimental anymore: - * ASTRecordPattern - * ASTPatternList (Note: it was renamed from `ASTComponentPatternList`) - * ASTGuard (Note: it was renamed from `ASTSwitchGuard`) + * ASTRecordPattern + * ASTPatternList (Note: it was renamed from `ASTComponentPatternList`) + * ASTGuard (Note: it was renamed from `ASTSwitchGuard`) #### 7.0.0-rc3 @@ -1676,11 +1676,11 @@ The following classes have been removed: The following previously deprecated classes have been removed: -* pmd-core - * `net.sourceforge.pmd.PMD` - * `net.sourceforge.pmd.cli.PMDCommandLineInterface` - * `net.sourceforge.pmd.cli.PMDParameters` - * `net.sourceforge.pmd.cli.PmdParametersParseResult` +* pmd-core + * `net.sourceforge.pmd.PMD` + * `net.sourceforge.pmd.cli.PMDCommandLineInterface` + * `net.sourceforge.pmd.cli.PMDParameters` + * `net.sourceforge.pmd.cli.PmdParametersParseResult` **CLI** @@ -1703,7 +1703,7 @@ The following previously deprecated classes have been removed: * The LanguageModule of Go, that only supports CPD execution, has been deprecated. This language is not fully supported by PMD, so having a language module does not make sense. The functionality of CPD is not affected by this change. The following class has been deprecated and will be removed with PMD 7.0.0: - * GoLanguageModule + * GoLanguageModule **Java** * Support for Java 18 preview language features have been removed. The version "18-preview" is no longer available. @@ -1753,8 +1753,8 @@ The following previously deprecated classes have been removed: **Experimental APIs** * CPDReport has a new method which limited mutation of a given report: - * filterMatches creates a new CPD report - with some matches removed with a given predicate based filter. + * filterMatches creates a new CPD report + with some matches removed with a given predicate based filter. #### 6.53.0 @@ -1795,21 +1795,21 @@ These classes / APIs have been deprecated and will be removed with PMD 7.0.0. **Deprecated API** * The following core APIs have been marked as deprecated for removal in PMD 7: - - PMD and `PMD.StatusCode` - PMD 7 will ship with a revamped CLI split from pmd-core. To programmatically launch analysis you can use PmdAnalysis. - - PMDConfiguration#getAllInputPaths - It is now superseded by PMDConfiguration#getInputPathList - - PMDConfiguration#setInputPaths - It is now superseded by PMDConfiguration#setInputPathList - - PMDConfiguration#addInputPath - It is now superseded by PMDConfiguration#addInputPath - - PMDConfiguration#getInputFilePath - It is now superseded by PMDConfiguration#getInputFile - - PMDConfiguration#getIgnoreFilePath - It is now superseded by PMDConfiguration#getIgnoreFile - - PMDConfiguration#setInputFilePath - It is now superseded by PMDConfiguration#setInputFilePath - - PMDConfiguration#setIgnoreFilePath - It is now superseded by PMDConfiguration#setIgnoreFilePath - - PMDConfiguration#getInputUri - It is now superseded by PMDConfiguration#getUri - - PMDConfiguration#setInputUri - It is now superseded by PMDConfiguration#setInputUri - - PMDConfiguration#getReportFile - It is now superseded by PMDConfiguration#getReportFilePath - - PMDConfiguration#setReportFile - It is now superseded by PMDConfiguration#setReportFile - - PMDConfiguration#isStressTest and PMDConfiguration#setStressTest - Will be removed with no replacement. - - PMDConfiguration#isBenchmark and PMDConfiguration#setBenchmark - Will be removed with no replacement, the CLI will still support it. - - CPD and `CPD.StatusCode` - PMD 7 will ship with a revamped CLI split from pmd-core. An alternative to programmatically launch CPD analysis will be added in due time. + - PMD and `PMD.StatusCode` - PMD 7 will ship with a revamped CLI split from pmd-core. To programmatically launch analysis you can use PmdAnalysis. + - PMDConfiguration#getAllInputPaths - It is now superseded by PMDConfiguration#getInputPathList + - PMDConfiguration#setInputPaths - It is now superseded by PMDConfiguration#setInputPathList + - PMDConfiguration#addInputPath - It is now superseded by PMDConfiguration#addInputPath + - PMDConfiguration#getInputFilePath - It is now superseded by PMDConfiguration#getInputFile + - PMDConfiguration#getIgnoreFilePath - It is now superseded by PMDConfiguration#getIgnoreFile + - PMDConfiguration#setInputFilePath - It is now superseded by PMDConfiguration#setInputFilePath + - PMDConfiguration#setIgnoreFilePath - It is now superseded by PMDConfiguration#setIgnoreFilePath + - PMDConfiguration#getInputUri - It is now superseded by PMDConfiguration#getUri + - PMDConfiguration#setInputUri - It is now superseded by PMDConfiguration#setInputUri + - PMDConfiguration#getReportFile - It is now superseded by PMDConfiguration#getReportFilePath + - PMDConfiguration#setReportFile - It is now superseded by PMDConfiguration#setReportFile + - PMDConfiguration#isStressTest and PMDConfiguration#setStressTest - Will be removed with no replacement. + - PMDConfiguration#isBenchmark and PMDConfiguration#setBenchmark - Will be removed with no replacement, the CLI will still support it. + - CPD and `CPD.StatusCode` - PMD 7 will ship with a revamped CLI split from pmd-core. An alternative to programmatically launch CPD analysis will be added in due time. * In order to reduce the dependency on Apex Jorje classes, the method DataType#fromBasicType has been deprecated. The equivalent method fromTypeName should be used instead. @@ -1831,11 +1831,11 @@ No changes. * In order to reduce the dependency on Apex Jorje classes, the following methods have been deprecated. These methods all leaked internal Jorje enums. These enums have been replaced now by enums the PMD's AST package. - * ASTAssignmentExpression#getOperator - * ASTBinaryExpression#getOperator - * ASTBooleanExpression#getOperator - * ASTPostfixExpression#getOperator - * ASTPrefixExpression#getOperator + * ASTAssignmentExpression#getOperator + * ASTBinaryExpression#getOperator + * ASTBooleanExpression#getOperator + * ASTPostfixExpression#getOperator + * ASTPrefixExpression#getOperator All these classes have now a new `getOp()` method. Existing code should be refactored to use this method instead. It returns the new enums, like AssignmentOperator, and avoids @@ -1855,11 +1855,11 @@ No changes. * The new module "pmd-test-schema" contains now the XSD schema and the code to parse the rule test XML files. The schema has been extracted in order to easily share it with other tools like the Rule Designer or IDE plugins. * Test schema changes: - * The attribute `isRegressionTest` of `test-code` is deprecated. The new - attribute `disabled` should be used instead for defining whether a rule test should be skipped or not. - * The attributes `reinitializeRule` and `useAuxClasspath` of `test-code` are deprecated and assumed true. - They will not be replaced. - * The new attribute `focused` of `test-code` allows disabling all tests except the focused one temporarily. + * The attribute `isRegressionTest` of `test-code` is deprecated. The new + attribute `disabled` should be used instead for defining whether a rule test should be skipped or not. + * The attributes `reinitializeRule` and `useAuxClasspath` of `test-code` are deprecated and assumed true. + They will not be replaced. + * The new attribute `focused` of `test-code` allows disabling all tests except the focused one temporarily. * More information about the rule test framework can be found in the documentation: [Testing your rules](pmd_userdocs_extending_testing.html) @@ -1877,9 +1877,9 @@ No changes. * To support the Java preview language features "Pattern Matching for Switch" and "Record Patterns", the following AST nodes have been introduced as experimental: - * ASTSwitchGuard - * ASTRecordPattern - * ASTComponentPatternList + * ASTSwitchGuard + * ASTRecordPattern + * ASTComponentPatternList **Internal API** @@ -1936,9 +1936,9 @@ You can identify them with the `@InternalApi` annotation. You'll also get a depr **Experimental APIs** * Report has two new methods which allow limited mutations of a given report: - * Report#filterViolations creates a new report with - some violations removed with a given predicate based filter. - * Report#union can combine two reports into a single new Report. + * Report#filterViolations creates a new report with + some violations removed with a given predicate based filter. + * Report#union can combine two reports into a single new Report. * net.sourceforge.pmd.util.Predicate will be replaced in PMD7 with the standard Predicate interface from java8. * The module `pmd-html` is entirely experimental right now. Anything in the package `net.sourceforge.pmd.lang.html` should be used cautiously. @@ -1948,10 +1948,10 @@ You can identify them with the `@InternalApi` annotation. You'll also get a depr **Deprecated API** * Several members of PMD have been newly deprecated, including: - - `PMD#EOL`: use `System#lineSeparator()` - - `PMD#SUPPRESS_MARKER`: use DEFAULT_SUPPRESS_MARKER - - `PMD#processFiles`: use the new programmatic API - - `PMD#getApplicableFiles`: is internal + - `PMD#EOL`: use `System#lineSeparator()` + - `PMD#SUPPRESS_MARKER`: use DEFAULT_SUPPRESS_MARKER + - `PMD#processFiles`: use the new programmatic API + - `PMD#getApplicableFiles`: is internal * PMDConfiguration#prependClasspath is deprecated in favour of prependAuxClasspath. * PMDConfiguration#setRuleSets and @@ -2104,10 +2104,10 @@ No changes. **Experimental APIs** * The AST types and APIs around Sealed Classes are not experimental anymore: - * ASTClassOrInterfaceDeclaration#isSealed, - ASTClassOrInterfaceDeclaration#isNonSealed, - ASTClassOrInterfaceDeclaration#getPermittedSubclasses - * ASTPermitsList +* ASTClassOrInterfaceDeclaration#isSealed, + ASTClassOrInterfaceDeclaration#isNonSealed, + ASTClassOrInterfaceDeclaration#getPermittedSubclasses +* ASTPermitsList **Internal API** @@ -2151,14 +2151,14 @@ No changes. * The experimental class `ASTRecordConstructorDeclaration` has been renamed to ASTCompactConstructorDeclaration in order to align the naming to the JLS. * The AST types and APIs around Pattern Matching and Records are not experimental anymore: - * ASTVariableId#isPatternBinding - * ASTPattern - * ASTTypePattern - * ASTRecordDeclaration - * ASTRecordComponentList - * ASTRecordComponent - * ASTRecordBody - * ASTCompactConstructorDeclaration +* ASTVariableId#isPatternBinding +* ASTPattern +* ASTTypePattern +* ASTRecordDeclaration +* ASTRecordComponentList +* ASTRecordComponent +* ASTRecordBody +* ASTCompactConstructorDeclaration **Internal API** @@ -2243,15 +2243,15 @@ No changes. * RuleReference#getOverriddenLanguage and RuleReference#setLanguage * Antlr4 generated lexers: - * net.sourceforge.pmd.lang.cs.antlr4.CSharpLexer will be moved to package `net.sourceforge.pmd.lang.cs.ast` with PMD 7. - * net.sourceforge.pmd.lang.dart.antlr4.Dart2Lexer will be renamed to `DartLexer` and moved to package - `net.sourceforge.pmd.lang.dart.ast` with PMD 7. All other classes in the old package will be removed. - * net.sourceforge.pmd.lang.go.antlr4.GolangLexer will be moved to package - `net.sourceforge.pmd.lang.go.ast` with PMD 7. All other classes in the old package will be removed. - * net.sourceforge.pmd.lang.kotlin.antlr4.Kotlin will be renamed to `KotlinLexer` and moved to package - `net.sourceforge.pmd.lang.kotlin.ast` with PMD 7. - * net.sourceforge.pmd.lang.lua.antlr4.LuaLexer will be moved to package - `net.sourceforge.pmd.lang.lua.ast` with PMD 7. All other classes in the old package will be removed. + * net.sourceforge.pmd.lang.cs.antlr4.CSharpLexer will be moved to package `net.sourceforge.pmd.lang.cs.ast` with PMD 7. + * net.sourceforge.pmd.lang.dart.antlr4.Dart2Lexer will be renamed to `DartLexer` and moved to package + `net.sourceforge.pmd.lang.dart.ast` with PMD 7. All other classes in the old package will be removed. + * net.sourceforge.pmd.lang.go.antlr4.GolangLexer will be moved to package + `net.sourceforge.pmd.lang.go.ast` with PMD 7. All other classes in the old package will be removed. + * net.sourceforge.pmd.lang.kotlin.antlr4.Kotlin will be renamed to `KotlinLexer` and moved to package + `net.sourceforge.pmd.lang.kotlin.ast` with PMD 7. + * net.sourceforge.pmd.lang.lua.antlr4.LuaLexer will be moved to package + `net.sourceforge.pmd.lang.lua.ast` with PMD 7. All other classes in the old package will be removed. #### 6.27.0 @@ -2412,10 +2412,10 @@ The following usages are now deprecated in the **Apex**, **Javascript**, **PL/SQ Those constructors will be made package private with 7.0.0. * **Subclassing of abstract node classes, or usage of their type**. The base classes are internal API and will be hidden in version 7.0.0. You should not couple your code to them. - * In the meantime you should use interfaces like VfNode or - Node, or the other published interfaces in this package, - to refer to nodes generically. - * Concrete node classes will **be made final** with 7.0.0. +* In the meantime you should use interfaces like VfNode or + Node, or the other published interfaces in this package, + to refer to nodes generically. +* Concrete node classes will **be made final** with 7.0.0. * Setters found in any node class or interface. **Rules should consider the AST immutable**. We will make those setters package private with 7.0.0. * The implementation classes of Parser (eg VfParser) are deprecated and should not be used directly. @@ -2506,49 +2506,49 @@ You can identify them with the `@InternalApi` annotation. You'll also get a depr **For removal** * pmd-core - * DFAGraphRule and its implementations - * DFAGraphMethod - * Many methods on the Node interface - and AbstractNode base class. See their javadoc for details. - * Node#isFindBoundary is deprecated for XPath queries. - * Many APIs of `net.sourceforge.pmd.lang.metrics`, though most of them were internal and - probably not used directly outside of PMD. Use MetricsUtil as - a replacement for the language-specific façades too. - * QualifiableNode, QualifiedName + * DFAGraphRule and its implementations + * DFAGraphMethod + * Many methods on the Node interface + and AbstractNode base class. See their javadoc for details. + * Node#isFindBoundary is deprecated for XPath queries. + * Many APIs of `net.sourceforge.pmd.lang.metrics`, though most of them were internal and + probably not used directly outside of PMD. Use MetricsUtil as + a replacement for the language-specific façades too. + * QualifiableNode, QualifiedName * pmd-java - * AbstractJavaParser - * AbstractJavaHandler - * [`ASTAnyTypeDeclaration.TypeKind`](https://docs.pmd-code.org/apidocs/pmd-java/6.55.0/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.TypeKind.html) - * ASTAnyTypeDeclaration#getTypeKind - * JavaQualifiedName - * ASTCatchStatement#getBlock - * ASTCompilationUnit#declarationsAreInDefaultPackage - * JavaQualifiableNode - * ASTAnyTypeDeclaration#getQualifiedName - * ASTMethodOrConstructorDeclaration#getQualifiedName - * ASTLambdaExpression#getQualifiedName - * net.sourceforge.pmd.lang.java.qname and its contents - * MethodLikeNode - * Its methods will also be removed from its implementations, - ASTMethodOrConstructorDeclaration, - ASTLambdaExpression. - * ASTAnyTypeDeclaration#getImage will be removed. Please use `getSimpleName()` - instead. This affects ASTAnnotationTypeDeclaration#getImage, - ASTClassOrInterfaceDeclaration#getImage, and - ASTEnumDeclaration#getImage. - * Several methods of ASTTryStatement, replacements with other names - have been added. This includes the XPath attribute `@Finally`, replace it with a test for `child::FinallyStatement`. - * Several methods named `getGuardExpressionNode` are replaced with `getCondition`. This affects the - following nodes: WhileStatement, DoStatement, ForStatement, IfStatement, AssertStatement, ConditionalExpression. - * ASTYieldStatement will not implement TypeNode - anymore come 7.0.0. Test the type of the expression nested within it. - * JavaMetrics, JavaMetricsComputer - * ASTArguments#getArgumentCount. - Use size instead. - * ASTFormalParameters#getParameterCount. - Use size instead. + * AbstractJavaParser + * AbstractJavaHandler + * [`ASTAnyTypeDeclaration.TypeKind`](https://docs.pmd-code.org/apidocs/pmd-java/6.55.0/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.TypeKind.html) + * ASTAnyTypeDeclaration#getTypeKind + * JavaQualifiedName + * ASTCatchStatement#getBlock + * ASTCompilationUnit#declarationsAreInDefaultPackage + * JavaQualifiableNode + * ASTAnyTypeDeclaration#getQualifiedName + * ASTMethodOrConstructorDeclaration#getQualifiedName + * ASTLambdaExpression#getQualifiedName + * net.sourceforge.pmd.lang.java.qname and its contents + * MethodLikeNode + * Its methods will also be removed from its implementations, + ASTMethodOrConstructorDeclaration, + ASTLambdaExpression. + * ASTAnyTypeDeclaration#getImage will be removed. Please use `getSimpleName()` + instead. This affects ASTAnnotationTypeDeclaration#getImage, + ASTClassOrInterfaceDeclaration#getImage, and + ASTEnumDeclaration#getImage. + * Several methods of ASTTryStatement, replacements with other names + have been added. This includes the XPath attribute `@Finally`, replace it with a test for `child::FinallyStatement`. + * Several methods named `getGuardExpressionNode` are replaced with `getCondition`. This affects the + following nodes: WhileStatement, DoStatement, ForStatement, IfStatement, AssertStatement, ConditionalExpression. + * ASTYieldStatement will not implement TypeNode + anymore come 7.0.0. Test the type of the expression nested within it. + * JavaMetrics, JavaMetricsComputer + * ASTArguments#getArgumentCount. + Use size instead. + * ASTFormalParameters#getParameterCount. + Use size instead. * pmd-apex - * ApexMetrics, ApexMetricsComputer + * ApexMetrics, ApexMetricsComputer **In ASTs (JSP)** @@ -2562,10 +2562,10 @@ The following usages are now deprecated **in the JSP AST** (with other languages Those constructors will be made package private with 7.0.0. * **Subclassing of abstract node classes, or usage of their type**. The base classes are internal API and will be hidden in version 7.0.0. You should not couple your code to them. - * In the meantime you should use interfaces like JspNode or - Node, or the other published interfaces in this package, - to refer to nodes generically. - * Concrete node classes will **be made final** with 7.0.0. +* In the meantime you should use interfaces like JspNode or + Node, or the other published interfaces in this package, + to refer to nodes generically. +* Concrete node classes will **be made final** with 7.0.0. * Setters found in any node class or interface. **Rules should consider the AST immutable**. We will make those setters package private with 7.0.0. * The class JspParser is deprecated and should not be used directly. @@ -2585,10 +2585,10 @@ The following usages are now deprecated **in the VM AST** (with other languages Those constructors will be made package private with 7.0.0. * **Subclassing of abstract node classes, or usage of their type**. The base classes are internal API and will be hidden in version 7.0.0. You should not couple your code to them. - * In the meantime you should use interfaces like VtlNode or - Node, or the other published interfaces in this package, - to refer to nodes generically. - * Concrete node classes will **be made final** with 7.0.0. +* In the meantime you should use interfaces like VtlNode or + Node, or the other published interfaces in this package, + to refer to nodes generically. +* Concrete node classes will **be made final** with 7.0.0. * Setters found in any node class or interface. **Rules should consider the AST immutable**. We will make those setters package private with 7.0.0. * The package net.sourceforge.pmd.lang.vm.directive as well as the classes @@ -2645,36 +2645,36 @@ You can identify them with the `@InternalApi` annotation. You'll also get a depr **For removal** * pmd-core - * Many methods on the Node interface - and AbstractNode base class. See their javadoc for details. - * Node#isFindBoundary is deprecated for XPath queries. + * Many methods on the Node interface + and AbstractNode base class. See their javadoc for details. + * Node#isFindBoundary is deprecated for XPath queries. * pmd-java - * AbstractJavaParser - * AbstractJavaHandler - * [`ASTAnyTypeDeclaration.TypeKind`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.55.0/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.TypeKind.html) - * ASTAnyTypeDeclaration#getTypeKind - * JavaQualifiedName - * ASTCatchStatement#getBlock - * ASTCompilationUnit#declarationsAreInDefaultPackage - * JavaQualifiableNode - * ASTAnyTypeDeclaration#getQualifiedName - * ASTMethodOrConstructorDeclaration#getQualifiedName - * ASTLambdaExpression#getQualifiedName - * net.sourceforge.pmd.lang.java.qname and its contents - * MethodLikeNode - * Its methods will also be removed from its implementations, - ASTMethodOrConstructorDeclaration, - ASTLambdaExpression. - * ASTAnyTypeDeclaration#getImage will be removed. Please use `getSimpleName()` - instead. This affects ASTAnnotationTypeDeclaration#getImage, - ASTClassOrInterfaceDeclaration#getImage, and - ASTEnumDeclaration#getImage. - * Several methods of ASTTryStatement, replacements with other names - have been added. This includes the XPath attribute `@Finally`, replace it with a test for `child::FinallyStatement`. - * Several methods named `getGuardExpressionNode` are replaced with `getCondition`. This affects the - following nodes: WhileStatement, DoStatement, ForStatement, IfStatement, AssertStatement, ConditionalExpression. - * ASTYieldStatement will not implement TypeNode - anymore come 7.0.0. Test the type of the expression nested within it. + * AbstractJavaParser + * AbstractJavaHandler + * [`ASTAnyTypeDeclaration.TypeKind`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.55.0/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.TypeKind.html) + * ASTAnyTypeDeclaration#getTypeKind + * JavaQualifiedName + * ASTCatchStatement#getBlock + * ASTCompilationUnit#declarationsAreInDefaultPackage + * JavaQualifiableNode + * ASTAnyTypeDeclaration#getQualifiedName + * ASTMethodOrConstructorDeclaration#getQualifiedName + * ASTLambdaExpression#getQualifiedName + * net.sourceforge.pmd.lang.java.qname and its contents + * MethodLikeNode + * Its methods will also be removed from its implementations, + ASTMethodOrConstructorDeclaration, + ASTLambdaExpression. + * ASTAnyTypeDeclaration#getImage will be removed. Please use `getSimpleName()` + instead. This affects ASTAnnotationTypeDeclaration#getImage, + ASTClassOrInterfaceDeclaration#getImage, and + ASTEnumDeclaration#getImage. + * Several methods of ASTTryStatement, replacements with other names + have been added. This includes the XPath attribute `@Finally`, replace it with a test for `child::FinallyStatement`. + * Several methods named `getGuardExpressionNode` are replaced with `getCondition`. This affects the + following nodes: WhileStatement, DoStatement, ForStatement, IfStatement, AssertStatement, ConditionalExpression. + * ASTYieldStatement will not implement TypeNode + anymore come 7.0.0. Test the type of the expression nested within it. #### 6.20.0 @@ -2687,39 +2687,39 @@ No changes. **For removal** * pmd-core - * All the package net.sourceforge.pmd.dcd and its subpackages. See DCD. - * In LanguageRegistry: - * commaSeparatedTerseNamesForLanguageVersion - * commaSeparatedTerseNamesForLanguage - * findAllVersions - * findLanguageVersionByTerseName - * getInstance - * RuleSet#getExcludePatterns. Use the new method getFileExclusions instead. - * RuleSet#getIncludePatterns. Use the new method getFileInclusions instead. - * Parser#canParse - * Parser#getSuppressMap - * RuleBuilder#RuleBuilder. Use the new constructor with the correct ResourceLoader instead. - * RuleFactory#RuleFactory. Use the new constructor with the correct ResourceLoader instead. + * All the package net.sourceforge.pmd.dcd and its subpackages. See DCD. + * In LanguageRegistry: + * commaSeparatedTerseNamesForLanguageVersion + * commaSeparatedTerseNamesForLanguage + * findAllVersions + * findLanguageVersionByTerseName + * getInstance + * RuleSet#getExcludePatterns. Use the new method getFileExclusions instead. + * RuleSet#getIncludePatterns. Use the new method getFileInclusions instead. + * Parser#canParse + * Parser#getSuppressMap + * RuleBuilder#RuleBuilder. Use the new constructor with the correct ResourceLoader instead. + * RuleFactory#RuleFactory. Use the new constructor with the correct ResourceLoader instead. * pmd-java - * CanSuppressWarnings and its implementations - * isSuppressed - * getDeclaringType. - * isSupressed - * ASTMethodDeclarator - * getMethodName - * getBlock - * getParameterCount + * CanSuppressWarnings and its implementations + * isSuppressed + * getDeclaringType. + * isSupressed + * ASTMethodDeclarator + * getMethodName + * getBlock + * getParameterCount * pmd-apex - * CanSuppressWarnings and its implementations - * isSupressed + * CanSuppressWarnings and its implementations + * isSupressed **Internal APIs** * pmd-core - * All the package net.sourceforge.pmd.util and its subpackages, - except net.sourceforge.pmd.util.datasource and net.sourceforge.pmd.util.database. - * GridBagHelper - * ColumnDescriptor + * All the package net.sourceforge.pmd.util and its subpackages, + except net.sourceforge.pmd.util.datasource and net.sourceforge.pmd.util.database. + * GridBagHelper + * ColumnDescriptor #### 6.18.0 @@ -2758,12 +2758,12 @@ No changes. Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0. You can identify them with the `@InternalApi` annotation. You'll also get a deprecation warning. * pmd-core - * net.sourceforge.pmd.cache + * net.sourceforge.pmd.cache * pmd-java - * net.sourceforge.pmd.lang.java.typeresolution: Everything, including - subpackages, except TypeHelper and - JavaTypeDefinition. - * ASTCompilationUnit#getClassTypeResolver + * net.sourceforge.pmd.lang.java.typeresolution: Everything, including + subpackages, except TypeHelper and + JavaTypeDefinition. + * ASTCompilationUnit#getClassTypeResolver #### 6.17.0 @@ -2789,9 +2789,9 @@ The following usages are now deprecated **in the Java AST** (with other language that never need to instantiate node themselves. Those constructors will be made package private with 7.0.0. * **Subclassing of abstract node classes, or usage of their type**. Version 7.0.0 will bring a new set of abstractions that will be public API, but the base classes are and will stay internal. You should not couple your code to them. - * In the meantime you should use interfaces like JavaNode or - Node, or the other published interfaces in this package, to refer to nodes generically. - * Concrete node classes will **be made final** with 7.0.0. + * In the meantime you should use interfaces like JavaNode or + Node, or the other published interfaces in this package, to refer to nodes generically. + * Concrete node classes will **be made final** with 7.0.0. * Setters found in any node class or interface. **Rules should consider the AST immutable**. We will make those setters package private with 7.0.0. @@ -2807,14 +2807,14 @@ of deprecations. * The `DumpFacades` in all languages, that could be used to transform a AST into a textual representation, will be removed with PMD 7. The rule designer is a better way to inspect nodes. - * net.sourceforge.pmd.lang.apex.ast.DumpFacade - * net.sourceforge.pmd.lang.java.ast.DumpFacade - * net.sourceforge.pmd.lang.ecmascript.ast.DumpFacade - * net.sourceforge.pmd.lang.jsp.ast.DumpFacade - * net.sourceforge.pmd.lang.plsql.ast.DumpFacade - * net.sourceforge.pmd.lang.vf.ast.DumpFacade - * net.sourceforge.pmd.lang.vm.ast.AbstractVmNode#dump - * net.sourceforge.pmd.lang.xml.ast.DumpFacade +* net.sourceforge.pmd.lang.apex.ast.DumpFacade +* net.sourceforge.pmd.lang.java.ast.DumpFacade +* net.sourceforge.pmd.lang.ecmascript.ast.DumpFacade +* net.sourceforge.pmd.lang.jsp.ast.DumpFacade +* net.sourceforge.pmd.lang.plsql.ast.DumpFacade +* net.sourceforge.pmd.lang.vf.ast.DumpFacade +* net.sourceforge.pmd.lang.vm.ast.AbstractVmNode#dump +* net.sourceforge.pmd.lang.xml.ast.DumpFacade * The method LanguageVersionHandler#getDumpFacade will be removed as well. It is deprecated, along with all its implementations in the subclasses of LanguageVersionHandler. @@ -2880,32 +2880,32 @@ to remove them in 7.0.0. The proposed changes to the API are described [on the w * Instead of spreading properties across countless classes, the utility class PropertyFactory will become from 7.0.0 on the only provider for property descriptor builders. Each current property type will be replaced by a corresponding method on `PropertyFactory`: - * IntegerProperty is replaced by PropertyFactory#intProperty - * IntegerMultiProperty is replaced by PropertyFactory#intListProperty + * IntegerProperty is replaced by PropertyFactory#intProperty + * IntegerMultiProperty is replaced by PropertyFactory#intListProperty - * FloatProperty and DoubleProperty are both replaced by PropertyFactory#doubleProperty. - Having a separate property for floats wasn't that useful. - * Similarly, FloatMultiProperty and DoubleMultiProperty are replaced by PropertyFactory#doubleListProperty. + * FloatProperty and DoubleProperty are both replaced by PropertyFactory#doubleProperty. + Having a separate property for floats wasn't that useful. + * Similarly, FloatMultiProperty and DoubleMultiProperty are replaced by PropertyFactory#doubleListProperty. - * StringProperty is replaced by PropertyFactory#stringProperty - * StringMultiProperty is replaced by PropertyFactory#stringListProperty + * StringProperty is replaced by PropertyFactory#stringProperty + * StringMultiProperty is replaced by PropertyFactory#stringListProperty - * RegexProperty is replaced by PropertyFactory#regexProperty + * RegexProperty is replaced by PropertyFactory#regexProperty - * EnumeratedProperty is replaced by PropertyFactory#enumProperty - * EnumeratedProperty is replaced by PropertyFactory#enumListProperty + * EnumeratedProperty is replaced by PropertyFactory#enumProperty + * EnumeratedProperty is replaced by PropertyFactory#enumListProperty - * BooleanProperty is replaced by PropertyFactory#booleanProperty - * Its multi-valued counterpart, BooleanMultiProperty, is not replaced, because it doesn't have a use case. + * BooleanProperty is replaced by PropertyFactory#booleanProperty + * Its multi-valued counterpart, BooleanMultiProperty, is not replaced, because it doesn't have a use case. - * CharacterProperty is replaced by PropertyFactory#charProperty - * CharacterMultiProperty is replaced by PropertyFactory#charListProperty + * CharacterProperty is replaced by PropertyFactory#charProperty + * CharacterMultiProperty is replaced by PropertyFactory#charListProperty - * LongProperty is replaced by PropertyFactory#longIntProperty - * LongMultiProperty is replaced by PropertyFactory#longIntListProperty + * LongProperty is replaced by PropertyFactory#longIntProperty + * LongMultiProperty is replaced by PropertyFactory#longIntListProperty - * MethodProperty, FileProperty, TypeProperty and their multi-valued counterparts - are discontinued for lack of a use-case, and have no planned replacement in 7.0.0 for now. + * MethodProperty, FileProperty, TypeProperty and their multi-valued counterparts + are discontinued for lack of a use-case, and have no planned replacement in 7.0.0 for now. Here's an example: @@ -2994,56 +2994,56 @@ You're highly encouraged to migrate to using this new API as soon as possible, t * Several methods from ASTLocalVariableDeclaration and ASTFieldDeclaration have also been deprecated: - * ASTFieldDeclaration won't be a TypeNode come 7.0.0, so - getType and - getTypeDefinition are deprecated. +* ASTFieldDeclaration won't be a TypeNode come 7.0.0, so + getType and + getTypeDefinition are deprecated. - * The method `getVariableName` on those two nodes will be removed, too. +* The method `getVariableName` on those two nodes will be removed, too. - * All these are deprecated because those nodes may declare several variables at once, possibly - with different types (and obviously with different names). They both implement `Iterator<`ASTVariableId`>` - though, so you should iterate on each declared variable. See [#910](https://github.com/pmd/pmd/issues/910). +* All these are deprecated because those nodes may declare several variables at once, possibly + with different types (and obviously with different names). They both implement `Iterator<`ASTVariableId`>` + though, so you should iterate on each declared variable. See [#910](https://github.com/pmd/pmd/issues/910). * Visitor decorators are now deprecated and will be removed in PMD 7.0.0. They were originally a way to write composable visitors, used in the metrics framework, but they didn't prove cost-effective. - * In net.sourceforge.pmd.lang.java.ast: JavaParserDecoratedVisitor, JavaParserControllessVisitor, - JavaParserControllessVisitorAdapter, and JavaParserVisitorDecorator are deprecated with no intended replacement. +* In net.sourceforge.pmd.lang.java.ast: JavaParserDecoratedVisitor, JavaParserControllessVisitor, + JavaParserControllessVisitorAdapter, and JavaParserVisitorDecorator are deprecated with no intended replacement. * The LanguageModules of several languages, that only support CPD execution, have been deprecated. These languages are not fully supported by PMD, so having a language module does not make sense. The functionality of CPD is not affected by this change. The following classes have been deprecated and will be removed with PMD 7.0.0: - * CppHandler - * CppLanguageModule - * CppParser - * CsLanguageModule - * FortranLanguageModule - * GroovyLanguageModule - * MatlabHandler - * MatlabLanguageModule - * MatlabParser - * ObjectiveCHandler - * ObjectiveCLanguageModule - * ObjectiveCParser - * PhpLanguageModule - * PythonHandler - * PythonLanguageModule - * PythonParser - * RubyLanguageModule +* CppHandler +* CppLanguageModule +* CppParser +* CsLanguageModule +* FortranLanguageModule +* GroovyLanguageModule +* MatlabHandler +* MatlabLanguageModule +* MatlabParser +* ObjectiveCHandler +* ObjectiveCLanguageModule +* ObjectiveCParser +* PhpLanguageModule +* PythonHandler +* PythonLanguageModule +* PythonParser +* RubyLanguageModule * Optional AST processing stages like symbol table, type resolution or data-flow analysis will be reified in 7.0.0 to factorise common logic and make them extensible. Further explanations about this change can be found on [#1426](https://github.com/pmd/pmd/pull/1426). Consequently, the following APIs are deprecated for removal: - * In Rule: isDfa(), isTypeResolution(), isMultifile() and their - respective setters. - * In RuleSet: usesDFA(Language), usesTypeResolution(Language), usesMultifile(Language) - * In RuleSets: usesDFA(Language), usesTypeResolution(Language), usesMultifile(Language) - * In LanguageVersionHandler: getDataFlowFacade(), getSymbolFacade(), getSymbolFacade(ClassLoader), - getTypeResolutionFacade(ClassLoader), getQualifiedNameResolutionFacade(ClassLoader) + * In Rule: isDfa(), isTypeResolution(), isMultifile() and their + respective setters. + * In RuleSet: usesDFA(Language), usesTypeResolution(Language), usesMultifile(Language) + * In RuleSets: usesDFA(Language), usesTypeResolution(Language), usesMultifile(Language) + * In LanguageVersionHandler: getDataFlowFacade(), getSymbolFacade(), getSymbolFacade(ClassLoader), + getTypeResolutionFacade(ClassLoader), getQualifiedNameResolutionFacade(ClassLoader) #### 6.9.0 @@ -3120,9 +3120,9 @@ No changes. * The method getXPathNodeName is added to the Node interface, which removes the use of `toString` of a node to get its XPath element name (see [#569](https://github.com/pmd/pmd/issues/569)). - * The default implementation provided in AbstractNode, will be removed with 7.0.0 - * With 7.0.0, the `Node.toString` method will not necessarily provide its XPath node - name anymore. + * The default implementation provided in AbstractNode, will be removed with 7.0.0 + * With 7.0.0, the `Node.toString` method will not necessarily provide its XPath node + name anymore. * The interface net.sourceforge.pmd.cpd.Renderer has been deprecated. A new interface CPDRenderer has been introduced to replace it. The main @@ -3141,343 +3141,343 @@ No changes. ## 🐛 Fixed Issues * miscellaneous - * [#881](https://github.com/pmd/pmd/issues/881): \[all] Breaking API changes for 7.0.0 - * [#896](https://github.com/pmd/pmd/issues/896): \[all] Use slf4j - * [#1431](https://github.com/pmd/pmd/pull/1431): \[ui] Remove old GUI applications (designerold, bgastviewer) - * [#1451](https://github.com/pmd/pmd/issues/1451): \[core] RulesetFactoryCompatibility stores the whole ruleset file in memory as a string - * [#2496](https://github.com/pmd/pmd/issues/2496): Update PMD 7 Logo on landing page - * [#2497](https://github.com/pmd/pmd/issues/2497): PMD 7 Logo page - * [#2498](https://github.com/pmd/pmd/issues/2498): Update PMD 7 Logo in documentation - * [#3797](https://github.com/pmd/pmd/issues/3797): \[all] Use JUnit5 - * [#4462](https://github.com/pmd/pmd/issues/4462): Provide Software Bill of Materials (SBOM) - * [#4460](https://github.com/pmd/pmd/pull/4460): Fix assembly-plugin warnings - * [#4582](https://github.com/pmd/pmd/issues/4582): \[dist] Download link broken - * [#4586](https://github.com/pmd/pmd/pull/4586): Use explicit encoding in ruleset xml files - * [#4642](https://github.com/pmd/pmd/issues/4642): Update regression tests with Java 21 language features - * [#4691](https://github.com/pmd/pmd/issues/4691): \[CVEs] Critical and High CEVs reported on PMD and PMD dependencies - * [#4699](https://github.com/pmd/pmd/pull/4699): Make PMD buildable with java 21 - * [#4736](https://github.com/pmd/pmd/issues/4736): \[ci] Improve build procedure - * [#4741](https://github.com/pmd/pmd/pull/4741): Add pmd-compat6 module for maven-pmd-plugin - * [#4749](https://github.com/pmd/pmd/pull/4749): Fixes NoSuchMethodError on processing errors in pmd-compat6 - * [#4776](https://github.com/pmd/pmd/issues/4776): \[ci] Upgrade to ruby 3 - * [#4796](https://github.com/pmd/pmd/pull/4796): Remove deprecated and release rulesets - * [#4823](https://github.com/pmd/pmd/pull/4823): Update to use renamed pmd-designer - * [#4827](https://github.com/pmd/pmd/pull/4827): \[compat6] Support config errors and cpd for csharp - * [#4830](https://github.com/pmd/pmd/issues/4830): Consolidate packages in each maven module - * [#4867](https://github.com/pmd/pmd/issues/4867): \[dist] ./mvnw command not found in dist-src + * [#881](https://github.com/pmd/pmd/issues/881): \[all] Breaking API changes for 7.0.0 + * [#896](https://github.com/pmd/pmd/issues/896): \[all] Use slf4j + * [#1431](https://github.com/pmd/pmd/pull/1431): \[ui] Remove old GUI applications (designerold, bgastviewer) + * [#1451](https://github.com/pmd/pmd/issues/1451): \[core] RulesetFactoryCompatibility stores the whole ruleset file in memory as a string + * [#2496](https://github.com/pmd/pmd/issues/2496): Update PMD 7 Logo on landing page + * [#2497](https://github.com/pmd/pmd/issues/2497): PMD 7 Logo page + * [#2498](https://github.com/pmd/pmd/issues/2498): Update PMD 7 Logo in documentation + * [#3797](https://github.com/pmd/pmd/issues/3797): \[all] Use JUnit5 + * [#4462](https://github.com/pmd/pmd/issues/4462): Provide Software Bill of Materials (SBOM) + * [#4460](https://github.com/pmd/pmd/pull/4460): Fix assembly-plugin warnings + * [#4582](https://github.com/pmd/pmd/issues/4582): \[dist] Download link broken + * [#4586](https://github.com/pmd/pmd/pull/4586): Use explicit encoding in ruleset xml files + * [#4642](https://github.com/pmd/pmd/issues/4642): Update regression tests with Java 21 language features + * [#4691](https://github.com/pmd/pmd/issues/4691): \[CVEs] Critical and High CEVs reported on PMD and PMD dependencies + * [#4699](https://github.com/pmd/pmd/pull/4699): Make PMD buildable with java 21 + * [#4736](https://github.com/pmd/pmd/issues/4736): \[ci] Improve build procedure + * [#4741](https://github.com/pmd/pmd/pull/4741): Add pmd-compat6 module for maven-pmd-plugin + * [#4749](https://github.com/pmd/pmd/pull/4749): Fixes NoSuchMethodError on processing errors in pmd-compat6 + * [#4776](https://github.com/pmd/pmd/issues/4776): \[ci] Upgrade to ruby 3 + * [#4796](https://github.com/pmd/pmd/pull/4796): Remove deprecated and release rulesets + * [#4823](https://github.com/pmd/pmd/pull/4823): Update to use renamed pmd-designer + * [#4827](https://github.com/pmd/pmd/pull/4827): \[compat6] Support config errors and cpd for csharp + * [#4830](https://github.com/pmd/pmd/issues/4830): Consolidate packages in each maven module + * [#4867](https://github.com/pmd/pmd/issues/4867): \[dist] ./mvnw command not found in dist-src * ant - * [#4080](https://github.com/pmd/pmd/issues/4080): \[ant] Split off Ant integration into a new submodule + * [#4080](https://github.com/pmd/pmd/issues/4080): \[ant] Split off Ant integration into a new submodule * core - * [#880](https://github.com/pmd/pmd/issues/880): \[core] Make visitors generic - * [#1027](https://github.com/pmd/pmd/issues/1027): \[core] Apply the new PropertyDescriptor<Pattern> type where applicable - * [#1204](https://github.com/pmd/pmd/issues/1204): \[core] Allow numeric properties in XML to be within an unbounded range - * [#1622](https://github.com/pmd/pmd/pull/1622): \[core] NodeStream API - * [#1687](https://github.com/pmd/pmd/issues/1687): \[core] Deprecate and Remove XPath 1.0 support - * [#1785](https://github.com/pmd/pmd/issues/1785): \[core] Allow abstract node types to be valid rulechain visits - * [#1825](https://github.com/pmd/pmd/pull/1825): \[core] Support NoAttribute for XPath - * [#2038](https://github.com/pmd/pmd/issues/2038): \[core] Remove DCD - * [#2218](https://github.com/pmd/pmd/issues/2218): \[core] `isFindBoundary` should not be an attribute - * [#2234](https://github.com/pmd/pmd/issues/2234): \[core] Consolidate PMD CLI into a single command - * [#2239](https://github.com/pmd/pmd/issues/2239): \[core] Merging Javacc build scripts - * [#2500](https://github.com/pmd/pmd/issues/2500): \[core] Clarify API for ANTLR based languages - * [#2518](https://github.com/pmd/pmd/issues/2518): \[core] Language properties - * [#2602](https://github.com/pmd/pmd/issues/2602): \[core] Remove ParserOptions - * [#2614](https://github.com/pmd/pmd/pull/2614): \[core] Upgrade Saxon, add XPath 3.1, remove Jaxen - * [#2696](https://github.com/pmd/pmd/pull/2696): \[core] Remove DFA - * [#2821](https://github.com/pmd/pmd/issues/2821): \[core] Rule processing error filenames are missing paths - * [#2873](https://github.com/pmd/pmd/issues/2873): \[core] Utility classes in pmd 7 - * [#2885](https://github.com/pmd/pmd/issues/2885): \[core] Error recovery mode - * [#3203](https://github.com/pmd/pmd/issues/3203): \[core] Replace RuleViolationFactory implementations with ViolationDecorator - * [#3692](https://github.com/pmd/pmd/pull/3692): \[core] Analysis listeners - * [#3782](https://github.com/pmd/pmd/issues/3782): \[core] Language lifecycle - * [#3815](https://github.com/pmd/pmd/issues/3815): \[core] Update Saxon HE to 10.7 - * [#3893](https://github.com/pmd/pmd/pull/3893): \[core] Text documents - * [#3902](https://github.com/pmd/pmd/issues/3902): \[core] Violation decorators - * [#3903](https://github.com/pmd/pmd/issues/3903): \[core] Consolidate `n.s.pmd.reporting` package - * [#3905](https://github.com/pmd/pmd/issues/3905): \[core] Stabilize tree export API - * [#3917](https://github.com/pmd/pmd/issues/3917): \[core] Consolidate `n.s.pmd.lang.rule` package - * [#3918](https://github.com/pmd/pmd/issues/3918): \[core] Make LanguageRegistry non static - * [#3919](https://github.com/pmd/pmd/issues/3919): \[core] Merge CPD and PMD language - * [#3922](https://github.com/pmd/pmd/pull/3922): \[core] Better error reporting for the ruleset parser - * [#4035](https://github.com/pmd/pmd/issues/4035): \[core] ConcurrentModificationException in DefaultRuleViolationFactory - * [#4065](https://github.com/pmd/pmd/issues/4065): \[core] Rename TokenMgrError to LexException, Tokenizer to CpdLexer - * [#4120](https://github.com/pmd/pmd/issues/4120): \[core] Explicitly name all language versions - * [#4204](https://github.com/pmd/pmd/issues/4204): \[core] Provide a CpdAnalysis class as a programmatic entry point into CPD - * [#4301](https://github.com/pmd/pmd/issues/4301): \[core] Remove deprecated property concrete classes - * [#4302](https://github.com/pmd/pmd/issues/4302): \[core] Migrate Property Framework API to Java 8 - * [#4309](https://github.com/pmd/pmd/issues/4309): \[core] Cleanups in XPath area - * [#4312](https://github.com/pmd/pmd/issues/4312): \[core] Remove unnecessary property `color` and system property `pmd.color` in `TextColorRenderer` - * [#4313](https://github.com/pmd/pmd/issues/4313): \[core] Remove support for <lang>-<ruleset> hyphen notation for ruleset references - * [#4314](https://github.com/pmd/pmd/issues/4314): \[core] Remove ruleset compatibility filter (RuleSetFactoryCompatibility) and CLI option `--no-ruleset-compatibility` - * [#4323](https://github.com/pmd/pmd/issues/4323): \[core] Refactor CPD integration - * [#4348](https://github.com/pmd/pmd/issues/4348): \[core] Consolidate @InternalApi classes - * [#4349](https://github.com/pmd/pmd/issues/4349): \[core] Cleanup remaining experimental and deprecated API - * [#4353](https://github.com/pmd/pmd/pull/4353): \[core] Micro optimizations for Node API - * [#4365](https://github.com/pmd/pmd/pull/4365): \[core] Improve benchmarking - * [#4397](https://github.com/pmd/pmd/pull/4397): \[core] Refactor CPD - * [#4378](https://github.com/pmd/pmd/issues/4378): \[core] Ruleset loading processes commented rules - * [#4420](https://github.com/pmd/pmd/pull/4420): \[core] Remove PMD.EOL - * [#4425](https://github.com/pmd/pmd/pull/4425): \[core] Replace TextFile::pathId - * [#4454](https://github.com/pmd/pmd/issues/4454): \[core] "Unknown option: '-min'" but is referenced in documentation - * [#4611](https://github.com/pmd/pmd/pull/4611): \[core] Fix loading language properties from env vars - * [#4621](https://github.com/pmd/pmd/issues/4621): \[core] Make `ClasspathClassLoader::getResource` child first - * [#4674](https://github.com/pmd/pmd/issues/4674): \[core] WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass - * [#4694](https://github.com/pmd/pmd/pull/4694): \[core] Fix line/col numbers in TokenMgrError - * [#4717](https://github.com/pmd/pmd/issues/4717): \[core] XSLTRenderer doesn't close report file - * [#4750](https://github.com/pmd/pmd/pull/4750): \[core] Fix flaky SummaryHTMLRenderer - * [#4782](https://github.com/pmd/pmd/pull/4782): \[core] Avoid using getImage/@Image + * [#880](https://github.com/pmd/pmd/issues/880): \[core] Make visitors generic + * [#1027](https://github.com/pmd/pmd/issues/1027): \[core] Apply the new PropertyDescriptor<Pattern> type where applicable + * [#1204](https://github.com/pmd/pmd/issues/1204): \[core] Allow numeric properties in XML to be within an unbounded range + * [#1622](https://github.com/pmd/pmd/pull/1622): \[core] NodeStream API + * [#1687](https://github.com/pmd/pmd/issues/1687): \[core] Deprecate and Remove XPath 1.0 support + * [#1785](https://github.com/pmd/pmd/issues/1785): \[core] Allow abstract node types to be valid rulechain visits + * [#1825](https://github.com/pmd/pmd/pull/1825): \[core] Support NoAttribute for XPath + * [#2038](https://github.com/pmd/pmd/issues/2038): \[core] Remove DCD + * [#2218](https://github.com/pmd/pmd/issues/2218): \[core] `isFindBoundary` should not be an attribute + * [#2234](https://github.com/pmd/pmd/issues/2234): \[core] Consolidate PMD CLI into a single command + * [#2239](https://github.com/pmd/pmd/issues/2239): \[core] Merging Javacc build scripts + * [#2500](https://github.com/pmd/pmd/issues/2500): \[core] Clarify API for ANTLR based languages + * [#2518](https://github.com/pmd/pmd/issues/2518): \[core] Language properties + * [#2602](https://github.com/pmd/pmd/issues/2602): \[core] Remove ParserOptions + * [#2614](https://github.com/pmd/pmd/pull/2614): \[core] Upgrade Saxon, add XPath 3.1, remove Jaxen + * [#2696](https://github.com/pmd/pmd/pull/2696): \[core] Remove DFA + * [#2821](https://github.com/pmd/pmd/issues/2821): \[core] Rule processing error filenames are missing paths + * [#2873](https://github.com/pmd/pmd/issues/2873): \[core] Utility classes in pmd 7 + * [#2885](https://github.com/pmd/pmd/issues/2885): \[core] Error recovery mode + * [#3203](https://github.com/pmd/pmd/issues/3203): \[core] Replace RuleViolationFactory implementations with ViolationDecorator + * [#3692](https://github.com/pmd/pmd/pull/3692): \[core] Analysis listeners + * [#3782](https://github.com/pmd/pmd/issues/3782): \[core] Language lifecycle + * [#3815](https://github.com/pmd/pmd/issues/3815): \[core] Update Saxon HE to 10.7 + * [#3893](https://github.com/pmd/pmd/pull/3893): \[core] Text documents + * [#3902](https://github.com/pmd/pmd/issues/3902): \[core] Violation decorators + * [#3903](https://github.com/pmd/pmd/issues/3903): \[core] Consolidate `n.s.pmd.reporting` package + * [#3905](https://github.com/pmd/pmd/issues/3905): \[core] Stabilize tree export API + * [#3917](https://github.com/pmd/pmd/issues/3917): \[core] Consolidate `n.s.pmd.lang.rule` package + * [#3918](https://github.com/pmd/pmd/issues/3918): \[core] Make LanguageRegistry non static + * [#3919](https://github.com/pmd/pmd/issues/3919): \[core] Merge CPD and PMD language + * [#3922](https://github.com/pmd/pmd/pull/3922): \[core] Better error reporting for the ruleset parser + * [#4035](https://github.com/pmd/pmd/issues/4035): \[core] ConcurrentModificationException in DefaultRuleViolationFactory + * [#4065](https://github.com/pmd/pmd/issues/4065): \[core] Rename TokenMgrError to LexException, Tokenizer to CpdLexer + * [#4120](https://github.com/pmd/pmd/issues/4120): \[core] Explicitly name all language versions + * [#4204](https://github.com/pmd/pmd/issues/4204): \[core] Provide a CpdAnalysis class as a programmatic entry point into CPD + * [#4301](https://github.com/pmd/pmd/issues/4301): \[core] Remove deprecated property concrete classes + * [#4302](https://github.com/pmd/pmd/issues/4302): \[core] Migrate Property Framework API to Java 8 + * [#4309](https://github.com/pmd/pmd/issues/4309): \[core] Cleanups in XPath area + * [#4312](https://github.com/pmd/pmd/issues/4312): \[core] Remove unnecessary property `color` and system property `pmd.color` in `TextColorRenderer` + * [#4313](https://github.com/pmd/pmd/issues/4313): \[core] Remove support for <lang>-<ruleset> hyphen notation for ruleset references + * [#4314](https://github.com/pmd/pmd/issues/4314): \[core] Remove ruleset compatibility filter (RuleSetFactoryCompatibility) and CLI option `--no-ruleset-compatibility` + * [#4323](https://github.com/pmd/pmd/issues/4323): \[core] Refactor CPD integration + * [#4348](https://github.com/pmd/pmd/issues/4348): \[core] Consolidate @InternalApi classes + * [#4349](https://github.com/pmd/pmd/issues/4349): \[core] Cleanup remaining experimental and deprecated API + * [#4353](https://github.com/pmd/pmd/pull/4353): \[core] Micro optimizations for Node API + * [#4365](https://github.com/pmd/pmd/pull/4365): \[core] Improve benchmarking + * [#4397](https://github.com/pmd/pmd/pull/4397): \[core] Refactor CPD + * [#4378](https://github.com/pmd/pmd/issues/4378): \[core] Ruleset loading processes commented rules + * [#4420](https://github.com/pmd/pmd/pull/4420): \[core] Remove PMD.EOL + * [#4425](https://github.com/pmd/pmd/pull/4425): \[core] Replace TextFile::pathId + * [#4454](https://github.com/pmd/pmd/issues/4454): \[core] "Unknown option: '-min'" but is referenced in documentation + * [#4611](https://github.com/pmd/pmd/pull/4611): \[core] Fix loading language properties from env vars + * [#4621](https://github.com/pmd/pmd/issues/4621): \[core] Make `ClasspathClassLoader::getResource` child first + * [#4674](https://github.com/pmd/pmd/issues/4674): \[core] WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass + * [#4694](https://github.com/pmd/pmd/pull/4694): \[core] Fix line/col numbers in TokenMgrError + * [#4717](https://github.com/pmd/pmd/issues/4717): \[core] XSLTRenderer doesn't close report file + * [#4750](https://github.com/pmd/pmd/pull/4750): \[core] Fix flaky SummaryHTMLRenderer + * [#4782](https://github.com/pmd/pmd/pull/4782): \[core] Avoid using getImage/@Image * cli - * [#2234](https://github.com/pmd/pmd/issues/2234): \[core] Consolidate PMD CLI into a single command - * [#3828](https://github.com/pmd/pmd/issues/3828): \[core] Progress reporting - * [#4079](https://github.com/pmd/pmd/issues/4079): \[cli] Split off CLI implementation into a pmd-cli submodule - * [#4423](https://github.com/pmd/pmd/pull/4423): \[cli] Fix NPE when only `--file-list` is specified - * [#4482](https://github.com/pmd/pmd/issues/4482): \[cli] pmd.bat can only be executed once - * [#4484](https://github.com/pmd/pmd/issues/4484): \[cli] ast-dump with no properties produce an NPE - * [#4594](https://github.com/pmd/pmd/pull/4594): \[cli] Change completion generation to runtime - * [#4685](https://github.com/pmd/pmd/pull/4685): \[cli] Clarify CPD documentation, fix positional parameter handling - * [#4723](https://github.com/pmd/pmd/issues/4723): \[cli] Launch fails for "bash pmd" + * [#2234](https://github.com/pmd/pmd/issues/2234): \[core] Consolidate PMD CLI into a single command + * [#3828](https://github.com/pmd/pmd/issues/3828): \[core] Progress reporting + * [#4079](https://github.com/pmd/pmd/issues/4079): \[cli] Split off CLI implementation into a pmd-cli submodule + * [#4423](https://github.com/pmd/pmd/pull/4423): \[cli] Fix NPE when only `--file-list` is specified + * [#4482](https://github.com/pmd/pmd/issues/4482): \[cli] pmd.bat can only be executed once + * [#4484](https://github.com/pmd/pmd/issues/4484): \[cli] ast-dump with no properties produce an NPE + * [#4594](https://github.com/pmd/pmd/pull/4594): \[cli] Change completion generation to runtime + * [#4685](https://github.com/pmd/pmd/pull/4685): \[cli] Clarify CPD documentation, fix positional parameter handling + * [#4723](https://github.com/pmd/pmd/issues/4723): \[cli] Launch fails for "bash pmd" * doc - * [#995](https://github.com/pmd/pmd/issues/995): \[doc] Document API evolution principles as ADR - * [#2501](https://github.com/pmd/pmd/issues/2501): \[doc] Verify ANTLR Documentation - * [#2511](https://github.com/pmd/pmd/issues/2511): \[doc] Review guides for writing java/xpath rules for correctness with PMD 7 - * [#3175](https://github.com/pmd/pmd/issues/3175): \[doc] Document language module features - * [#4294](https://github.com/pmd/pmd/issues/4294): \[doc] Migration Guide for upgrading PMD 6 ➡️ 7 - * [#4303](https://github.com/pmd/pmd/issues/4303): \[doc] Document new property framework - * [#4308](https://github.com/pmd/pmd/issues/4308): \[doc] Document XPath API @DeprecatedAttribute - * [#4319](https://github.com/pmd/pmd/issues/4319): \[doc] Document TypeRes API and Symbols API - * [#4438](https://github.com/pmd/pmd/issues/4438): \[doc] Documentation links in VS Code are outdated - * [#4521](https://github.com/pmd/pmd/issues/4521): \[doc] Website is not mobile friendly - * [#4676](https://github.com/pmd/pmd/issues/4676): \[doc] Clarify how CPD `--ignore-literals` and `--ignore-identifiers` work - * [#4659](https://github.com/pmd/pmd/pull/4659): \[doc] Improve ant documentation - * [#4669](https://github.com/pmd/pmd/pull/4669): \[doc] Add bld PMD Extension to Tools / Integrations - * [#4704](https://github.com/pmd/pmd/issues/4704): \[doc] Multivalued properties do not accept \| as a separator + * [#995](https://github.com/pmd/pmd/issues/995): \[doc] Document API evolution principles as ADR + * [#2501](https://github.com/pmd/pmd/issues/2501): \[doc] Verify ANTLR Documentation + * [#2511](https://github.com/pmd/pmd/issues/2511): \[doc] Review guides for writing java/xpath rules for correctness with PMD 7 + * [#3175](https://github.com/pmd/pmd/issues/3175): \[doc] Document language module features + * [#4294](https://github.com/pmd/pmd/issues/4294): \[doc] Migration Guide for upgrading PMD 6 ➡️ 7 + * [#4303](https://github.com/pmd/pmd/issues/4303): \[doc] Document new property framework + * [#4308](https://github.com/pmd/pmd/issues/4308): \[doc] Document XPath API @DeprecatedAttribute + * [#4319](https://github.com/pmd/pmd/issues/4319): \[doc] Document TypeRes API and Symbols API + * [#4438](https://github.com/pmd/pmd/issues/4438): \[doc] Documentation links in VS Code are outdated + * [#4521](https://github.com/pmd/pmd/issues/4521): \[doc] Website is not mobile friendly + * [#4676](https://github.com/pmd/pmd/issues/4676): \[doc] Clarify how CPD `--ignore-literals` and `--ignore-identifiers` work + * [#4659](https://github.com/pmd/pmd/pull/4659): \[doc] Improve ant documentation + * [#4669](https://github.com/pmd/pmd/pull/4669): \[doc] Add bld PMD Extension to Tools / Integrations + * [#4704](https://github.com/pmd/pmd/issues/4704): \[doc] Multivalued properties do not accept \| as a separator * testing - * [#2435](https://github.com/pmd/pmd/issues/2435): \[test] Remove duplicated Dummy language module - * [#4234](https://github.com/pmd/pmd/issues/4234): \[test] Tests that change the logging level do not work + * [#2435](https://github.com/pmd/pmd/issues/2435): \[test] Remove duplicated Dummy language module + * [#4234](https://github.com/pmd/pmd/issues/4234): \[test] Tests that change the logging level do not work Language specific fixes: * apex - * [#1937](https://github.com/pmd/pmd/issues/1937): \[apex] Apex should only have a single RootNode - * [#1648](https://github.com/pmd/pmd/issues/1648): \[apex,vf] Remove CodeClimate dependency - * [#1750](https://github.com/pmd/pmd/pull/1750): \[apex] Remove apex statistical rules - * [#2836](https://github.com/pmd/pmd/pull/2836): \[apex] Remove Apex ProjectMirror - * [#3766](https://github.com/pmd/pmd/issues/3766): \[apex] Replace Jorje with fully open source front-end - * [#3973](https://github.com/pmd/pmd/issues/3973): \[apex] Update parser to support new 'as user' keywords (User Mode for Database Operations) - * [#4427](https://github.com/pmd/pmd/issues/4427): \[apex] ApexBadCrypto test failing to detect inline code - * [#4453](https://github.com/pmd/pmd/issues/4453): \[apex] \[7.0-rc1] Exception while initializing Apexlink (Index 34812 out of bounds for length 34812) - * [#4828](https://github.com/pmd/pmd/issues/4828): \[apex] Support null coalescing operator ?? (apex 60) - * [#4845](https://github.com/pmd/pmd/issues/4845): \[apex] Use same ANLTR version for apex-parser + * [#1937](https://github.com/pmd/pmd/issues/1937): \[apex] Apex should only have a single RootNode + * [#1648](https://github.com/pmd/pmd/issues/1648): \[apex,vf] Remove CodeClimate dependency + * [#1750](https://github.com/pmd/pmd/pull/1750): \[apex] Remove apex statistical rules + * [#2836](https://github.com/pmd/pmd/pull/2836): \[apex] Remove Apex ProjectMirror + * [#3766](https://github.com/pmd/pmd/issues/3766): \[apex] Replace Jorje with fully open source front-end + * [#3973](https://github.com/pmd/pmd/issues/3973): \[apex] Update parser to support new 'as user' keywords (User Mode for Database Operations) + * [#4427](https://github.com/pmd/pmd/issues/4427): \[apex] ApexBadCrypto test failing to detect inline code + * [#4453](https://github.com/pmd/pmd/issues/4453): \[apex] \[7.0-rc1] Exception while initializing Apexlink (Index 34812 out of bounds for length 34812) + * [#4828](https://github.com/pmd/pmd/issues/4828): \[apex] Support null coalescing operator ?? (apex 60) + * [#4845](https://github.com/pmd/pmd/issues/4845): \[apex] Use same ANLTR version for apex-parser * apex-design - * [#2667](https://github.com/pmd/pmd/issues/2667): \[apex] Integrate nawforce/ApexLink to build robust Unused rule - * [#4509](https://github.com/pmd/pmd/issues/4509): \[apex] ExcessivePublicCount doesn't consider inner classes correctly - * [#4596](https://github.com/pmd/pmd/issues/4596): \[apex] ExcessivePublicCount ignores properties + * [#2667](https://github.com/pmd/pmd/issues/2667): \[apex] Integrate nawforce/ApexLink to build robust Unused rule + * [#4509](https://github.com/pmd/pmd/issues/4509): \[apex] ExcessivePublicCount doesn't consider inner classes correctly + * [#4596](https://github.com/pmd/pmd/issues/4596): \[apex] ExcessivePublicCount ignores properties * apex-documentation - * [#4774](https://github.com/pmd/pmd/issues/4774): \[apex] ApexDoc false-positive for the first method of an annotated Apex class + * [#4774](https://github.com/pmd/pmd/issues/4774): \[apex] ApexDoc false-positive for the first method of an annotated Apex class * apex-performance - * [#4675](https://github.com/pmd/pmd/issues/4675): \[apex] New Rule: OperationWithHighCostInLoop + * [#4675](https://github.com/pmd/pmd/issues/4675): \[apex] New Rule: OperationWithHighCostInLoop * apex-security - * [#4646](https://github.com/pmd/pmd/issues/4646): \[apex] ApexSOQLInjection does not recognise SObjectType or SObjectField as safe variable types + * [#4646](https://github.com/pmd/pmd/issues/4646): \[apex] ApexSOQLInjection does not recognise SObjectType or SObjectField as safe variable types * groovy - * [#4726](https://github.com/pmd/pmd/pull/4726): \[groovy] Support Groovy to 3 and 4 and CPD suppressions + * [#4726](https://github.com/pmd/pmd/pull/4726): \[groovy] Support Groovy to 3 and 4 and CPD suppressions * java - * [#520](https://github.com/pmd/pmd/issues/520): \[java] Allow `@SuppressWarnings` with constants instead of literals - * [#864](https://github.com/pmd/pmd/issues/864): \[java] Similar/duplicated implementations for determining FQCN - * [#905](https://github.com/pmd/pmd/issues/905): \[java] Add new node for anonymous class declaration - * [#910](https://github.com/pmd/pmd/issues/910): \[java] AST inconsistency between primitive and reference type arrays - * [#997](https://github.com/pmd/pmd/issues/997): \[java] Java8 parsing corner case with annotated array types - * [#998](https://github.com/pmd/pmd/issues/998): \[java] AST inconsistencies around FormalParameter - * [#1019](https://github.com/pmd/pmd/issues/1019): \[java] Breaking Java Grammar changes for PMD 7.0.0 - * [#1124](https://github.com/pmd/pmd/issues/1124): \[java] ImmutableList implementation in the qname codebase - * [#1128](https://github.com/pmd/pmd/issues/1128): \[java] Improve ASTLocalVariableDeclaration - * [#1150](https://github.com/pmd/pmd/issues/1150): \[java] ClassOrInterfaceType AST improvements - * [#1207](https://github.com/pmd/pmd/issues/1207): \[java] Resolve explicit types using FQCNs, without hitting the classloader - * [#1307](https://github.com/pmd/pmd/issues/1307): \[java] AccessNode API changes - * [#1367](https://github.com/pmd/pmd/issues/1367): \[java] Parsing error on annotated inner class - * [#1661](https://github.com/pmd/pmd/issues/1661): \[java] About operator nodes - * [#2366](https://github.com/pmd/pmd/pull/2366): \[java] Remove qualified names - * [#2819](https://github.com/pmd/pmd/issues/2819): \[java] GLB bugs in pmd 7 - * [#3642](https://github.com/pmd/pmd/issues/3642): \[java] Parse error on rare extra dimensions on method return type on annotation methods - * [#3763](https://github.com/pmd/pmd/issues/3763): \[java] Ambiguous reference error in valid code - * [#3749](https://github.com/pmd/pmd/issues/3749): \[java] Improve `isOverridden` in ASTMethodDeclaration - * [#3750](https://github.com/pmd/pmd/issues/3750): \[java] Make symbol table support instanceof pattern bindings - * [#3751](https://github.com/pmd/pmd/issues/3751): \[java] Rename some node types - * [#3752](https://github.com/pmd/pmd/issues/3752): \[java] Expose annotations in symbol API - * [#4237](https://github.com/pmd/pmd/pull/4237): \[java] Cleanup handling of Java comments - * [#4317](https://github.com/pmd/pmd/issues/4317): \[java] Some AST nodes should not be TypeNodes - * [#4359](https://github.com/pmd/pmd/issues/4359): \[java] Type resolution fails with NPE when the scope is not a type declaration - * [#4367](https://github.com/pmd/pmd/issues/4367): \[java] Move testrule TypeResTest into internal - * [#4383](https://github.com/pmd/pmd/issues/4383): \[java] IllegalStateException: Object is not an array type! - * [#4401](https://github.com/pmd/pmd/issues/4401): \[java] PMD 7 fails to build under Java 19 - * [#4405](https://github.com/pmd/pmd/issues/4405): \[java] Processing error with ArrayIndexOutOfBoundsException - * [#4583](https://github.com/pmd/pmd/issues/4583): \[java] Support JDK 21 (LTS) - * [#4628](https://github.com/pmd/pmd/pull/4628): \[java] Support loading classes from java runtime images - * [#4753](https://github.com/pmd/pmd/issues/4753): \[java] PMD crashes while using generics and wildcards - * [#4757](https://github.com/pmd/pmd/issues/4757): \[java] Intermittent NPEs while analyzing Java code - * [#4794](https://github.com/pmd/pmd/issues/4794): \[java] Support JDK 22 + * [#520](https://github.com/pmd/pmd/issues/520): \[java] Allow `@SuppressWarnings` with constants instead of literals + * [#864](https://github.com/pmd/pmd/issues/864): \[java] Similar/duplicated implementations for determining FQCN + * [#905](https://github.com/pmd/pmd/issues/905): \[java] Add new node for anonymous class declaration + * [#910](https://github.com/pmd/pmd/issues/910): \[java] AST inconsistency between primitive and reference type arrays + * [#997](https://github.com/pmd/pmd/issues/997): \[java] Java8 parsing corner case with annotated array types + * [#998](https://github.com/pmd/pmd/issues/998): \[java] AST inconsistencies around FormalParameter + * [#1019](https://github.com/pmd/pmd/issues/1019): \[java] Breaking Java Grammar changes for PMD 7.0.0 + * [#1124](https://github.com/pmd/pmd/issues/1124): \[java] ImmutableList implementation in the qname codebase + * [#1128](https://github.com/pmd/pmd/issues/1128): \[java] Improve ASTLocalVariableDeclaration + * [#1150](https://github.com/pmd/pmd/issues/1150): \[java] ClassOrInterfaceType AST improvements + * [#1207](https://github.com/pmd/pmd/issues/1207): \[java] Resolve explicit types using FQCNs, without hitting the classloader + * [#1307](https://github.com/pmd/pmd/issues/1307): \[java] AccessNode API changes + * [#1367](https://github.com/pmd/pmd/issues/1367): \[java] Parsing error on annotated inner class + * [#1661](https://github.com/pmd/pmd/issues/1661): \[java] About operator nodes + * [#2366](https://github.com/pmd/pmd/pull/2366): \[java] Remove qualified names + * [#2819](https://github.com/pmd/pmd/issues/2819): \[java] GLB bugs in pmd 7 + * [#3642](https://github.com/pmd/pmd/issues/3642): \[java] Parse error on rare extra dimensions on method return type on annotation methods + * [#3763](https://github.com/pmd/pmd/issues/3763): \[java] Ambiguous reference error in valid code + * [#3749](https://github.com/pmd/pmd/issues/3749): \[java] Improve `isOverridden` in ASTMethodDeclaration + * [#3750](https://github.com/pmd/pmd/issues/3750): \[java] Make symbol table support instanceof pattern bindings + * [#3751](https://github.com/pmd/pmd/issues/3751): \[java] Rename some node types + * [#3752](https://github.com/pmd/pmd/issues/3752): \[java] Expose annotations in symbol API + * [#4237](https://github.com/pmd/pmd/pull/4237): \[java] Cleanup handling of Java comments + * [#4317](https://github.com/pmd/pmd/issues/4317): \[java] Some AST nodes should not be TypeNodes + * [#4359](https://github.com/pmd/pmd/issues/4359): \[java] Type resolution fails with NPE when the scope is not a type declaration + * [#4367](https://github.com/pmd/pmd/issues/4367): \[java] Move testrule TypeResTest into internal + * [#4383](https://github.com/pmd/pmd/issues/4383): \[java] IllegalStateException: Object is not an array type! + * [#4401](https://github.com/pmd/pmd/issues/4401): \[java] PMD 7 fails to build under Java 19 + * [#4405](https://github.com/pmd/pmd/issues/4405): \[java] Processing error with ArrayIndexOutOfBoundsException + * [#4583](https://github.com/pmd/pmd/issues/4583): \[java] Support JDK 21 (LTS) + * [#4628](https://github.com/pmd/pmd/pull/4628): \[java] Support loading classes from java runtime images + * [#4753](https://github.com/pmd/pmd/issues/4753): \[java] PMD crashes while using generics and wildcards + * [#4757](https://github.com/pmd/pmd/issues/4757): \[java] Intermittent NPEs while analyzing Java code + * [#4794](https://github.com/pmd/pmd/issues/4794): \[java] Support JDK 22 * java-bestpractices - * [#342](https://github.com/pmd/pmd/issues/342): \[java] AccessorMethodGeneration: Name clash with another public field not properly handled - * [#755](https://github.com/pmd/pmd/issues/755): \[java] AccessorClassGeneration false positive for private constructors - * [#770](https://github.com/pmd/pmd/issues/770): \[java] UnusedPrivateMethod yields false positive for counter-variant arguments - * [#807](https://github.com/pmd/pmd/issues/807): \[java] AccessorMethodGeneration false positive with overloads - * [#833](https://github.com/pmd/pmd/issues/833): \[java] ForLoopCanBeForeach should consider iterating on this - * [#1189](https://github.com/pmd/pmd/issues/1189): \[java] UnusedPrivateMethod false positive from inner class via external class - * [#1205](https://github.com/pmd/pmd/issues/1205): \[java] Improve ConstantsInInterface message to mention alternatives - * [#1212](https://github.com/pmd/pmd/issues/1212): \[java] Don't raise JUnitTestContainsTooManyAsserts on JUnit 5's assertAll - * [#1422](https://github.com/pmd/pmd/issues/1422): \[java] JUnitTestsShouldIncludeAssert false positive with inherited @Rule field - * [#1455](https://github.com/pmd/pmd/issues/1455): \[java] JUnitTestsShouldIncludeAssert: False positives for assert methods named "check" and "verify" - * [#1563](https://github.com/pmd/pmd/issues/1563): \[java] ForLoopCanBeForeach false positive with method call using index variable - * [#1565](https://github.com/pmd/pmd/issues/1565): \[java] JUnitAssertionsShouldIncludeMessage false positive with AssertJ - * [#1747](https://github.com/pmd/pmd/issues/1747): \[java] PreserveStackTrace false-positive - * [#1969](https://github.com/pmd/pmd/issues/1969): \[java] MissingOverride false-positive triggered by package-private method overwritten in another package by extending class - * [#1998](https://github.com/pmd/pmd/issues/1998): \[java] AccessorClassGeneration false-negative: subclass calls private constructor - * [#2130](https://github.com/pmd/pmd/issues/2130): \[java] UnusedLocalVariable: false-negative with array - * [#2147](https://github.com/pmd/pmd/issues/2147): \[java] JUnitTestsShouldIncludeAssert - false positives with lambdas and static methods - * [#2464](https://github.com/pmd/pmd/issues/2464): \[java] LooseCoupling must ignore class literals: ArrayList.class - * [#2542](https://github.com/pmd/pmd/issues/2542): \[java] UseCollectionIsEmpty can not detect the case `foo.bar().size()` - * [#2650](https://github.com/pmd/pmd/issues/2650): \[java] UseTryWithResources false positive when AutoCloseable helper used - * [#2796](https://github.com/pmd/pmd/issues/2796): \[java] UnusedAssignment false positive with call chains - * [#2797](https://github.com/pmd/pmd/issues/2797): \[java] MissingOverride long-standing issues - * [#2806](https://github.com/pmd/pmd/issues/2806): \[java] SwitchStmtsShouldHaveDefault false-positive with Java 14 switch non-fallthrough branches - * [#2822](https://github.com/pmd/pmd/issues/2822): \[java] LooseCoupling rule: Extend to cover user defined implementations and interfaces - * [#2843](https://github.com/pmd/pmd/pull/2843): \[java] Fix UnusedAssignment FP with field accesses - * [#2882](https://github.com/pmd/pmd/issues/2882): \[java] UseTryWithResources - false negative for explicit close - * [#2883](https://github.com/pmd/pmd/issues/2883): \[java] JUnitAssertionsShouldIncludeMessage false positive with method call - * [#2890](https://github.com/pmd/pmd/issues/2890): \[java] UnusedPrivateMethod false positive with generics - * [#2946](https://github.com/pmd/pmd/issues/2946): \[java] SwitchStmtsShouldHaveDefault false positive on enum inside enums - * [#3672](https://github.com/pmd/pmd/pull/3672): \[java] LooseCoupling - fix false positive with generics - * [#3675](https://github.com/pmd/pmd/pull/3675): \[java] MissingOverride - fix false positive with mixing type vars - * [#3858](https://github.com/pmd/pmd/issues/3858): \[java] UseCollectionIsEmpty should infer local variable type from method invocation - * [#4433](https://github.com/pmd/pmd/issues/4433): \[java] \[7.0-rc1] ReplaceHashtableWithMap on java.util.Properties - * [#4492](https://github.com/pmd/pmd/issues/4492): \[java] GuardLogStatement gives false positive when argument is a Java method reference - * [#4503](https://github.com/pmd/pmd/issues/4503): \[java] JUnitTestsShouldIncludeAssert: false negative with TestNG - * [#4516](https://github.com/pmd/pmd/issues/4516): \[java] UnusedLocalVariable: false-negative with try-with-resources - * [#4517](https://github.com/pmd/pmd/issues/4517): \[java] UnusedLocalVariable: false-negative with compound assignments - * [#4518](https://github.com/pmd/pmd/issues/4518): \[java] UnusedLocalVariable: false-positive with multiple for-loop indices - * [#4603](https://github.com/pmd/pmd/issues/4603): \[java] UnusedAssignment false positive in record compact constructor - * [#4625](https://github.com/pmd/pmd/issues/4625): \[java] UnusedPrivateMethod false positive: Autoboxing into Number - * [#4634](https://github.com/pmd/pmd/issues/4634): \[java] JUnit4TestShouldUseTestAnnotation false positive with TestNG - * [#4817](https://github.com/pmd/pmd/issues/4817): \[java] UnusedPrivateMethod false-positive used in lambda + * [#342](https://github.com/pmd/pmd/issues/342): \[java] AccessorMethodGeneration: Name clash with another public field not properly handled + * [#755](https://github.com/pmd/pmd/issues/755): \[java] AccessorClassGeneration false positive for private constructors + * [#770](https://github.com/pmd/pmd/issues/770): \[java] UnusedPrivateMethod yields false positive for counter-variant arguments + * [#807](https://github.com/pmd/pmd/issues/807): \[java] AccessorMethodGeneration false positive with overloads + * [#833](https://github.com/pmd/pmd/issues/833): \[java] ForLoopCanBeForeach should consider iterating on this + * [#1189](https://github.com/pmd/pmd/issues/1189): \[java] UnusedPrivateMethod false positive from inner class via external class + * [#1205](https://github.com/pmd/pmd/issues/1205): \[java] Improve ConstantsInInterface message to mention alternatives + * [#1212](https://github.com/pmd/pmd/issues/1212): \[java] Don't raise JUnitTestContainsTooManyAsserts on JUnit 5's assertAll + * [#1422](https://github.com/pmd/pmd/issues/1422): \[java] JUnitTestsShouldIncludeAssert false positive with inherited @Rule field + * [#1455](https://github.com/pmd/pmd/issues/1455): \[java] JUnitTestsShouldIncludeAssert: False positives for assert methods named "check" and "verify" + * [#1563](https://github.com/pmd/pmd/issues/1563): \[java] ForLoopCanBeForeach false positive with method call using index variable + * [#1565](https://github.com/pmd/pmd/issues/1565): \[java] JUnitAssertionsShouldIncludeMessage false positive with AssertJ + * [#1747](https://github.com/pmd/pmd/issues/1747): \[java] PreserveStackTrace false-positive + * [#1969](https://github.com/pmd/pmd/issues/1969): \[java] MissingOverride false-positive triggered by package-private method overwritten in another package by extending class + * [#1998](https://github.com/pmd/pmd/issues/1998): \[java] AccessorClassGeneration false-negative: subclass calls private constructor + * [#2130](https://github.com/pmd/pmd/issues/2130): \[java] UnusedLocalVariable: false-negative with array + * [#2147](https://github.com/pmd/pmd/issues/2147): \[java] JUnitTestsShouldIncludeAssert - false positives with lambdas and static methods + * [#2464](https://github.com/pmd/pmd/issues/2464): \[java] LooseCoupling must ignore class literals: ArrayList.class + * [#2542](https://github.com/pmd/pmd/issues/2542): \[java] UseCollectionIsEmpty can not detect the case `foo.bar().size()` + * [#2650](https://github.com/pmd/pmd/issues/2650): \[java] UseTryWithResources false positive when AutoCloseable helper used + * [#2796](https://github.com/pmd/pmd/issues/2796): \[java] UnusedAssignment false positive with call chains + * [#2797](https://github.com/pmd/pmd/issues/2797): \[java] MissingOverride long-standing issues + * [#2806](https://github.com/pmd/pmd/issues/2806): \[java] SwitchStmtsShouldHaveDefault false-positive with Java 14 switch non-fallthrough branches + * [#2822](https://github.com/pmd/pmd/issues/2822): \[java] LooseCoupling rule: Extend to cover user defined implementations and interfaces + * [#2843](https://github.com/pmd/pmd/pull/2843): \[java] Fix UnusedAssignment FP with field accesses + * [#2882](https://github.com/pmd/pmd/issues/2882): \[java] UseTryWithResources - false negative for explicit close + * [#2883](https://github.com/pmd/pmd/issues/2883): \[java] JUnitAssertionsShouldIncludeMessage false positive with method call + * [#2890](https://github.com/pmd/pmd/issues/2890): \[java] UnusedPrivateMethod false positive with generics + * [#2946](https://github.com/pmd/pmd/issues/2946): \[java] SwitchStmtsShouldHaveDefault false positive on enum inside enums + * [#3672](https://github.com/pmd/pmd/pull/3672): \[java] LooseCoupling - fix false positive with generics + * [#3675](https://github.com/pmd/pmd/pull/3675): \[java] MissingOverride - fix false positive with mixing type vars + * [#3858](https://github.com/pmd/pmd/issues/3858): \[java] UseCollectionIsEmpty should infer local variable type from method invocation + * [#4433](https://github.com/pmd/pmd/issues/4433): \[java] \[7.0-rc1] ReplaceHashtableWithMap on java.util.Properties + * [#4492](https://github.com/pmd/pmd/issues/4492): \[java] GuardLogStatement gives false positive when argument is a Java method reference + * [#4503](https://github.com/pmd/pmd/issues/4503): \[java] JUnitTestsShouldIncludeAssert: false negative with TestNG + * [#4516](https://github.com/pmd/pmd/issues/4516): \[java] UnusedLocalVariable: false-negative with try-with-resources + * [#4517](https://github.com/pmd/pmd/issues/4517): \[java] UnusedLocalVariable: false-negative with compound assignments + * [#4518](https://github.com/pmd/pmd/issues/4518): \[java] UnusedLocalVariable: false-positive with multiple for-loop indices + * [#4603](https://github.com/pmd/pmd/issues/4603): \[java] UnusedAssignment false positive in record compact constructor + * [#4625](https://github.com/pmd/pmd/issues/4625): \[java] UnusedPrivateMethod false positive: Autoboxing into Number + * [#4634](https://github.com/pmd/pmd/issues/4634): \[java] JUnit4TestShouldUseTestAnnotation false positive with TestNG + * [#4817](https://github.com/pmd/pmd/issues/4817): \[java] UnusedPrivateMethod false-positive used in lambda * java-codestyle - * [#1208](https://github.com/pmd/pmd/issues/1208): \[java] PrematureDeclaration rule false-positive on variable declared to measure time - * [#1429](https://github.com/pmd/pmd/issues/1429): \[java] PrematureDeclaration as result of method call (false positive) - * [#1480](https://github.com/pmd/pmd/issues/1480): \[java] IdenticalCatchBranches false positive with return expressions - * [#1673](https://github.com/pmd/pmd/issues/1673): \[java] UselessParentheses false positive with conditional operator - * [#1790](https://github.com/pmd/pmd/issues/1790): \[java] UnnecessaryFullyQualifiedName false positive with enum constant - * [#1918](https://github.com/pmd/pmd/issues/1918): \[java] UselessParentheses false positive with boolean operators - * [#2134](https://github.com/pmd/pmd/issues/2134): \[java] PreserveStackTrace not handling `Throwable.addSuppressed(...)` - * [#2299](https://github.com/pmd/pmd/issues/2299): \[java] UnnecessaryFullyQualifiedName false positive with similar package name - * [#2391](https://github.com/pmd/pmd/issues/2391): \[java] UseDiamondOperator FP when expected type and constructed type have a different parameterization - * [#2528](https://github.com/pmd/pmd/issues/2528): \[java] MethodNamingConventions - JUnit 5 method naming not support ParameterizedTest - * [#2739](https://github.com/pmd/pmd/issues/2739): \[java] UselessParentheses false positive for string concatenation - * [#2748](https://github.com/pmd/pmd/issues/2748): \[java] UnnecessaryCast false positive with unchecked cast - * [#2847](https://github.com/pmd/pmd/issues/2847): \[java] New Rule: Use Explicit Types - * [#2973](https://github.com/pmd/pmd/issues/2973): \[java] New rule: UnnecessaryBoxing - * [#3195](https://github.com/pmd/pmd/pull/3195): \[java] Improve rule UnnecessaryReturn to detect more cases - * [#3218](https://github.com/pmd/pmd/pull/3218): \[java] Generalize UnnecessaryCast to flag all unnecessary casts - * [#3221](https://github.com/pmd/pmd/issues/3221): \[java] PrematureDeclaration false positive for unused variables - * [#3238](https://github.com/pmd/pmd/issues/3238): \[java] Improve ExprContext, fix FNs of UnnecessaryCast - * [#3500](https://github.com/pmd/pmd/pull/3500): \[java] UnnecessaryBoxing - check for Integer.valueOf(String) calls - * [#4239](https://github.com/pmd/pmd/issues/4239): \[java] UnnecessaryLocalBeforeReturn - false positive with catch clause - * [#4268](https://github.com/pmd/pmd/issues/4268): \[java] CommentDefaultAccessModifier: false positive with TestNG annotations - * [#4273](https://github.com/pmd/pmd/issues/4273): \[java] CommentDefaultAccessModifier ignoredAnnotations should include "org.junit.jupiter.api.extension.RegisterExtension" by default - * [#4357](https://github.com/pmd/pmd/pull/4357): \[java] Fix IllegalStateException in UseDiamondOperator rule - * [#4432](https://github.com/pmd/pmd/issues/4432): \[java] \[7.0-rc1] UnnecessaryImport - Unused static import is being used - * [#4455](https://github.com/pmd/pmd/issues/4455): \[java] FieldNamingConventions: false positive with lombok's @UtilityClass - * [#4487](https://github.com/pmd/pmd/issues/4487): \[java] UnnecessaryConstructor: false-positive with @Inject and @Autowired - * [#4511](https://github.com/pmd/pmd/issues/4511): \[java] LocalVariableCouldBeFinal shouldn't report unused variables - * [#4512](https://github.com/pmd/pmd/issues/4512): \[java] MethodArgumentCouldBeFinal shouldn't report unused parameters - * [#4557](https://github.com/pmd/pmd/issues/4557): \[java] UnnecessaryImport FP with static imports of overloaded methods - * [#4578](https://github.com/pmd/pmd/issues/4578): \[java] CommentDefaultAccessModifier comment needs to be before annotation if present - * [#4631](https://github.com/pmd/pmd/issues/4631): \[java] UnnecessaryFullyQualifiedName fails to recognize illegal self reference in enums - * [#4645](https://github.com/pmd/pmd/issues/4645): \[java] CommentDefaultAccessModifier - False Positive with JUnit5's ParameterizedTest - * [#4754](https://github.com/pmd/pmd/pull/4754): \[java] EmptyControlStatementRule: Add allowCommentedBlocks property - * [#4816](https://github.com/pmd/pmd/issues/4816): \[java] UnnecessaryImport false-positive on generic method call with on lambda + * [#1208](https://github.com/pmd/pmd/issues/1208): \[java] PrematureDeclaration rule false-positive on variable declared to measure time + * [#1429](https://github.com/pmd/pmd/issues/1429): \[java] PrematureDeclaration as result of method call (false positive) + * [#1480](https://github.com/pmd/pmd/issues/1480): \[java] IdenticalCatchBranches false positive with return expressions + * [#1673](https://github.com/pmd/pmd/issues/1673): \[java] UselessParentheses false positive with conditional operator + * [#1790](https://github.com/pmd/pmd/issues/1790): \[java] UnnecessaryFullyQualifiedName false positive with enum constant + * [#1918](https://github.com/pmd/pmd/issues/1918): \[java] UselessParentheses false positive with boolean operators + * [#2134](https://github.com/pmd/pmd/issues/2134): \[java] PreserveStackTrace not handling `Throwable.addSuppressed(...)` + * [#2299](https://github.com/pmd/pmd/issues/2299): \[java] UnnecessaryFullyQualifiedName false positive with similar package name + * [#2391](https://github.com/pmd/pmd/issues/2391): \[java] UseDiamondOperator FP when expected type and constructed type have a different parameterization + * [#2528](https://github.com/pmd/pmd/issues/2528): \[java] MethodNamingConventions - JUnit 5 method naming not support ParameterizedTest + * [#2739](https://github.com/pmd/pmd/issues/2739): \[java] UselessParentheses false positive for string concatenation + * [#2748](https://github.com/pmd/pmd/issues/2748): \[java] UnnecessaryCast false positive with unchecked cast + * [#2847](https://github.com/pmd/pmd/issues/2847): \[java] New Rule: Use Explicit Types + * [#2973](https://github.com/pmd/pmd/issues/2973): \[java] New rule: UnnecessaryBoxing + * [#3195](https://github.com/pmd/pmd/pull/3195): \[java] Improve rule UnnecessaryReturn to detect more cases + * [#3218](https://github.com/pmd/pmd/pull/3218): \[java] Generalize UnnecessaryCast to flag all unnecessary casts + * [#3221](https://github.com/pmd/pmd/issues/3221): \[java] PrematureDeclaration false positive for unused variables + * [#3238](https://github.com/pmd/pmd/issues/3238): \[java] Improve ExprContext, fix FNs of UnnecessaryCast + * [#3500](https://github.com/pmd/pmd/pull/3500): \[java] UnnecessaryBoxing - check for Integer.valueOf(String) calls + * [#4239](https://github.com/pmd/pmd/issues/4239): \[java] UnnecessaryLocalBeforeReturn - false positive with catch clause + * [#4268](https://github.com/pmd/pmd/issues/4268): \[java] CommentDefaultAccessModifier: false positive with TestNG annotations + * [#4273](https://github.com/pmd/pmd/issues/4273): \[java] CommentDefaultAccessModifier ignoredAnnotations should include "org.junit.jupiter.api.extension.RegisterExtension" by default + * [#4357](https://github.com/pmd/pmd/pull/4357): \[java] Fix IllegalStateException in UseDiamondOperator rule + * [#4432](https://github.com/pmd/pmd/issues/4432): \[java] \[7.0-rc1] UnnecessaryImport - Unused static import is being used + * [#4455](https://github.com/pmd/pmd/issues/4455): \[java] FieldNamingConventions: false positive with lombok's @UtilityClass + * [#4487](https://github.com/pmd/pmd/issues/4487): \[java] UnnecessaryConstructor: false-positive with @Inject and @Autowired + * [#4511](https://github.com/pmd/pmd/issues/4511): \[java] LocalVariableCouldBeFinal shouldn't report unused variables + * [#4512](https://github.com/pmd/pmd/issues/4512): \[java] MethodArgumentCouldBeFinal shouldn't report unused parameters + * [#4557](https://github.com/pmd/pmd/issues/4557): \[java] UnnecessaryImport FP with static imports of overloaded methods + * [#4578](https://github.com/pmd/pmd/issues/4578): \[java] CommentDefaultAccessModifier comment needs to be before annotation if present + * [#4631](https://github.com/pmd/pmd/issues/4631): \[java] UnnecessaryFullyQualifiedName fails to recognize illegal self reference in enums + * [#4645](https://github.com/pmd/pmd/issues/4645): \[java] CommentDefaultAccessModifier - False Positive with JUnit5's ParameterizedTest + * [#4754](https://github.com/pmd/pmd/pull/4754): \[java] EmptyControlStatementRule: Add allowCommentedBlocks property + * [#4816](https://github.com/pmd/pmd/issues/4816): \[java] UnnecessaryImport false-positive on generic method call with on lambda * java-design - * [#174](https://github.com/pmd/pmd/issues/174): \[java] SingularField false positive with switch in method that both assigns and reads field - * [#1014](https://github.com/pmd/pmd/issues/1014): \[java] LawOfDemeter: False positive with lambda expression - * [#1605](https://github.com/pmd/pmd/issues/1605): \[java] LawOfDemeter: False positive for standard UTF-8 charset name - * [#2160](https://github.com/pmd/pmd/issues/2160): \[java] Issues with Law of Demeter - * [#2175](https://github.com/pmd/pmd/issues/2175): \[java] LawOfDemeter: False positive for chained methods with generic method call - * [#2179](https://github.com/pmd/pmd/issues/2179): \[java] LawOfDemeter: False positive with static property access - should treat class-level property as global object, not dot-accessed property - * [#2180](https://github.com/pmd/pmd/issues/2180): \[java] LawOfDemeter: False positive with Thread and ThreadLocalRandom - * [#2182](https://github.com/pmd/pmd/issues/2182): \[java] LawOfDemeter: False positive with package-private access - * [#2188](https://github.com/pmd/pmd/issues/2188): \[java] LawOfDemeter: False positive with fields assigned to local vars - * [#2536](https://github.com/pmd/pmd/issues/2536): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal can't detect inner class - * [#3668](https://github.com/pmd/pmd/pull/3668): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal - fix FP with inner private classes - * [#3754](https://github.com/pmd/pmd/issues/3754): \[java] SingularField false positive with read in while condition - * [#3786](https://github.com/pmd/pmd/issues/3786): \[java] SimplifyBooleanReturns should consider operator precedence - * [#3840](https://github.com/pmd/pmd/issues/3840): \[java] LawOfDemeter disallows method call on locally created object - * [#4238](https://github.com/pmd/pmd/pull/4238): \[java] Make LawOfDemeter not use the rulechain - * [#4254](https://github.com/pmd/pmd/issues/4254): \[java] ImmutableField - false positive with Lombok @Setter - * [#4434](https://github.com/pmd/pmd/issues/4434): \[java] \[7.0-rc1] ExceptionAsFlowControl when simply propagating - * [#4456](https://github.com/pmd/pmd/issues/4456): \[java] FinalFieldCouldBeStatic: false positive with lombok's @UtilityClass - * [#4477](https://github.com/pmd/pmd/issues/4477): \[java] SignatureDeclareThrowsException: false-positive with TestNG annotations - * [#4490](https://github.com/pmd/pmd/issues/4490): \[java] ImmutableField - false negative with Lombok @Getter - * [#4549](https://github.com/pmd/pmd/pull/4549): \[java] Make LawOfDemeter results deterministic + * [#174](https://github.com/pmd/pmd/issues/174): \[java] SingularField false positive with switch in method that both assigns and reads field + * [#1014](https://github.com/pmd/pmd/issues/1014): \[java] LawOfDemeter: False positive with lambda expression + * [#1605](https://github.com/pmd/pmd/issues/1605): \[java] LawOfDemeter: False positive for standard UTF-8 charset name + * [#2160](https://github.com/pmd/pmd/issues/2160): \[java] Issues with Law of Demeter + * [#2175](https://github.com/pmd/pmd/issues/2175): \[java] LawOfDemeter: False positive for chained methods with generic method call + * [#2179](https://github.com/pmd/pmd/issues/2179): \[java] LawOfDemeter: False positive with static property access - should treat class-level property as global object, not dot-accessed property + * [#2180](https://github.com/pmd/pmd/issues/2180): \[java] LawOfDemeter: False positive with Thread and ThreadLocalRandom + * [#2182](https://github.com/pmd/pmd/issues/2182): \[java] LawOfDemeter: False positive with package-private access + * [#2188](https://github.com/pmd/pmd/issues/2188): \[java] LawOfDemeter: False positive with fields assigned to local vars + * [#2536](https://github.com/pmd/pmd/issues/2536): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal can't detect inner class + * [#3668](https://github.com/pmd/pmd/pull/3668): \[java] ClassWithOnlyPrivateConstructorsShouldBeFinal - fix FP with inner private classes + * [#3754](https://github.com/pmd/pmd/issues/3754): \[java] SingularField false positive with read in while condition + * [#3786](https://github.com/pmd/pmd/issues/3786): \[java] SimplifyBooleanReturns should consider operator precedence + * [#3840](https://github.com/pmd/pmd/issues/3840): \[java] LawOfDemeter disallows method call on locally created object + * [#4238](https://github.com/pmd/pmd/pull/4238): \[java] Make LawOfDemeter not use the rulechain + * [#4254](https://github.com/pmd/pmd/issues/4254): \[java] ImmutableField - false positive with Lombok @Setter + * [#4434](https://github.com/pmd/pmd/issues/4434): \[java] \[7.0-rc1] ExceptionAsFlowControl when simply propagating + * [#4456](https://github.com/pmd/pmd/issues/4456): \[java] FinalFieldCouldBeStatic: false positive with lombok's @UtilityClass + * [#4477](https://github.com/pmd/pmd/issues/4477): \[java] SignatureDeclareThrowsException: false-positive with TestNG annotations + * [#4490](https://github.com/pmd/pmd/issues/4490): \[java] ImmutableField - false negative with Lombok @Getter + * [#4549](https://github.com/pmd/pmd/pull/4549): \[java] Make LawOfDemeter results deterministic * java-documentation - * [#4369](https://github.com/pmd/pmd/pull/4369): \[java] Improve CommentSize - * [#4416](https://github.com/pmd/pmd/pull/4416): \[java] Fix reported line number in CommentContentRule + * [#4369](https://github.com/pmd/pmd/pull/4369): \[java] Improve CommentSize + * [#4416](https://github.com/pmd/pmd/pull/4416): \[java] Fix reported line number in CommentContentRule * java-errorprone - * [#659](https://github.com/pmd/pmd/issues/659): \[java] MissingBreakInSwitch - last default case does not contain a break - * [#718](https://github.com/pmd/pmd/issues/718): \[java] BrokenNullCheck false positive with parameter/field confusion - * [#932](https://github.com/pmd/pmd/issues/932): \[java] SingletonClassReturningNewInstance false positive with double assignment - * [#1005](https://github.com/pmd/pmd/issues/1005): \[java] CloneMethodMustImplementCloneable triggers for interfaces - * [#1669](https://github.com/pmd/pmd/issues/1669): \[java] NullAssignment - FP with ternay and null as constructor argument - * [#1831](https://github.com/pmd/pmd/issues/1831): \[java] DetachedTestCase reports abstract methods - * [#1899](https://github.com/pmd/pmd/issues/1899): \[java] Recognize @SuppressWanings("fallthrough") for MissingBreakInSwitch - * [#2320](https://github.com/pmd/pmd/issues/2320): \[java] NullAssignment - FP with ternary and null as method argument - * [#2532](https://github.com/pmd/pmd/issues/2532): \[java] AvoidDecimalLiteralsInBigDecimalConstructor can not detect the case `new BigDecimal(Expression)` - * [#2579](https://github.com/pmd/pmd/issues/2579): \[java] MissingBreakInSwitch detects the lack of break in the last case - * [#2880](https://github.com/pmd/pmd/issues/2880): \[java] CompareObjectsWithEquals - false negative with type res - * [#2893](https://github.com/pmd/pmd/issues/2893): \[java] Remove special cases from rule EmptyCatchBlock - * [#2894](https://github.com/pmd/pmd/issues/2894): \[java] Improve MissingBreakInSwitch - * [#3071](https://github.com/pmd/pmd/issues/3071): \[java] BrokenNullCheck FP with PMD 6.30.0 - * [#3087](https://github.com/pmd/pmd/issues/3087): \[java] UnnecessaryBooleanAssertion overlaps with SimplifiableTestAssertion - * [#3100](https://github.com/pmd/pmd/issues/3100): \[java] UseCorrectExceptionLogging FP in 6.31.0 - * [#3173](https://github.com/pmd/pmd/issues/3173): \[java] UseProperClassLoader false positive - * [#3351](https://github.com/pmd/pmd/issues/3351): \[java] ConstructorCallsOverridableMethod ignores abstract methods - * [#3400](https://github.com/pmd/pmd/issues/3400): \[java] AvoidUsingOctalValues FN with underscores - * [#3843](https://github.com/pmd/pmd/issues/3843): \[java] UseEqualsToCompareStrings should consider return type - * [#4063](https://github.com/pmd/pmd/issues/4063): \[java] AvoidBranchingStatementAsLastInLoop: False-negative about try/finally block - * [#4356](https://github.com/pmd/pmd/pull/4356): \[java] Fix NPE in CloseResourceRule - * [#4449](https://github.com/pmd/pmd/issues/4449): \[java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression - * [#4457](https://github.com/pmd/pmd/issues/4457): \[java] OverrideBothEqualsAndHashcode: false negative with anonymous classes - * [#4493](https://github.com/pmd/pmd/issues/4493): \[java] MissingStaticMethodInNonInstantiatableClass: false-positive about @Inject - * [#4505](https://github.com/pmd/pmd/issues/4505): \[java] ImplicitSwitchFallThrough NPE in PMD 7.0.0-rc1 - * [#4510](https://github.com/pmd/pmd/issues/4510): \[java] ConstructorCallsOverridableMethod: false positive with lombok's @Value - * [#4513](https://github.com/pmd/pmd/issues/4513): \[java] UselessOperationOnImmutable various false negatives with String - * [#4514](https://github.com/pmd/pmd/issues/4514): \[java] AvoidLiteralsInIfCondition false positive and negative for String literals when ignoreExpressions=true - * [#4546](https://github.com/pmd/pmd/issues/4546): \[java] OverrideBothEqualsAndHashCode ignores records - * [#4719](https://github.com/pmd/pmd/pull/4719): \[java] UnnecessaryCaseChange: example doc toUpperCase() should compare to a capitalized string + * [#659](https://github.com/pmd/pmd/issues/659): \[java] MissingBreakInSwitch - last default case does not contain a break + * [#718](https://github.com/pmd/pmd/issues/718): \[java] BrokenNullCheck false positive with parameter/field confusion + * [#932](https://github.com/pmd/pmd/issues/932): \[java] SingletonClassReturningNewInstance false positive with double assignment + * [#1005](https://github.com/pmd/pmd/issues/1005): \[java] CloneMethodMustImplementCloneable triggers for interfaces + * [#1669](https://github.com/pmd/pmd/issues/1669): \[java] NullAssignment - FP with ternay and null as constructor argument + * [#1831](https://github.com/pmd/pmd/issues/1831): \[java] DetachedTestCase reports abstract methods + * [#1899](https://github.com/pmd/pmd/issues/1899): \[java] Recognize @SuppressWanings("fallthrough") for MissingBreakInSwitch + * [#2320](https://github.com/pmd/pmd/issues/2320): \[java] NullAssignment - FP with ternary and null as method argument + * [#2532](https://github.com/pmd/pmd/issues/2532): \[java] AvoidDecimalLiteralsInBigDecimalConstructor can not detect the case `new BigDecimal(Expression)` + * [#2579](https://github.com/pmd/pmd/issues/2579): \[java] MissingBreakInSwitch detects the lack of break in the last case + * [#2880](https://github.com/pmd/pmd/issues/2880): \[java] CompareObjectsWithEquals - false negative with type res + * [#2893](https://github.com/pmd/pmd/issues/2893): \[java] Remove special cases from rule EmptyCatchBlock + * [#2894](https://github.com/pmd/pmd/issues/2894): \[java] Improve MissingBreakInSwitch + * [#3071](https://github.com/pmd/pmd/issues/3071): \[java] BrokenNullCheck FP with PMD 6.30.0 + * [#3087](https://github.com/pmd/pmd/issues/3087): \[java] UnnecessaryBooleanAssertion overlaps with SimplifiableTestAssertion + * [#3100](https://github.com/pmd/pmd/issues/3100): \[java] UseCorrectExceptionLogging FP in 6.31.0 + * [#3173](https://github.com/pmd/pmd/issues/3173): \[java] UseProperClassLoader false positive + * [#3351](https://github.com/pmd/pmd/issues/3351): \[java] ConstructorCallsOverridableMethod ignores abstract methods + * [#3400](https://github.com/pmd/pmd/issues/3400): \[java] AvoidUsingOctalValues FN with underscores + * [#3843](https://github.com/pmd/pmd/issues/3843): \[java] UseEqualsToCompareStrings should consider return type + * [#4063](https://github.com/pmd/pmd/issues/4063): \[java] AvoidBranchingStatementAsLastInLoop: False-negative about try/finally block + * [#4356](https://github.com/pmd/pmd/pull/4356): \[java] Fix NPE in CloseResourceRule + * [#4449](https://github.com/pmd/pmd/issues/4449): \[java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression + * [#4457](https://github.com/pmd/pmd/issues/4457): \[java] OverrideBothEqualsAndHashcode: false negative with anonymous classes + * [#4493](https://github.com/pmd/pmd/issues/4493): \[java] MissingStaticMethodInNonInstantiatableClass: false-positive about @Inject + * [#4505](https://github.com/pmd/pmd/issues/4505): \[java] ImplicitSwitchFallThrough NPE in PMD 7.0.0-rc1 + * [#4510](https://github.com/pmd/pmd/issues/4510): \[java] ConstructorCallsOverridableMethod: false positive with lombok's @Value + * [#4513](https://github.com/pmd/pmd/issues/4513): \[java] UselessOperationOnImmutable various false negatives with String + * [#4514](https://github.com/pmd/pmd/issues/4514): \[java] AvoidLiteralsInIfCondition false positive and negative for String literals when ignoreExpressions=true + * [#4546](https://github.com/pmd/pmd/issues/4546): \[java] OverrideBothEqualsAndHashCode ignores records + * [#4719](https://github.com/pmd/pmd/pull/4719): \[java] UnnecessaryCaseChange: example doc toUpperCase() should compare to a capitalized string * java-multithreading - * [#2537](https://github.com/pmd/pmd/issues/2537): \[java] DontCallThreadRun can't detect the case that call run() in `this.run()` - * [#2538](https://github.com/pmd/pmd/issues/2538): \[java] DontCallThreadRun can't detect the case that call run() in `foo.bar.run()` - * [#2577](https://github.com/pmd/pmd/issues/2577): \[java] UseNotifyAllInsteadOfNotify falsely detect a special case with argument: `foo.notify(bar)` - * [#4483](https://github.com/pmd/pmd/issues/4483): \[java] NonThreadSafeSingleton false positive with double-checked locking + * [#2537](https://github.com/pmd/pmd/issues/2537): \[java] DontCallThreadRun can't detect the case that call run() in `this.run()` + * [#2538](https://github.com/pmd/pmd/issues/2538): \[java] DontCallThreadRun can't detect the case that call run() in `foo.bar.run()` + * [#2577](https://github.com/pmd/pmd/issues/2577): \[java] UseNotifyAllInsteadOfNotify falsely detect a special case with argument: `foo.notify(bar)` + * [#4483](https://github.com/pmd/pmd/issues/4483): \[java] NonThreadSafeSingleton false positive with double-checked locking * java-performance - * [#1224](https://github.com/pmd/pmd/issues/1224): \[java] InefficientEmptyStringCheck false negative in anonymous class - * [#2587](https://github.com/pmd/pmd/issues/2587): \[java] AvoidArrayLoops could also check for list copy through iterated List.add() - * [#2712](https://github.com/pmd/pmd/issues/2712): \[java] SimplifyStartsWith false-positive with AssertJ - * [#3486](https://github.com/pmd/pmd/pull/3486): \[java] InsufficientStringBufferDeclaration: Fix NPE - * [#3848](https://github.com/pmd/pmd/issues/3848): \[java] StringInstantiation: false negative when using method result - * [#4070](https://github.com/pmd/pmd/issues/4070): \[java] A false positive about the rule RedundantFieldInitializer - * [#4458](https://github.com/pmd/pmd/issues/4458): \[java] RedundantFieldInitializer: false positive with lombok's @Value + * [#1224](https://github.com/pmd/pmd/issues/1224): \[java] InefficientEmptyStringCheck false negative in anonymous class + * [#2587](https://github.com/pmd/pmd/issues/2587): \[java] AvoidArrayLoops could also check for list copy through iterated List.add() + * [#2712](https://github.com/pmd/pmd/issues/2712): \[java] SimplifyStartsWith false-positive with AssertJ + * [#3486](https://github.com/pmd/pmd/pull/3486): \[java] InsufficientStringBufferDeclaration: Fix NPE + * [#3848](https://github.com/pmd/pmd/issues/3848): \[java] StringInstantiation: false negative when using method result + * [#4070](https://github.com/pmd/pmd/issues/4070): \[java] A false positive about the rule RedundantFieldInitializer + * [#4458](https://github.com/pmd/pmd/issues/4458): \[java] RedundantFieldInitializer: false positive with lombok's @Value * javascript - * [#4673](https://github.com/pmd/pmd/pull/4673): \[javascript] CPD: Added support for decorator notation + * [#4673](https://github.com/pmd/pmd/pull/4673): \[javascript] CPD: Added support for decorator notation * kotlin - * [#419](https://github.com/pmd/pmd/issues/419): \[kotlin] Add support for Kotlin - * [#4389](https://github.com/pmd/pmd/pull/4389): \[kotlin] Update grammar to version 1.8 + * [#419](https://github.com/pmd/pmd/issues/419): \[kotlin] Add support for Kotlin + * [#4389](https://github.com/pmd/pmd/pull/4389): \[kotlin] Update grammar to version 1.8 * plsql - * [#4820](https://github.com/pmd/pmd/issues/4820): \[plsql] WITH clause is ignored for SELECT INTO statements + * [#4820](https://github.com/pmd/pmd/issues/4820): \[plsql] WITH clause is ignored for SELECT INTO statements * swift - * [#1877](https://github.com/pmd/pmd/pull/1877): \[swift] Feature/swift rules - * [#1882](https://github.com/pmd/pmd/pull/1882): \[swift] UnavailableFunction Swift rule - * [#4697](https://github.com/pmd/pmd/issues/4697): \[swift] Support Swift 5.9 features (mainly macros expansion expressions) + * [#1877](https://github.com/pmd/pmd/pull/1877): \[swift] Feature/swift rules + * [#1882](https://github.com/pmd/pmd/pull/1882): \[swift] UnavailableFunction Swift rule + * [#4697](https://github.com/pmd/pmd/issues/4697): \[swift] Support Swift 5.9 features (mainly macros expansion expressions) * xml - * [#1800](https://github.com/pmd/pmd/pull/1800): \[xml] Unimplement org.w3c.dom.Node from the XmlNodeWrapper + * [#1800](https://github.com/pmd/pmd/pull/1800): \[xml] Unimplement org.w3c.dom.Node from the XmlNodeWrapper * xml-bestpractices - * [#4592](https://github.com/pmd/pmd/pull/4592): \[xml] Add MissingEncoding rule + * [#4592](https://github.com/pmd/pmd/pull/4592): \[xml] Add MissingEncoding rule ## ✨ External Contributions diff --git a/pmd-ant/pom.xml b/pmd-ant/pom.xml index 92156edb96..ce517cdd1a 100644 --- a/pmd-ant/pom.xml +++ b/pmd-ant/pom.xml @@ -7,7 +7,7 @@ pmd net.sourceforge.pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT 4.0.0 diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml index 7324f13452..42af8646ed 100644 --- a/pmd-apex/pom.xml +++ b/pmd-apex/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CognitiveComplexityRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CognitiveComplexityRule.java index 37112180d7..28a2110917 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CognitiveComplexityRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CognitiveComplexityRule.java @@ -75,7 +75,7 @@ public class CognitiveComplexityRule extends AbstractApexRule { String.valueOf(classLevelThreshold), }; - asCtx(data).addViolation(node, messageParams); + asCtx(data).addViolation(node, (Object[]) messageParams); } } return data; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityRule.java index 9318666fa5..e1af8663df 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/CyclomaticComplexityRule.java @@ -78,7 +78,7 @@ public class CyclomaticComplexityRule extends AbstractApexRule { " total", classWmc + " (highest " + classHighest + ")", }; - asCtx(data).addViolation(node, messageParams); + asCtx(data).addViolation(node, (Object[]) messageParams); } } return data; diff --git a/pmd-cli/pom.xml b/pmd-cli/pom.xml index 946c1a8d55..9b7a284ad1 100644 --- a/pmd-cli/pom.xml +++ b/pmd-cli/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-coco/pom.xml b/pmd-coco/pom.xml index c142f4225d..fe97db0606 100644 --- a/pmd-coco/pom.xml +++ b/pmd-coco/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-compat6/pom.xml b/pmd-compat6/pom.xml index d442413de1..c2f957d9a1 100644 --- a/pmd-compat6/pom.xml +++ b/pmd-compat6/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT pmd-compat6 diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml index 67cd064514..62e389fde9 100644 --- a/pmd-core/pom.xml +++ b/pmd-core/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/MatchCollector.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/MatchCollector.java index b79ac5efbd..36c6e99c2f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/MatchCollector.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/MatchCollector.java @@ -5,14 +5,20 @@ package net.sourceforge.pmd.cpd; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; class MatchCollector { - private final List matchList = new ArrayList<>(); - private final Map> matchTree = new TreeMap<>(); + private final Map> matchTree = new TreeMap<>(); + + private final Map> tokenMatchSets = new HashMap<>(); + private final MatchAlgorithm ma; MatchCollector(MatchAlgorithm ma) { @@ -21,12 +27,18 @@ class MatchCollector { public void collect(List marks) { // first get a pairwise collection of all maximal matches - for (int i = 0; i < marks.size() - 1; i++) { + int skipped; + for (int i = 0; i < marks.size() - 1; i += skipped + 1) { + skipped = 0; TokenEntry mark1 = marks.get(i); for (int j = i + 1; j < marks.size(); j++) { TokenEntry mark2 = marks.get(j); int diff = mark1.getIndex() - mark2.getIndex(); if (-diff < ma.getMinimumTileSize()) { + // self-repeating sequence such as ABBABBABB with min 6, + // will match 2 against any other occurrence of ABBABB + // avoid duplicate overlapping reports by skipping it on the next outer loop + skipped++; continue; } if (hasPreviousDupe(mark1, mark2)) { @@ -38,7 +50,7 @@ class MatchCollector { if (dupes < ma.getMinimumTileSize()) { continue; } - // is it still too close together + // both blocks overlap if (diff + dupes >= 1) { continue; } @@ -48,37 +60,71 @@ class MatchCollector { } private void reportMatch(TokenEntry mark1, TokenEntry mark2, int dupes) { - matchTree.compute(dupes, (dupCount, matches) -> { - if (matches == null) { - matches = new TreeMap<>(); - addNewMatch(mark1, mark2, dupCount, matches); - } else { - Match matchA = matches.get(mark1.getIndex()); - Match matchB = matches.get(mark2.getIndex()); + /* + * Check if the match is previously know. This can happen when a snippet is duplicated more than once. + * If A, B and C are identical snippets, MatchAlgorithm will find the matching pairs: + * - AB + * - AC + * - BC + * It should be reduced to a single match with 3 marks + */ + if (tokenMatchSets.computeIfAbsent(mark1.getIndex(), HashSet::new).contains(mark2.getIndex())) { + return; + } - if (matchA == null && matchB == null) { - addNewMatch(mark1, mark2, dupes, matches); - } else if (matchA == null) { - matchB.addMark(mark1); - matches.put(mark1.getIndex(), matchB); - } else if (matchB == null) { - matchA.addMark(mark2); - matches.put(mark2.getIndex(), matchA); + // This may not be a "new match", but actually a sub-match of a larger one. + // always rely on the lowest mark index, as that's the order in which process them + final int lowestKey = tokenMatchSets.get(mark1.getIndex()).stream().reduce(mark1.getIndex(), Math::min); + + List matches = matchTree.computeIfAbsent(lowestKey, ArrayList::new); + Iterator matchIterator = matches.iterator(); + while (matchIterator.hasNext()) { + Match m = matchIterator.next(); + + // Check all other marks + for (Mark otherMark : m.getMarkSet()) { + TokenEntry otherEnd = otherMark.getToken(); + if (otherEnd.getIndex() == mark1.getIndex()) { + continue; + } + + // does the new match supersedes this one? + if (otherEnd.getIndex() < mark2.getIndex() && otherEnd.getIndex() + m.getTokenCount() >= mark2.getIndex() + dupes) { + // this match is embedded in the previous one… ignore it. + return; + } else if (mark2.getIndex() < otherEnd.getIndex() && mark2.getIndex() + dupes >= otherEnd.getIndex() + m.getTokenCount()) { + // the new match is longer and overlaps with the old one - replace it + matchIterator.remove(); + break; + } else if (dupes == m.getTokenCount()) { + // we found yet another exact match of the same snippet. Roll it together + + // Add this adjacency to all combinations + m.iterator().forEachRemaining(other -> registerTokenMatch(other.getToken(), mark2)); + + m.addMark(mark2); + return; } } - return matches; - }); + } + + // this is a new match, add it + matches.add(new Match(dupes, mark1, mark2)); + + // add matches in both directions + registerTokenMatch(mark1, mark2); } - private void addNewMatch(TokenEntry mark1, TokenEntry mark2, int dupes, Map matches) { - Match match = new Match(dupes, mark1, mark2); - matches.put(mark1.getIndex(), match); - matches.put(mark2.getIndex(), match); - matchList.add(match); + private void registerTokenMatch(TokenEntry mark1, TokenEntry mark2) { + tokenMatchSets.computeIfAbsent(mark1.getIndex(), HashSet::new).add(mark2.getIndex()); + tokenMatchSets.computeIfAbsent(mark2.getIndex(), HashSet::new).add(mark1.getIndex()); } List getMatches() { - return matchList; + return matchTree.values().stream().reduce(new ArrayList<>(), (acc, matches) -> { + acc.addAll(matches); + return acc; + }); } private boolean hasPreviousDupe(TokenEntry mark1, TokenEntry mark2) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/BaseNodeInfo.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/BaseNodeInfo.java index 55f8458051..2ad543c236 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/BaseNodeInfo.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/BaseNodeInfo.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.rule.xpath.internal; +import java.util.Collections; import java.util.List; import java.util.ListIterator; @@ -105,16 +106,15 @@ abstract class BaseNodeInfo extends AbstractNodeWrapper implements SiblingCounti return iterateList(nodes, true); } - @SuppressWarnings({"unchecked", "rawtypes"}) - static AxisIterator iterateList(List nodes, boolean forwards) { - return forwards ? new NodeListIterator((List) nodes) - : new RevListAxisIterator((List) nodes); + static AxisIterator iterateList(List nodes, boolean forwards) { + return forwards ? new NodeListIterator(Collections.unmodifiableList(nodes)) + : new RevListAxisIterator<>(nodes); } - private static class RevListAxisIterator implements AxisIterator { - private final ListIterator iter; + private static class RevListAxisIterator implements AxisIterator { + private final ListIterator iter; - RevListAxisIterator(List list) { + RevListAxisIterator(List list) { iter = list.listIterator(list.size()); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java index 9294c59a6b..9347de077c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/CollectionUtil.java @@ -662,6 +662,18 @@ public final class CollectionUtil { } } + /** + * Union of two PSets, which avoids creating a new pset if possible. + */ + public static PSet union(PSet as, PSet bs) { + if (as.isEmpty()) { + return bs; + } else if (bs.isEmpty()) { + return as; + } + return as.plusAll(bs); + } + public static @NonNull List makeUnmodifiableAndNonNull(@Nullable List list) { if (list instanceof PSequence) { return (List) list; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/MatchAlgorithmTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/MatchAlgorithmTest.java index 2ddee6712a..5e2afca9b2 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/MatchAlgorithmTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/MatchAlgorithmTest.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.cpd; import static net.sourceforge.pmd.util.CollectionUtil.listOf; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.Iterator; @@ -35,6 +36,18 @@ class MatchAlgorithmTest { + "\n" + LINE_7 + "\n" + LINE_8; } + private static String getMultipleRepetitionsCode() { + return "var x = [\n" + + " 1, 1, 1, 1, 1, 1, 1, 1,\n" + + " 0, 0, 0, 0, 0, 0, 0, 0,\n" + + " 2, 2, 2, 2, 2, 2, 2, 2,\n" + + " 0, 0, 0, 0, 0, 0, 0, 0,\n" + + " 3, 3, 3, 3, 3, 3, 3, 3,\n" + + " 0, 0, 0, 0, 0, 0, 0, 0,\n" + + " 4, 4, 4, 4, 4, 4, 4, 4\n" + + "];"; + } + @Test void testSimple() throws IOException { DummyLanguageModule dummy = DummyLanguageModule.getInstance(); @@ -65,4 +78,36 @@ class MatchAlgorithmTest { assertEquals(fileName, mark2.getLocation().getFileId()); assertEquals(LINE_4 + "\n", sourceManager.getSlice(mark2).toString()); } + + @Test + void testMultipleMatches() throws IOException { + DummyLanguageModule dummy = DummyLanguageModule.getInstance(); + CpdLexer cpdLexer = dummy.createCpdLexer(dummy.newPropertyBundle()); + FileId fileName = FileId.fromPathLikeString("Foo.dummy"); + TextFile textFile = TextFile.forCharSeq(getMultipleRepetitionsCode(), fileName, dummy.getDefaultVersion()); + SourceManager sourceManager = new SourceManager(listOf(textFile)); + Tokens tokens = new Tokens(); + TextDocument sourceCode = sourceManager.get(textFile); + CpdLexer.tokenize(cpdLexer, sourceCode, tokens); + + MatchAlgorithm matchAlgorithm = new MatchAlgorithm(tokens, 15); + List matches = matchAlgorithm.findMatches(new CPDNullListener(), sourceManager); + assertEquals(1, matches.size()); + Match match = matches.get(0); + + Iterator marks = match.iterator(); + Mark mark1 = marks.next(); + Mark mark2 = marks.next(); + assertTrue(marks.hasNext()); + Mark mark3 = marks.next(); + + assertEquals(2, mark1.getLocation().getStartLine()); + assertEquals(fileName, mark1.getLocation().getFileId()); + + assertEquals(4, mark2.getLocation().getStartLine()); + assertEquals(fileName, mark2.getLocation().getFileId()); + + assertEquals(6, mark3.getLocation().getStartLine()); + assertEquals(fileName, mark3.getLocation().getFileId()); + } } diff --git a/pmd-cpp/pom.xml b/pmd-cpp/pom.xml index 8b2baf8fc5..83e10131b0 100644 --- a/pmd-cpp/pom.xml +++ b/pmd-cpp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-cpp/src/test/java/net/sourceforge/pmd/lang/cpp/cpd/CppCpdTest.java b/pmd-cpp/src/test/java/net/sourceforge/pmd/lang/cpp/cpd/CppCpdTest.java new file mode 100644 index 0000000000..0496a37a82 --- /dev/null +++ b/pmd-cpp/src/test/java/net/sourceforge/pmd/lang/cpp/cpd/CppCpdTest.java @@ -0,0 +1,44 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.cpp.cpd; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import net.sourceforge.pmd.cpd.CPDConfiguration; +import net.sourceforge.pmd.cpd.CpdAnalysis; +import net.sourceforge.pmd.internal.util.IOUtil; +import net.sourceforge.pmd.lang.cpp.CppLanguageModule; + +class CppCpdTest { + private Path testdir; + + @BeforeEach + void setUp() { + String path = IOUtil.normalizePath("src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata"); + testdir = Paths.get(path); + } + + @Test + void testIssue2438() throws Exception { + CPDConfiguration configuration = new CPDConfiguration(); + configuration.setMinimumTileSize(50); + configuration.setOnlyRecognizeLanguage(CppLanguageModule.getInstance()); + try (CpdAnalysis cpd = CpdAnalysis.create(configuration)) { + cpd.files().addFile(testdir.resolve("ctype.c")); + + cpd.performAnalysis(matches -> { + // There should only be 1 duplication, and it should be maximal + assertEquals(1, matches.getMatches().size()); + assertEquals(128, matches.getMatches().get(0).getTokenCount()); + }); + } + } +} diff --git a/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/ctype.c b/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/ctype.c new file mode 100644 index 0000000000..bf58aac5ad --- /dev/null +++ b/pmd-cpp/src/test/resources/net/sourceforge/pmd/lang/cpp/cpd/testdata/ctype.c @@ -0,0 +1,29 @@ +#include + +char _ctmp; +unsigned char _ctype[] = {0x00, /* EOF */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 160-175 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 176-191 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 192-207 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 208-223 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 224-239 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* 240-255 */ + diff --git a/pmd-cs/pom.xml b/pmd-cs/pom.xml index 961ea3bbd2..35d1e15296 100644 --- a/pmd-cs/pom.xml +++ b/pmd-cs/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-dart/pom.xml b/pmd-dart/pom.xml index 0ae496e75a..795188bfe7 100644 --- a/pmd-dart/pom.xml +++ b/pmd-dart/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml index 544dec8f55..72a6d4c1d5 100644 --- a/pmd-dist/pom.xml +++ b/pmd-dist/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml index 10f70bd0e4..2d9a5acba0 100644 --- a/pmd-doc/pom.xml +++ b/pmd-doc/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-fortran/pom.xml b/pmd-fortran/pom.xml index 4629e05389..754de6aa55 100644 --- a/pmd-fortran/pom.xml +++ b/pmd-fortran/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-gherkin/pom.xml b/pmd-gherkin/pom.xml index 86ee0f2b8a..79f5588ae7 100644 --- a/pmd-gherkin/pom.xml +++ b/pmd-gherkin/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-go/pom.xml b/pmd-go/pom.xml index 88ac216243..e3e1490468 100644 --- a/pmd-go/pom.xml +++ b/pmd-go/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-groovy/pom.xml b/pmd-groovy/pom.xml index 0d15dfbb0b..677f0d4559 100644 --- a/pmd-groovy/pom.xml +++ b/pmd-groovy/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-html/pom.xml b/pmd-html/pom.xml index a184d7cc1f..c1168e66f5 100644 --- a/pmd-html/pom.xml +++ b/pmd-html/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index dbc0c16c0a..b85f32cfb0 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLambdaExpression.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLambdaExpression.java index cb6e353da9..dcf14f021d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLambdaExpression.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLambdaExpression.java @@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.java.ast; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.types.JMethodSig; import net.sourceforge.pmd.lang.java.types.JTypeMirror; @@ -75,33 +74,39 @@ public final class ASTLambdaExpression extends AbstractJavaExpr implements Funct return !isBlockBody(); } - /** Returns the body of this expression, if it is a block. */ - @Nullable - public ASTBlock getBlock() { - return AstImplUtil.getChildAs(this, 1, ASTBlock.class); + /** + * Returns the body of this expression, if it is a block. + * + * @deprecated Use {@link #getBlockBody()} + */ + @Deprecated + public @Nullable ASTBlock getBlock() { + return getBlockBody(); } - /** Returns the body of this expression, if it is an expression. */ - @Nullable - public ASTExpression getExpression() { - return AstImplUtil.getChildAs(this, 1, ASTExpression.class); + /** + * Returns the body of this expression, if it is an expression. + * + * @deprecated Use {@link #getExpressionBody()} + */ + @Deprecated + public @Nullable ASTExpression getExpression() { + return getExpressionBody(); } /** * Returns the body of this lambda if it is a block. */ - @Nullable - public ASTBlock getBlockBody() { - return NodeStream.of(getLastChild()).filterIs(ASTBlock.class).first(); + public @Nullable ASTBlock getBlockBody() { + return AstImplUtil.getChildAs(this, 1, ASTBlock.class); } /** * Returns the body of this lambda if it is an expression. */ - @Nullable - public ASTExpression getExpressionBody() { - return NodeStream.of(getLastChild()).filterIs(ASTExpression.class).first(); + public @Nullable ASTExpression getExpressionBody() { + return AstImplUtil.getChildAs(this, 1, ASTExpression.class); } @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java index 43464c046d..7d28a03cad 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/internal/PrettyPrintingUtil.java @@ -383,7 +383,7 @@ public final class PrettyPrintingUtil { public Void visit(ASTLambdaExpression node, StringBuilder sb) { node.getParameters().acceptVisitor(this, sb); sb.append(" -> "); - ASTExpression exprBody = node.getExpression(); + ASTExpression exprBody = node.getExpressionBody(); if (exprBody != null) { exprBody.acceptVisitor(this, sb); } else { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AccessorMethodGenerationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AccessorMethodGenerationRule.java index 0313d95be8..33e8e96c41 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AccessorMethodGenerationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/AccessorMethodGenerationRule.java @@ -76,7 +76,7 @@ public class AccessorMethodGenerationRule extends AbstractJavaRulechainRule { JavaNode node = sym.tryGetNode(); assert node != null : "Node should be in the same compilation unit"; if (reportedNodes.add(node)) { - ruleContext.addViolation(node, new String[] {stripPackageName(refExpr.getEnclosingType().getSymbol())}); + ruleContext.addViolation(node, stripPackageName(refExpr.getEnclosingType().getSymbol())); } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java index 74aed90913..da2fba47ea 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java @@ -24,7 +24,7 @@ public class MissingOverrideRule extends AbstractJavaRulechainRule { @Override public Object visit(ASTMethodDeclaration node, Object data) { if (node.isOverridden() && !node.isAnnotationPresent(Override.class)) { - asCtx(data).addViolation(node, new Object[] { PrettyPrintingUtil.displaySignature(node) }); + asCtx(data).addViolation(node, PrettyPrintingUtil.displaySignature(node)); } return data; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnnecessaryVarargsArrayCreationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnnecessaryVarargsArrayCreationRule.java index 9ecb6e5374..fbddc7e33f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnnecessaryVarargsArrayCreationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnnecessaryVarargsArrayCreationRule.java @@ -11,10 +11,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation; import net.sourceforge.pmd.lang.java.ast.InvocationNode; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; -import net.sourceforge.pmd.lang.java.types.JArrayType; import net.sourceforge.pmd.lang.java.types.JTypeMirror; import net.sourceforge.pmd.lang.java.types.OverloadSelectionResult; -import net.sourceforge.pmd.lang.java.types.TypePrettyPrint; public class UnnecessaryVarargsArrayCreationRule extends AbstractJavaRulechainRule { @@ -26,6 +24,9 @@ public class UnnecessaryVarargsArrayCreationRule extends AbstractJavaRulechainRu @Override public Object visit(ASTArrayAllocation array, Object data) { + if (array.getArrayInitializer() == null) { + return null; + } JavaNode parent = array.getParent(); if (parent instanceof ASTArgumentList && array.getIndexInParent() == parent.getNumChildren() - 1) { @@ -39,19 +40,10 @@ public class UnnecessaryVarargsArrayCreationRule extends AbstractJavaRulechainRu List formals = info.getMethodType().getFormalParameters(); JTypeMirror lastFormal = formals.get(formals.size() - 1); - JTypeMirror expectedComponent = ((JArrayType) lastFormal).getComponentType(); - if (array.getTypeMirror().isSubtypeOf(expectedComponent) - && !array.getTypeMirror().equals(lastFormal)) { - // confusing - asCtx(data) - .addViolationWithMessage( - array, - "Unclear if a varargs or non-varargs call is intended. Cast to {0} or {0}[], or pass varargs parameters separately to clarify intent.", - TypePrettyPrint.prettyPrintWithSimpleNames(expectedComponent) - ); - } else if (array.getArrayInitializer() != null) { - // just regular unnecessary + if (array.getTypeMirror().equals(lastFormal)) { + // If type not equal, then it would not actually be equivalent to remove the array creation. + // That case may be caught by ConfusingArgumentToVarargsMethod asCtx(data).addViolation(array); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java index 4962c3e415..76dd7645f7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedFormalParameterRule.java @@ -52,7 +52,7 @@ public class UnusedFormalParameterRule extends AbstractJavaRulechainRule { for (ASTFormalParameter formal : node.getFormalParameters()) { ASTVariableId varId = formal.getVarId(); if (JavaAstUtils.isNeverUsed(varId) && !JavaRuleUtil.isExplicitUnusedVarName(varId.getName())) { - asCtx(data).addViolation(varId, new Object[] { node instanceof ASTMethodDeclaration ? "method" : "constructor", varId.getName(), }); + asCtx(data).addViolation(varId, node instanceof ASTMethodDeclaration ? "method" : "constructor", varId.getName()); } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedPrivateMethodRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedPrivateMethodRule.java index 53a8c42434..4d239378b9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedPrivateMethodRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedPrivateMethodRule.java @@ -12,6 +12,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.ast.ASTAnnotation; @@ -20,7 +21,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodReference; import net.sourceforge.pmd.lang.java.ast.ASTModifierList; -import net.sourceforge.pmd.lang.java.ast.ASTStringLiteral; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.MethodUsage; import net.sourceforge.pmd.lang.java.ast.ModifierOwner.Visibility; @@ -54,12 +54,15 @@ public class UnusedPrivateMethodRule extends AbstractIgnoredAnnotationRule { // first set, ie, not every call in the file. Set methodsUsedByAnnotations = file.descendants(ASTMethodDeclaration.class) + .crossFindBoundaries() .children(ASTModifierList.class) .children(ASTAnnotation.class) .filter(t -> TypeTestUtil.isA("org.junit.jupiter.params.provider.MethodSource", t)) - .descendants(ASTStringLiteral.class) .toStream() - .map(ASTStringLiteral::getConstValue) + // Get the referenced method names… if none, use the test method name instead + .flatMap(a -> a.getFlatValue("value").isEmpty() + ? Stream.of(a.ancestors(ASTMethodDeclaration.class).first().getName()) + : a.getFlatValue("value").toStream().map(mv -> (String) mv.getConstValue())) .collect(Collectors.toSet()); Map> consideredNames = diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java index ae98020f5e..4c1503392d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/AbstractNamingConventionRule.java @@ -60,11 +60,9 @@ abstract class AbstractNamingConventionRule extends Abstract void checkMatches(T node, PropertyDescriptor regex, Object data) { String name = nameExtractor(node); if (!getProperty(regex).matcher(name).matches()) { - asCtx(data).addViolation(node, new Object[]{ - kindDisplayName(node, regex), - name, - getProperty(regex).toString(), - }); + asCtx(data).addViolation(node, kindDisplayName(node, regex), + name, + getProperty(regex).toString()); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java index 8ebab9356d..7b0f65506a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/FieldNamingConventionsRule.java @@ -90,11 +90,9 @@ public class FieldNamingConventionsRule extends AbstractNamingConventionRule IGNORE_IF_MAY_NPE = + PropertyFactory.booleanProperty("ignoreIfMayNPE") + .desc("Ignore lambdas that may throw a null pointer exception (NPE) when converted to a method reference. " + + "Those expressions will NPE at mref creation time, while the equivalent lambda would NPE only when invoked (which may be never).") + .defaultValue(false) + .build(); + + + private static final PropertyDescriptor IGNORE_IF_RECEIVER_IS_METHOD = + PropertyFactory.booleanProperty("ignoreIfReceiverIsMethod") + .desc("Ignore if the receiver of the method reference is a method call. " + + "These may cause side effects that often should prevent the conversion to a method reference.") + .defaultValue(true) + .build(); + + public LambdaCanBeMethodReferenceRule() { + super(ASTLambdaExpression.class); + definePropertyDescriptor(IGNORE_IF_MAY_NPE); + definePropertyDescriptor(IGNORE_IF_RECEIVER_IS_METHOD); + } + + @Override + public Object visit(ASTLambdaExpression node, Object data) { + if (node.isExpressionBody()) { + ASTExpression expression = node.getExpressionBody(); + processLambdaWithBody(node, asCtx(data), expression); + } else { + ASTStatement onlyStmt = ASTList.singleOrNull(node.getBlockBody()); + if (onlyStmt instanceof ASTReturnStatement) { + processLambdaWithBody(node, asCtx(data), ((ASTReturnStatement) onlyStmt).getExpr()); + } + } + return null; + } + + private void processLambdaWithBody(ASTLambdaExpression lambda, RuleContext data, ASTExpression expression) { + if (lambda.getParameters().toStream().any(it -> it.getDeclaredAnnotations().nonEmpty())) { + return; + } + if (expression instanceof ASTMethodCall) { + ASTMethodCall call = (ASTMethodCall) expression; + if (canBeTransformed(lambda, call) && argumentsListMatches(call, lambda.getParameters())) { + data.addViolation(lambda, buildMethodRefString(lambda, call)); + } + } + } + + private String buildMethodRefString(ASTLambdaExpression lambda, ASTMethodCall call) { + StringBuilder sb = new StringBuilder(); + ASTExpression qualifier = call.getQualifier(); + OverloadSelectionResult info = call.getOverloadSelectionInfo(); + assert !info.isFailed() : "should not be failed: " + call; + + if (qualifier == null && info.getMethodType().isStatic() + || lambda.getParameters().size() != call.getArguments().size()) { + // this second condition corresponds to the case the first lambda + // param is the receiver of the method call + + JTypeDeclSymbol symbol = info.getMethodType().getDeclaringType().getSymbol(); + assert symbol != null + : "null symbol for " + info.getMethodType().getDeclaringType() + ", method " + info.getMethodType(); + sb.append(symbol.getSimpleName()); + } else if (qualifier == null) { + sb.append("this"); + } else { + boolean needsParentheses = !(qualifier instanceof ASTPrimaryExpression); + if (needsParentheses) { + sb.append('('); + } + sb.append(PrettyPrintingUtil.prettyPrint(qualifier)); + if (needsParentheses) { + sb.append(')'); + } + } + sb.append("::").append(call.getMethodName()); + return sb.toString(); + } + + private boolean argumentsListMatches(ASTMethodCall call, ASTLambdaParameterList params) { + ASTArgumentList args = call.getArguments(); + int start; + if (params.size() == args.size() + 1) { + // first parameter for the method call may be its receiver + start = 1; + JVariableSymbol firstParam = params.get(0).getVarId().getSymbol(); + if (!JavaAstUtils.isReferenceToVar(call.getQualifier(), firstParam)) { + return false; + } + } else if (args.size() == params.size()) { + start = 0; + } else { + return false; + } + + for (int i = 0; i < args.size(); i++) { + ASTExpression arg = args.get(i); + ASTLambdaParameter parm = params.get(i + start); + if (!JavaAstUtils.isReferenceToVar(arg, parm.getVarId().getSymbol())) { + return false; + } + } + return true; + } + + // coarse check to filter out some stuff before checking call arguments + private boolean canBeTransformed(ASTLambdaExpression lambda, ASTMethodCall call) { + ASTExpression qualifier = JavaAstUtils.peelCasts(call.getQualifier()); + if (call.getOverloadSelectionInfo().isFailed()) { + // err on the side of FNs + return false; + } + if (qualifier instanceof ASTConstructorCall) { + // ctors may not be transformed because that would change semantics, + // with only one instance being created + return false; + } else if (qualifier instanceof ASTTypeExpression + || qualifier instanceof ASTSuperExpression + || qualifier instanceof ASTThisExpression + || qualifier instanceof ASTClassLiteral + || qualifier instanceof ASTLiteral + || qualifier == null) { + // these are always transformable + return true; + } + + boolean isIgnoredBecauseOfMethodCall = + qualifier instanceof ASTMethodCall && getProperty(IGNORE_IF_RECEIVER_IS_METHOD); + + // if call uses first lambda parm as receiver, then the mref may not npe at creation time + boolean mayNPE = lambda.getParameters().size() == call.getArguments().size(); + boolean isIgnoredBecauseOfNPE = mayNPE && getProperty(IGNORE_IF_MAY_NPE); + return !isIgnoredBecauseOfNPE && !isIgnoredBecauseOfMethodCall; + + } + +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java index b0d8cce641..b571bfd5f3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/LinguisticNamingRule.java @@ -116,7 +116,7 @@ public class LinguisticNamingRule extends AbstractJavaRulechainRule { && prefixes.contains(splitMethodName[0].toLowerCase(Locale.ROOT))) { // "To" or any other configured prefix found asCtx(data).addViolationWithMessage(node, "Linguistics Antipattern - The transform method ''{0}'' should not return void linguistically", - new Object[] { nameOfMethod }); + nameOfMethod); } } @@ -125,7 +125,7 @@ public class LinguisticNamingRule extends AbstractJavaRulechainRule { if (node.isVoid() && containsCamelCaseWord(nameOfMethod, StringUtils.capitalize(infix))) { // "To" or any other configured infix in the middle somewhere asCtx(data).addViolationWithMessage(node, "Linguistics Antipattern - The transform method ''{0}'' should not return void linguistically", - new Object[] { nameOfMethod }); + nameOfMethod); // the first violation is sufficient - it is still the same method we are analyzing here break; } @@ -135,14 +135,14 @@ public class LinguisticNamingRule extends AbstractJavaRulechainRule { private void checkGetters(ASTMethodDeclaration node, Object data, String nameOfMethod) { if (startsWithCamelCaseWord(nameOfMethod, "get") && node.isVoid()) { asCtx(data).addViolationWithMessage(node, "Linguistics Antipattern - The getter ''{0}'' should not return void linguistically", - new Object[] { nameOfMethod }); + nameOfMethod); } } private void checkSetters(ASTMethodDeclaration node, Object data, String nameOfMethod) { if (startsWithCamelCaseWord(nameOfMethod, "set") && !node.isVoid()) { asCtx(data).addViolationWithMessage(node, "Linguistics Antipattern - The setter ''{0}'' should not return any type except void linguistically", - new Object[] { nameOfMethod }); + nameOfMethod); } } @@ -158,7 +158,7 @@ public class LinguisticNamingRule extends AbstractJavaRulechainRule { for (String prefix : getProperty(BOOLEAN_METHOD_PREFIXES_PROPERTY)) { if (startsWithCamelCaseWord(nameOfMethod, prefix) && !isBooleanType(t)) { asCtx(data).addViolationWithMessage(node, "Linguistics Antipattern - The method ''{0}'' indicates linguistically it returns a boolean, but it returns ''{1}''", - new Object[] {nameOfMethod, PrettyPrintingUtil.prettyPrintType(t) }); + nameOfMethod, PrettyPrintingUtil.prettyPrintType(t)); } } } @@ -168,7 +168,7 @@ public class LinguisticNamingRule extends AbstractJavaRulechainRule { for (String prefix : getProperty(BOOLEAN_FIELD_PREFIXES_PROPERTY)) { if (startsWithCamelCaseWord(node.getName(), prefix) && !isBooleanType(typeNode)) { asCtx(data).addViolationWithMessage(node, "Linguistics Antipattern - The field ''{0}'' indicates linguistically it is a boolean, but it is ''{1}''", - new Object[] { node.getName(), PrettyPrintingUtil.prettyPrintType(typeNode) }); + node.getName(), PrettyPrintingUtil.prettyPrintType(typeNode)); } } } @@ -177,7 +177,7 @@ public class LinguisticNamingRule extends AbstractJavaRulechainRule { for (String prefix : getProperty(BOOLEAN_FIELD_PREFIXES_PROPERTY)) { if (startsWithCamelCaseWord(node.getName(), prefix) && !isBooleanType(typeNode)) { asCtx(data).addViolationWithMessage(node, "Linguistics Antipattern - The variable ''{0}'' indicates linguistically it is a boolean, but it is ''{1}''", - new Object[] { node.getName(), PrettyPrintingUtil.prettyPrintType(typeNode) }); + node.getName(), PrettyPrintingUtil.prettyPrintType(typeNode)); } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java index b1172787a9..4c2b79b4bc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryFullyQualifiedNameRule.java @@ -88,7 +88,7 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRulechainRule // we don't actually know where the method came from String simpleName = formatMemberName(next, methodCall.getMethodType().getSymbol()); String unnecessary = produceQualifier(deepest, next, true); - asCtx(data).addViolation(next, new Object[] {unnecessary, simpleName, ""}); + asCtx(data).addViolation(next, unnecessary, simpleName, ""); return null; } } else if (getProperty(REPORT_FIELDS) && opa instanceof ASTFieldAccess) { @@ -98,7 +98,7 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRulechainRule String simpleName = formatMemberName(next, fieldAccess.getReferencedSym()); String reasonToString = unnecessaryReasonWrapper(reasonForFieldInScope); String unnecessary = produceQualifier(deepest, next, true); - asCtx(data).addViolation(next, new Object[] {unnecessary, simpleName, reasonToString}); + asCtx(data).addViolation(next, unnecessary, simpleName, reasonToString); return null; } } @@ -108,7 +108,7 @@ public class UnnecessaryFullyQualifiedNameRule extends AbstractJavaRulechainRule String simpleName = next.getSimpleName(); String reasonToString = unnecessaryReasonWrapper(bestReason); String unnecessary = produceQualifier(deepest, next, false); - asCtx(data).addViolation(next, new Object[] {unnecessary, simpleName, reasonToString}); + asCtx(data).addViolation(next, unnecessary, simpleName, reasonToString); } return null; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryImportRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryImportRule.java index 2b1bcf356e..b2049fa1fc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryImportRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryImportRule.java @@ -220,7 +220,7 @@ public class UnnecessaryImportRule extends AbstractJavaRule { } private void reportWithMessage(ASTImportDeclaration node, Object data, String message) { - asCtx(data).addViolationWithMessage(node, message, new String[] { PrettyPrintingUtil.prettyImport(node) }); + asCtx(data).addViolationWithMessage(node, message, PrettyPrintingUtil.prettyImport(node)); } @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryModifierRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryModifierRule.java index 358ce5719c..97c9a263b8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryModifierRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UnnecessaryModifierRule.java @@ -54,12 +54,10 @@ public class UnnecessaryModifierRule extends AbstractJavaRulechainRule { if (unnecessaryModifiers.isEmpty()) { return; } - asCtx(data).addViolation(node, new String[]{ - formatUnnecessaryModifiers(unnecessaryModifiers), - PrettyPrintingUtil.getPrintableNodeKind(node), - PrettyPrintingUtil.getNodeName(node), - explanation.isEmpty() ? "" : ": " + explanation, - }); + asCtx(data).addViolation(node, formatUnnecessaryModifiers(unnecessaryModifiers), + PrettyPrintingUtil.getPrintableNodeKind(node), + PrettyPrintingUtil.getNodeName(node), + explanation.isEmpty() ? "" : ": " + explanation); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UseDiamondOperatorRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UseDiamondOperatorRule.java index a2ae464eae..d73916d580 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UseDiamondOperatorRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codestyle/UseDiamondOperatorRule.java @@ -85,7 +85,7 @@ public class UseDiamondOperatorRule extends AbstractJavaRulechainRule { JavaNode reportNode = targs == null ? newTypeNode : targs; String message = targs == null ? RAW_TYPE_MESSAGE : REPLACE_TYPE_ARGS_MESSAGE; String replaceWith = produceSuggestedExprImage(ctorCall); - asCtx(data).addViolationWithMessage(reportNode, message, new String[] { replaceWith }); + asCtx(data).addViolationWithMessage(reportNode, message, replaceWith); } return null; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CognitiveComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CognitiveComplexityRule.java index fe5fd9eafe..7a7978f0f5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CognitiveComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CognitiveComplexityRule.java @@ -56,10 +56,10 @@ public class CognitiveComplexityRule extends AbstractJavaRulechainRule { int cognitive = MetricsUtil.computeMetric(COGNITIVE_COMPLEXITY, node); final int reportLevel = getReportLevel(); if (cognitive >= reportLevel) { - asCtx(data).addViolation(node, new String[] { node instanceof ASTMethodDeclaration ? "method" : "constructor", - PrettyPrintingUtil.displaySignature(node), - String.valueOf(cognitive), - String.valueOf(reportLevel) }); + asCtx(data).addViolation(node, node instanceof ASTMethodDeclaration ? "method" : "constructor", + PrettyPrintingUtil.displaySignature(node), + String.valueOf(cognitive), + String.valueOf(reportLevel)); } return data; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java index 349921ac12..52359d8439 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CyclomaticComplexityRule.java @@ -89,7 +89,7 @@ public class CyclomaticComplexityRule extends AbstractJavaRulechainRule { " total", classWmc + " (highest " + classHighest + ")", }; - asCtx(data).addViolation(node, messageParams); + asCtx(data).addViolation(node, (Object[]) messageParams); } } return data; @@ -120,11 +120,7 @@ public class CyclomaticComplexityRule extends AbstractJavaRulechainRule { String kindname = node instanceof ASTConstructorDeclaration ? "constructor" : "method"; - - asCtx(data).addViolation(node, new String[] {kindname, - opname, - "", - "" + cyclo, }); + asCtx(data).addViolation(node, kindname, opname, "", "" + cyclo); } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/DataClassRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/DataClassRule.java index a17517fc66..941cb2c28e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/DataClassRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/DataClassRule.java @@ -53,9 +53,9 @@ public class DataClassRule extends AbstractJavaRulechainRule { int noam = MetricsUtil.computeMetric(NUMBER_OF_ACCESSORS, node); int wmc = MetricsUtil.computeMetric(WEIGHED_METHOD_COUNT, node); - asCtx(data).addViolation(node, new Object[] {node.getSimpleName(), - StringUtil.percentageString(woc, 3), - nopa, noam, wmc, }); + asCtx(data).addViolation(node, node.getSimpleName(), + StringUtil.percentageString(woc, 3), + nopa, noam, wmc); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java index a81090e1e7..e59b688a98 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java @@ -59,9 +59,9 @@ public class GodClassRule extends AbstractJavaRulechainRule { if (wmc >= WMC_VERY_HIGH && atfd > FEW_ATFD_THRESHOLD && tcc < TCC_THRESHOLD) { - asCtx(data).addViolation(node, new Object[] {wmc, - StringUtil.percentageString(tcc, 3), - atfd, }); + asCtx(data).addViolation(node, wmc, + StringUtil.percentageString(tcc, 3), + atfd); } return data; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java index c3907702b9..a2d9840b7e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LawOfDemeterRule.java @@ -132,11 +132,9 @@ public class LawOfDemeterRule extends AbstractJavaRule { asCtx(data).addViolationWithMessage( node, FIELD_ACCESS_ON_FOREIGN_VALUE, - new Object[] { - node.getName(), - PrettyPrintingUtil.prettyPrint(node.getQualifier()), - foreignDegree(node.getQualifier()), - }); + node.getName(), + PrettyPrintingUtil.prettyPrint(node.getQualifier()), + foreignDegree(node.getQualifier())); } return null; } @@ -147,11 +145,9 @@ public class LawOfDemeterRule extends AbstractJavaRule { asCtx(data).addViolationWithMessage( node, METHOD_CALL_ON_FOREIGN_VALUE, - new Object[] { - node.getMethodName(), - PrettyPrintingUtil.prettyPrint(node.getQualifier()), - foreignDegree(node.getQualifier()), - }); + node.getMethodName(), + PrettyPrintingUtil.prettyPrint(node.getQualifier()), + foreignDegree(node.getQualifier())); } return null; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LoosePackageCouplingRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LoosePackageCouplingRule.java index 0d48c33ef4..1e71a21117 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LoosePackageCouplingRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/LoosePackageCouplingRule.java @@ -86,11 +86,11 @@ public class LoosePackageCouplingRule extends AbstractJavaRule { // On demand imports automatically fail because they include // everything if (node.isImportOnDemand()) { - asCtx(data).addViolation(node, new Object[] { node.getImportedName(), pkg }); + asCtx(data).addViolation(node, node.getImportedName(), pkg); break; } else { if (!isAllowedClass(node)) { - asCtx(data).addViolation(node, new Object[] { node.getImportedName(), pkg }); + asCtx(data).addViolation(node, node.getImportedName(), pkg); break; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java index fa1237ad4e..6c1f566dfe 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NPathComplexityRule.java @@ -51,10 +51,10 @@ public class NPathComplexityRule extends AbstractJavaRulechainRule { BigInteger npath = MetricsUtil.computeMetric(JavaMetrics.NPATH, node); if (npath.compareTo(BigInteger.valueOf(reportLevel)) >= 0) { - asCtx(data).addViolation(node, new String[] {node instanceof ASTMethodDeclaration ? "method" : "constructor", - PrettyPrintingUtil.displaySignature(node), - String.valueOf(npath), - String.valueOf(reportLevel)}); + asCtx(data).addViolation(node, node instanceof ASTMethodDeclaration ? "method" : "constructor", + PrettyPrintingUtil.displaySignature(node), + String.valueOf(npath), + String.valueOf(reportLevel)); } return data; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java index fe252338f1..94e134460b 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NcssCountRule.java @@ -101,7 +101,7 @@ public final class NcssCountRule extends AbstractJavaRulechainRule { node.getSimpleName(), classSize + " (Highest = " + classHighest + ")", }; - asCtx(data).addViolation(node, messageParams); + asCtx(data).addViolation(node, (Object[]) messageParams); } } } @@ -115,9 +115,8 @@ public final class NcssCountRule extends AbstractJavaRulechainRule { if (JavaMetrics.NCSS.supports(node)) { int methodSize = MetricsUtil.computeMetric(JavaMetrics.NCSS, node, ncssOptions); if (methodSize >= level) { - asCtx(data).addViolation(node, new String[] { - node instanceof ASTMethodDeclaration ? "method" : "constructor", - PrettyPrintingUtil.displaySignature(node), "" + methodSize, }); + asCtx(data).addViolation(node, node instanceof ASTMethodDeclaration ? "method" : "constructor", + PrettyPrintingUtil.displaySignature(node), "" + methodSize); } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java index ac75cb0f90..c3aa18a459 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java @@ -51,6 +51,7 @@ import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.rule.internal.JavaRuleUtil; import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol; +import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; import net.sourceforge.pmd.lang.java.types.InvocationMatcher; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -175,7 +176,7 @@ public class CloseResourceRule extends AbstractJavaRule { if (isWrappingResourceSpecifiedInTry(resVar)) { reportedVarNames.add(resVar.getName()); asCtx(data).addViolationWithMessage(resVar, WRAPPING_TRY_WITH_RES_VAR_MESSAGE, - new Object[] { resVar.getName() }); + resVar.getName()); } else if (shouldVarOfTypeBeClosedInMethod(resVar, resVarType, methodOrConstructor)) { reportedVarNames.add(resVar.getName()); addCloseResourceViolation(resVar, runtimeType, data); @@ -184,7 +185,7 @@ public class CloseResourceRule extends AbstractJavaRule { if (reassigningStatement != null) { reportedVarNames.add(resVar.getName()); asCtx(data).addViolationWithMessage(reassigningStatement, REASSIGN_BEFORE_CLOSED_MESSAGE, - new Object[] { resVar.getName() }); + resVar.getName()); } } } @@ -287,12 +288,15 @@ public class CloseResourceRule extends AbstractJavaRule { private boolean isWrappingResourceSpecifiedInTry(ASTVariableId var) { ASTVariableAccess wrappedVarName = getWrappedVariableName(var); if (wrappedVarName != null) { - ASTVariableId referencedVar = wrappedVarName.getReferencedSym().tryGetNode(); - if (referencedVar != null) { - List tryContainers = referencedVar.ancestors(ASTTryStatement.class).toList(); - for (ASTTryStatement tryContainer : tryContainers) { - if (isTryWithResourceSpecifyingVariable(tryContainer, referencedVar)) { - return true; + JVariableSymbol referencedSym = wrappedVarName.getReferencedSym(); + if (referencedSym != null) { + ASTVariableId referencedVar = referencedSym.tryGetNode(); + if (referencedVar != null) { + List tryContainers = referencedVar.ancestors(ASTTryStatement.class).toList(); + for (ASTTryStatement tryContainer : tryContainers) { + if (isTryWithResourceSpecifyingVariable(tryContainer, referencedVar)) { + return true; + } } } } @@ -692,7 +696,7 @@ public class CloseResourceRule extends AbstractJavaRule { ASTVariableAccess closedVar = (ASTVariableAccess) node.getQualifier(); if (isNotInFinallyBlock(closedVar) && !reportedVarNames.contains(closedVar.getName())) { asCtx(data).addViolationWithMessage(closedVar, CLOSE_IN_FINALLY_BLOCK_MESSAGE, - new Object[] { closedVar.getName() }); + closedVar.getName()); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ConfusingArgumentToVarargsMethodRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ConfusingArgumentToVarargsMethodRule.java new file mode 100644 index 0000000000..0bd64ef259 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/ConfusingArgumentToVarargsMethodRule.java @@ -0,0 +1,62 @@ +/* + * 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.ASTArgumentList; +import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation; +import net.sourceforge.pmd.lang.java.ast.ASTExpression; +import net.sourceforge.pmd.lang.java.ast.InvocationNode; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule; +import net.sourceforge.pmd.lang.java.types.JArrayType; +import net.sourceforge.pmd.lang.java.types.JTypeMirror; +import net.sourceforge.pmd.lang.java.types.OverloadSelectionResult; +import net.sourceforge.pmd.lang.java.types.TypePrettyPrint; + +public class ConfusingArgumentToVarargsMethodRule extends AbstractJavaRulechainRule { + + public ConfusingArgumentToVarargsMethodRule() { + super(ASTArgumentList.class); + } + + @Override + public Object visit(ASTArgumentList argList, Object data) { + if (argList.isEmpty()) { + return null; + } + + // node is the last param in an arguments list + InvocationNode call = (InvocationNode) argList.getParent(); + OverloadSelectionResult info = call.getOverloadSelectionInfo(); + if (info.isFailed() + || info.isVarargsCall() + || !info.getMethodType().isVarargs()) { + return null; + } + + List formals = info.getMethodType().getFormalParameters(); + JTypeMirror lastFormal = formals.get(formals.size() - 1); + JTypeMirror expectedComponent = ((JArrayType) lastFormal).getComponentType(); + + // since we know this is not a varargs call the last arg has an array type + ASTExpression varargsArg = argList.getLastChild(); + assert varargsArg != null; + if (varargsArg.getTypeMirror().isSubtypeOf(expectedComponent) + && !varargsArg.getTypeMirror().equals(lastFormal)) { + // confusing + + String message; + if (varargsArg instanceof ASTArrayAllocation && ((ASTArrayAllocation) varargsArg).getArrayInitializer() != null) { + message = "Unclear if a varargs or non-varargs call is intended. Cast to {0} or {0}[], or pass varargs parameters separately to clarify intent."; + } else { + message = "Unclear if a varargs or non-varargs call is intended. Cast to {0} or {0}[] to clarify intent."; + } + asCtx(data).addViolationWithMessage(varargsArg, message, TypePrettyPrint.prettyPrintWithSimpleNames(expectedComponent)); + } + + return null; + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/DataflowPass.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/DataflowPass.java index 3ecdf964d4..6624bc5323 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/DataflowPass.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/DataflowPass.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.internal; +import static net.sourceforge.pmd.util.CollectionUtil.asSingle; + import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; @@ -14,12 +16,16 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.function.Supplier; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.pcollections.HashTreePSet; +import org.pcollections.PSet; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.NodeStream; +import net.sourceforge.pmd.lang.java.ast.ASTArrayAllocation; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.AccessType; import net.sourceforge.pmd.lang.java.ast.ASTAssignmentExpression; @@ -346,27 +352,29 @@ public final class DataflowPass { @Override public SpanInfo visit(ASTBlock node, final SpanInfo data) { - // variables local to a loop iteration must be killed before the - // next iteration + return processBreakableStmt(node, data, () -> { + // variables local to a loop iteration must be killed before the + // next iteration - SpanInfo state = data; - Set localsToKill = new LinkedHashSet<>(); + SpanInfo state = data; + List localsToKill = new ArrayList<>(0); - for (JavaNode child : node.children()) { - // each output is passed as input to the next (most relevant for blocks) - state = acceptOpt(child, state); - if (child instanceof ASTLocalVariableDeclaration) { - for (ASTVariableId id : (ASTLocalVariableDeclaration) child) { - localsToKill.add(id); + for (JavaNode child : node.children()) { + // each output is passed as input to the next (most relevant for blocks) + state = acceptOpt(child, state); + if (child instanceof ASTLocalVariableDeclaration) { + for (ASTVariableId id : (ASTLocalVariableDeclaration) child) { + localsToKill.add(id); + } } } - } - for (ASTVariableId var : localsToKill) { - state.deleteVar(var.getSymbol()); - } + for (ASTVariableId var : localsToKill) { + state.deleteVar(var.getSymbol()); + } - return state; + return state; + }); } @Override @@ -383,8 +391,19 @@ public final class DataflowPass { GlobalAlgoState global = data.global; SpanInfo before = acceptOpt(switchLike.getTestedExpression(), data); - global.breakTargets.push(before.fork()); + SpanInfo breakTarget = before.fork(); + global.breakTargets.push(breakTarget); + accLabels(switchLike, global, breakTarget, null); + // If switch non-total then there is a path where the switch completes normally + // (value not matched). + // Todo make that an attribute of ASTSwitchLike, check for totality when pattern matching is involved + boolean isTotal = switchLike.hasDefaultCase() + || switchLike instanceof ASTSwitchExpression + || switchLike.isExhaustiveEnumSwitch(); + + PSet successors = HashTreePSet.empty(); + boolean allBranchesCompleteAbruptly = true; SpanInfo current = before; for (ASTSwitchBranch branch : switchLike.getBranches()) { if (branch instanceof ASTSwitchArrowBranch) { @@ -393,20 +412,42 @@ public final class DataflowPass { } else { // fallthrough branch current = acceptOpt(branch, before.fork().absorb(current)); - branch.getUserMap().set(SWITCH_BRANCH_FALLS_THROUGH, current.hasCompletedAbruptly.complement()); + OptionalBool isFallingThrough = current.hasCompletedAbruptly.complement(); + branch.getUserMap().set(SWITCH_BRANCH_FALLS_THROUGH, isFallingThrough); + successors = CollectionUtil.union(successors, current.abruptCompletionTargets); + allBranchesCompleteAbruptly &= current.hasCompletedAbruptly.isTrue(); + + if (isFallingThrough == OptionalBool.NO) { + current = before.fork(); + } } } before = global.breakTargets.pop(); + PSet<@Nullable SpanInfo> externalTargets = successors.minus(before); + OptionalBool switchCompletesAbruptly; + if (isTotal && allBranchesCompleteAbruptly && externalTargets.equals(successors)) { + // then all branches complete abruptly, and none of them because of a break to this switch + switchCompletesAbruptly = OptionalBool.YES; + } else if (successors.isEmpty() || asSingle(successors) == breakTarget) { // NOPMD CompareObjectsWithEqual this is what we want + // then the branches complete normally, or they just break the switch + switchCompletesAbruptly = OptionalBool.NO; + } else { + switchCompletesAbruptly = OptionalBool.UNKNOWN; + } + // join with the last state, which is the exit point of the // switch, if it's not closed by a break; - return before.absorb(current); + SpanInfo result = before.absorb(current); + result.hasCompletedAbruptly = switchCompletesAbruptly; + result.abruptCompletionTargets = externalTargets; + return result; } @Override public SpanInfo visit(ASTIfStatement node, SpanInfo data) { - return makeConditional(data, node.getCondition(), node.getThenBranch(), node.getElseBranch()); + return processBreakableStmt(node, data, () -> makeConditional(data, node.getCondition(), node.getThenBranch(), node.getElseBranch())); } @Override @@ -510,12 +551,14 @@ public final class DataflowPass { @Override public SpanInfo visit(ASTSynchronizedStatement node, SpanInfo data) { - // visit lock expr and child block - SpanInfo body = super.visit(node, data); - // We should assume that all assignments may be observed by other threads - // at the end of the critical section. - useAllSelfFields(body, JavaAstUtils.isInStaticCtx(node), enclosingClassScope); - return body; + return processBreakableStmt(node, data, () -> { + // visit lock expr and child block + SpanInfo body = super.visit(node, data); + // We should assume that all assignments may be observed by other threads + // at the end of the critical section. + useAllSelfFields(body, JavaAstUtils.isInStaticCtx(node), enclosingClassScope); + return body; + }); } @Override @@ -542,48 +585,61 @@ public final class DataflowPass { */ ASTFinallyClause finallyClause = node.getFinallyClause(); + SpanInfo finalState = processBreakableStmt(node, before, () -> { + + if (finallyClause != null) { + before.myFinally = before.forkEmpty(); + } + + final List catchClauses = node.getCatchClauses().toList(); + final List catchSpans = catchClauses.isEmpty() ? Collections.emptyList() + : new ArrayList<>(); + + // pre-fill catch spans + for (int i = 0; i < catchClauses.size(); i++) { + catchSpans.add(before.forkEmpty()); + } + + @Nullable ASTResourceList resources = node.getResources(); + + SpanInfo bodyState = before.fork(); + bodyState = bodyState.withCatchBlocks(catchSpans); + bodyState = acceptOpt(resources, bodyState); + bodyState = acceptOpt(node.getBody(), bodyState); + bodyState = bodyState.withCatchBlocks(Collections.emptyList()); + + SpanInfo exceptionalState = null; + int i = 0; + for (ASTCatchClause catchClause : node.getCatchClauses()) { + SpanInfo current = acceptOpt(catchClause, catchSpans.get(i)); + exceptionalState = current.absorb(exceptionalState); + i++; + } + return bodyState.absorb(exceptionalState); + }); + if (finallyClause != null) { - before.myFinally = before.forkEmpty(); - } - - final List catchClauses = node.getCatchClauses().toList(); - final List catchSpans = catchClauses.isEmpty() ? Collections.emptyList() - : new ArrayList<>(); - - // pre-fill catch spans - for (int i = 0; i < catchClauses.size(); i++) { - catchSpans.add(before.forkEmpty()); - } - - @Nullable ASTResourceList resources = node.getResources(); - - SpanInfo bodyState = before.fork(); - bodyState = bodyState.withCatchBlocks(catchSpans); - bodyState = acceptOpt(resources, bodyState); - bodyState = acceptOpt(node.getBody(), bodyState); - bodyState = bodyState.withCatchBlocks(Collections.emptyList()); - - SpanInfo exceptionalState = null; - int i = 0; - for (ASTCatchClause catchClause : node.getCatchClauses()) { - SpanInfo current = acceptOpt(catchClause, catchSpans.get(i)); - exceptionalState = current.absorb(exceptionalState); - i++; - } - - SpanInfo finalState; - finalState = bodyState.absorb(exceptionalState); - if (finallyClause != null) { - // this represents the finally clause when it was entered - // because of abrupt completion - // since we don't know when it terminated we must join it with before - SpanInfo abruptFinally = before.myFinally.absorb(before); - acceptOpt(finallyClause, abruptFinally); - before.myFinally = null; - abruptFinally.abruptCompletionByThrow(false); // propagate to enclosing catch/finallies + if (finalState.abruptCompletionTargets.contains(finalState.returnOrThrowTarget)) { + // this represents the finally clause when it was entered + // because of abrupt completion + // since we don't know when it terminated we must join it with before + SpanInfo abruptFinally = before.myFinally.absorb(before); + acceptOpt(finallyClause, abruptFinally); + before.myFinally = null; + abruptFinally.abruptCompletionByThrow(false); // propagate to enclosing catch/finallies + } // this is the normal finally finalState = acceptOpt(finallyClause, finalState); + // then all break targets are successors of the finally + for (SpanInfo target : finalState.abruptCompletionTargets) { + // Then there is a return or throw within the try or catch blocks. + // Control first passes to the finally, then tries to get out of the function + // (stopping on finally). + // before.myFinally = null; + //finalState.abruptCompletionByThrow(false); // propagate to enclosing catch/finallies + target.absorb(finalState); + } } // In the 7.0 grammar, the resources should be explicitly @@ -707,33 +763,73 @@ public final class DataflowPass { } SpanInfo result = popTargets(loop, breakTarget, continueTarget); - result = result.absorb(iter); + result.absorb(iter); if (checkFirstIter) { // if the first iteration is checked, // then it could be false on the first try, meaning // the definitions before the loop reach after too - result = result.absorb(before); + result.absorb(before); } if (foreachVar != null) { result.deleteVar(foreachVar.getSymbol()); } + // These targets are now obsolete + result.abruptCompletionTargets = + result.abruptCompletionTargets.minus(breakTarget).minus(continueTarget); return result; } + /** + * Process a statement that may be broken out of if it is annotated with a label. + * This is theoretically all statements, as all of them may be annotated. However, + * some statements may not contain a break. Eg if a return statement has a label, + * the label can never be used. The weirdest example is probably an annotated break + * statement, which may break out of itself. + * + *

Try statements are handled specially because of the finally. + */ + private SpanInfo processBreakableStmt(ASTStatement statement, SpanInfo input, Supplier processFun) { + if (!(statement.getParent() instanceof ASTLabeledStatement)) { + // happy path, no labels + return processFun.get(); + } + GlobalAlgoState globalState = input.global; + // this will be filled with the reaching defs of the break statements, then merged with the actual exit state + SpanInfo placeholderForExitState = input.forkEmpty(); + + PSet labels = accLabels(statement, globalState, placeholderForExitState, null); + SpanInfo endState = processFun.get(); + + // remove the labels + globalState.breakTargets.namedTargets.keySet().removeAll(labels); + SpanInfo result = endState.absorb(placeholderForExitState); + result.abruptCompletionTargets = result.abruptCompletionTargets.minus(placeholderForExitState); + return result; + } + + private static PSet accLabels(JavaNode statement, GlobalAlgoState globalState, SpanInfo breakTarget, @Nullable SpanInfo continueTarget) { + Node parent = statement.getParent(); + PSet labels = HashTreePSet.empty(); + // collect labels and give a name to the exit state. + while (parent instanceof ASTLabeledStatement) { + String label = ((ASTLabeledStatement) parent).getLabel(); + labels = labels.plus(label); + globalState.breakTargets.namedTargets.put(label, breakTarget); + if (continueTarget != null) { + globalState.continueTargets.namedTargets.put(label, continueTarget); + } + parent = parent.getParent(); + } + return labels; + } + private void pushTargets(ASTLoopStatement loop, SpanInfo breakTarget, SpanInfo continueTarget) { GlobalAlgoState globalState = breakTarget.global; + accLabels(loop, globalState, breakTarget, continueTarget); globalState.breakTargets.unnamedTargets.push(breakTarget); globalState.continueTargets.unnamedTargets.push(continueTarget); - - Node parent = loop.getParent(); - while (parent instanceof ASTLabeledStatement) { - String label = ((ASTLabeledStatement) parent).getLabel(); - globalState.breakTargets.namedTargets.put(label, breakTarget); - globalState.continueTargets.namedTargets.put(label, continueTarget); - parent = parent.getParent(); - } } private SpanInfo popTargets(ASTLoopStatement loop, SpanInfo breakTarget, SpanInfo continueTarget) { @@ -764,7 +860,7 @@ public final class DataflowPass { @Override public SpanInfo visit(ASTBreakStatement node, SpanInfo data) { - return data.global.breakTargets.doBreak(data, node.getImage()); + return processBreakableStmt(node, data, () -> data.global.breakTargets.doBreak(data, node.getImage())); } @Override @@ -787,7 +883,7 @@ public final class DataflowPass { @Override public SpanInfo visit(ASTReturnStatement node, SpanInfo data) { super.visit(node, data); - return data.abruptCompletion(null); + return data.abruptCompletion(data.returnOrThrowTarget); } // following deals with assignment @@ -952,6 +1048,16 @@ public final class DataflowPass { return state; } + @Override + public SpanInfo visit(ASTArrayAllocation node, SpanInfo state) { + state = acceptOpt(node.getArrayInitializer(), state); + state = acceptOpt(node.getTypeNode().getDimensions(), state); + // May throw OOM error for instance. This abrupt completion routine is + // noop if we are outside a try block. + state.abruptCompletionByThrow(true); + return state; + } + private SpanInfo visitInvocationExpr(T node, SpanInfo state) { state = acceptOpt(node.getQualifier(), state); state = acceptOpt(node.getArguments(), state); @@ -1162,16 +1268,46 @@ public final class DataflowPass { final GlobalAlgoState global; final Map symtable; + + /** + * Whether the current span completed abruptly. Abrupt + * completion occurs with break, continue, return or throw + * statements. A loop whose body completes abruptly may or + * may not complete abruptly itself. For instance in + *

{@code
+         * for (int i = 0; i < 5; i++) {
+         *     break;
+         * }
+         * }
+ * the loop body completes abruptly on all paths, but the loop + * itself completes normally. This is also the case in a switch + * statement where all cases are followed by a break. + */ private OptionalBool hasCompletedAbruptly = OptionalBool.NO; + /** + * Collects the abrupt completion targets of the current span. + * The value {@link #returnOrThrowTarget} + * represents a return statement or a throw that + * is not followed by an enclosing finally block. + */ + private PSet abruptCompletionTargets = HashTreePSet.empty(); + + /** + * Sentinel to represent the target of a throw or return statement. + */ + private final SpanInfo returnOrThrowTarget; + + private SpanInfo(GlobalAlgoState global) { this(null, global, new LinkedHashMap<>()); } - private SpanInfo(SpanInfo parent, + private SpanInfo(@Nullable SpanInfo parent, GlobalAlgoState global, Map symtable) { this.parent = parent; + this.returnOrThrowTarget = parent == null ? this : parent.returnOrThrowTarget; this.global = global; this.symtable = symtable; this.myCatches = Collections.emptyList(); @@ -1340,20 +1476,26 @@ public final class DataflowPass { } /** Abrupt completion for return, continue, break. */ - SpanInfo abruptCompletion(SpanInfo target) { - // if target == null then this will unwind all the parents + SpanInfo abruptCompletion(@NonNull SpanInfo target) { hasCompletedAbruptly = OptionalBool.YES; + abruptCompletionTargets = abruptCompletionTargets.plus(target); + SpanInfo parent = this; - while (parent != target && parent != null) { // NOPMD CompareObjectsWithEqual this is what we want + while (parent != null) { if (parent.myFinally != null) { parent.myFinally.absorb(this); // stop on the first finally, its own end state will // be merged into the nearest enclosing finally - return this; + break; + } + if (parent == target) { // NOPMD CompareObjectsWithEqual this is what we want + break; } parent = parent.parent; + } + // rest of this block is dead code so we don't track declarations this.symtable.clear(); return this; } @@ -1377,6 +1519,7 @@ public final class DataflowPass { if (!byMethodCall) { hasCompletedAbruptly = OptionalBool.YES; } + abruptCompletionTargets = abruptCompletionTargets.plus(returnOrThrowTarget); SpanInfo parent = this; while (parent != null) { @@ -1396,6 +1539,7 @@ public final class DataflowPass { parent = parent.parent; } + if (!byMethodCall) { this.symtable.clear(); // following is dead code } @@ -1420,10 +1564,11 @@ public final class DataflowPass { CollectionUtil.mergeMaps(this.symtable, other.symtable, VarLocalInfo::merge); this.hasCompletedAbruptly = mergeCertitude(this.hasCompletedAbruptly, other.hasCompletedAbruptly); + this.abruptCompletionTargets = CollectionUtil.union(this.abruptCompletionTargets, other.abruptCompletionTargets); return this; } - private OptionalBool mergeCertitude(OptionalBool first, OptionalBool other) { + static OptionalBool mergeCertitude(OptionalBool first, OptionalBool other) { if (first.isKnown() && other.isKnown()) { return first == other ? first : OptionalBool.UNKNOWN; } @@ -1467,8 +1612,9 @@ public final class DataflowPass { if (target != null) { // otherwise CT error target.absorb(data); + return data.abruptCompletion(target); } - return data.abruptCompletion(target); + return data; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java index 8f100a88af..367c2e7be0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/ConsecutiveLiteralAppendsRule.java @@ -258,8 +258,7 @@ public class ConsecutiveLiteralAppendsRule extends AbstractJavaRulechainRule { private void checkForViolation(Object data) { if (counter.isViolation()) { assert counter.getReportNode() != null; - String[] param = { String.valueOf(counter.getCounter()) }; - asCtx(data).addViolation(counter.getReportNode(), param); + asCtx(data).addViolation(counter.getReportNode(), String.valueOf(counter.getCounter())); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java index 7f1905577f..a6fabf91a2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java @@ -72,7 +72,7 @@ public class InsufficientStringBufferDeclarationRule extends AbstractJavaRulecha } - public String[] getParamsForViolation() { + public Object[] getParamsForViolation() { return new String[] { getTypeName(variable), String.valueOf(capacity), String.valueOf(anticipatedLength) }; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ast/LambdaMirrorImpl.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ast/LambdaMirrorImpl.java index 69f6fa1da2..d354acb4e4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ast/LambdaMirrorImpl.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ast/LambdaMirrorImpl.java @@ -91,9 +91,9 @@ class LambdaMirrorImpl extends BaseFunctionalMirror impleme @Override public List getResultExpressions() { - ASTBlock block = myNode.getBlock(); + ASTBlock block = myNode.getBlockBody(); if (block == null) { - return Collections.singletonList(createSubexpression(myNode.getExpression())); + return Collections.singletonList(createSubexpression(myNode.getExpressionBody())); } else { return block.descendants(ASTReturnStatement.class) .map(ASTReturnStatement::getExpr) @@ -111,15 +111,15 @@ class LambdaMirrorImpl extends BaseFunctionalMirror impleme @Override public boolean isValueCompatible() { - ASTBlock block = myNode.getBlock(); + ASTBlock block = myNode.getBlockBody(); return block == null || isLambdaBodyCompatible(block, false); } @Override public boolean isVoidCompatible() { - ASTBlock block = myNode.getBlock(); + ASTBlock block = myNode.getBlockBody(); if (block == null) { - return isExpressionStatement(myNode.getExpression()); + return isExpressionStatement(myNode.getExpressionBody()); } else { return isLambdaBodyCompatible(block, true); } diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 19beaf3d79..881f6b4995 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -1438,7 +1438,7 @@ class Foo{ @@ -1451,30 +1451,6 @@ class Foo{ ```java Arrays.asList("foo", "bar"); ``` - - This rule also reports such array creations when they are confusing, because the array is a subtype of the component type of the expected array type. - For instance if you have - ```java - void varargs(Object... parm); - ``` - and call it like so - ```java - varargs(new String[]{"a"}); - ``` - it is not clear whether you intended the method to receive the value `new Object[]{ new String[] {"a"} }` or just `new String[] {"a"}` (the latter happens). This confusion occurs because `String[]` is both a subtype of `Object[]` and of `Object`. To clarify your intent in this case, use a cast or pass individual elements like so: - ```java - // varargs call - // parm will be `new Object[] { "a" }` - varargs("a"); - - // non-varargs call - // parm will be `new String[] { "a" }` - varargs((Object[]) new String[]{"a"}); - - // varargs call - // parm will be `new Object[] { new String[] { "a" } }` - varargs((Object) new String[]{"a"}); - ``` 3 + + + + This rule reports lambda expressions that can be written more succinctly as a method reference. This is the case if the lambda is an expression lambda that only calls one method, passing the entire lambda parameter list in order to the method. For instance: + ```java + x -> Foo.call(x) // can be Foo::call + x -> call(x) // can be this::call, if call is an instance method + (x, y, z) -> call(x, y, z) // can be this::call + () -> foo.get() // can be foo::get + x -> x.foo() // can be XType::foo (where XType is the type of x) + ``` + + In some cases rewriting a lambda to a method reference can change the semantics of the code. For instance in `(x) -> someVar.call(x)`, the invocation of the lambda may produce a NullPointerException (NPE) if `someVar` is null. The method reference `someVar::call` will also NPE if `someVar` is null, but it will do so at the point the method reference is created, while the lambda is created without error and its NPE is only thrown if the lambda is invoked (which may be never). Code should probably not rely on this subtle semantic difference, therefore these potentially problematic lambdas are also reported by default. This behavior can be disabled by setting the property `ignoreIfMayNPE` to `true`. + + The property `ignoreIfMayNPE` is true by default. By default, calls whose receiver is itself a method call are ignored, because they could cause side effects. This may be changed by setting the property `ignoreIfReceiverIsMethod` to `false`. + + Scope limitations: + - This rule will not report lambdas of the form `x -> new CtorCall().something(x)`, because the semantics of the method reference would be to create a single new object, while the lambda creates one object per invocation. + - The rule cannot know if the qualifier of a method call performs side effects. This means `(x) -> sideEffectingMethod().foo(x)` will be reported. Suppress the warning in this case. + + 3 + + s.length()) // could be String::length + .reduce((x, y) -> Integer.sum(x, y)) // could be Integer::sum + .getAsInt(); + } + } + ]]> + + + + + + Reports a confusing argument passed to a varargs method. + + This can occur when an array is passed as a single varargs argument, when the array type is not exactly the + type of array that the varargs method expects. If, that array is a subtype of the component type of the expected + array type, then it might not be clear what value the called varargs method will receive. + For instance if you have: + ```java + void varargs(Object... parm); + ``` + and call it like so: + ```java + varargs(new String[]{"a"}); + ``` + it is not clear whether you intended the method to receive the value `new Object[]{ new String[] {"a"} }` or + just `new String[] {"a"}` (the latter happens). This confusion occurs because `String[]` is both a subtype + of `Object[]` and of `Object`. To clarify your intent in this case, use a cast or pass individual elements like so: + ```java + // varargs call + // parm will be `new Object[] { "a" }` + varargs("a"); + + // non-varargs call + // parm will be `new String[] { "a" }` + varargs((Object[]) new String[]{"a"}); + + // varargs call + // parm will be `new Object[] { new String[] { "a" } }` + varargs((Object) new String[]{"a"}); + ``` + + Another confusing case is when you pass `null` as the varargs argument. Here it is not clear whether you intended + to pass an array with a single null element, or a null array (the latter happens). This can similarly be clarified + with a cast. + + 3 + + + @@ -62,6 +63,7 @@ + @@ -209,6 +211,7 @@ + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/LambdaCanBeMethodReferenceTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/LambdaCanBeMethodReferenceTest.java new file mode 100644 index 0000000000..8fd614d560 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/codestyle/LambdaCanBeMethodReferenceTest.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.codestyle; + +import net.sourceforge.pmd.test.PmdRuleTst; + +class LambdaCanBeMethodReferenceTest extends PmdRuleTst { + // no additional unit tests +} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/ConfusingArgumentToVarargsMethodTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/ConfusingArgumentToVarargsMethodTest.java new file mode 100644 index 0000000000..876c564600 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/ConfusingArgumentToVarargsMethodTest.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule.errorprone; + +import net.sourceforge.pmd.test.PmdRuleTst; + +class ConfusingArgumentToVarargsMethodTest extends PmdRuleTst { + // no additional unit tests +} diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TestExtensions.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TestExtensions.kt index bb3fed6787..89b76f3f48 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TestExtensions.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TestExtensions.kt @@ -13,12 +13,12 @@ import io.kotest.matchers.shouldNotBe import io.kotest.matchers.types.shouldBeInstanceOf import net.sourceforge.pmd.lang.ast.Node import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken -import net.sourceforge.pmd.lang.test.ast.NodeSpec -import net.sourceforge.pmd.lang.test.ast.ValuedNodeSpec -import net.sourceforge.pmd.lang.test.ast.shouldBe import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind.* +import net.sourceforge.pmd.lang.test.ast.NodeSpec +import net.sourceforge.pmd.lang.test.ast.ValuedNodeSpec +import net.sourceforge.pmd.lang.test.ast.shouldBe fun > C?.shouldContainAtMostOneOf(vararg expected: T) { this shouldNotBe null diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceTest.kt index 137ffe49ac..850cfba564 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceTest.kt @@ -137,7 +137,7 @@ class TypeInferenceTest : ProcessorTestSpec({ variableId("it") } } - it::getExpression shouldBe child { + it::getExpressionBody shouldBe child { it shouldHaveType it.typeSystem.BOOLEAN it::getQualifier shouldBe variableAccess("it") { it shouldHaveType it.typeSystem.STRING diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/PrimitiveWrapperInstantiation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/PrimitiveWrapperInstantiation.xml index cc56bcfbb2..29691b14b0 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/PrimitiveWrapperInstantiation.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/PrimitiveWrapperInstantiation.xml @@ -414,6 +414,18 @@ public class SomeClass { this.bar = new Boolean("some arbitrary string is just false"); //violation this.bar = Boolean.valueOf(s); //use this instead of Boolean#new } +} + ]]> + + + + [java] Instantiation rules cannot tell apart java.lang primitive wrappers and shadowed classes #1548 + 0 + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnnecessaryVarargsArrayCreation.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnnecessaryVarargsArrayCreation.xml index 7bfe784785..90231037ce 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnnecessaryVarargsArrayCreation.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnnecessaryVarargsArrayCreation.xml @@ -38,10 +38,9 @@ Confusing argument - 2 + 1 - Unnecessary explicit varargs array creation - Unclear if a varargs or non-varargs call is intended. Cast to Object or Object[], or pass varargs parameters separately to clarify intent. + Unnecessary explicit array creation for varargs method call Catch in loop (reportUnusedVariables) true 6 + 9,11,18,19,25,34 + + Custom label causes NPE + 1 + 7 + + + + Try with nested finally + 0 + + + + + + Labeled statements (1) + 2 + 8,13 + + + + Labeled break statement (2) + 0 + + + + Labeled synchronized statement (3) + 0 + + + + + Labeled block + 0 + + + + Unused formal value @@ -3750,6 +3895,36 @@ record TestRecord(int foo) { this.foo = foo; // explicit } } +]]> + + + Label on switch + 0 + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml index 3a91d558ef..eb072c2dbc 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml @@ -1901,6 +1901,67 @@ public class NotUsedPrivateMethodFalsePositive { return clientIdsToDps.getUnchecked(""); } } +]]> + + + + [java] UnusedPrivateMethod false positive when using @MethodSource on a @Nested test #4975 + 0 + strings) { + // insert code + } + + private static Stream getStrings() { + Stream tests = Stream.of( + Arguments.of(List.of("TEST", "TEST_1")), + Arguments.of(List.of("TEST_2", "TEST_3")) + ); + + return Stream.of(tests) + .reduce(Stream::concat) + .orElseGet(Stream::empty); + } + } +} +]]> + + + + [java] UnusedPrivateMethod FP with Junit 5 @MethodSource and default factory method name #4278 + 0 + testGetUsername_noMethodSourceValue() { + return Stream.of( + Arguments.of("foo"), + Arguments.of("bar"), + Arguments.of("baz") + ); + } + + @MethodSource + @ParameterizedTest + void testGetUsername_noMethodSourceValue(String username) { + User sut = new User(username); + + Assertions.assertEquals(username, sut.getUsername()); + } +} ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LambdaCanBeMethodReference.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LambdaCanBeMethodReference.xml new file mode 100644 index 0000000000..48f0f2d328 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/LambdaCanBeMethodReference.xml @@ -0,0 +1,340 @@ + + + + Static referee, return type adapted int to void + 1 + 5 + + Lambda expression could be written as a method reference: `Foo::correct` + + correct(x)); // flag + int foo = 0; + iTakeLambda(x -> correct(foo)); // ok + } + public static int correct(int a) { + return 0; + } + } + + interface ALambda { + void doSomething(int a); + } + ]]> + + + self referee, return type adapted int to void + 1 + 5 + + Lambda expression could be written as a method reference: `this::correct` + + correct(x)); // flag + int foo = 0; + iTakeLambda(x -> correct(foo)); // ok + } + public int correct(int a) { + return 0; + } + } + + interface ALambda { + void doSomething(int a); + } + ]]> + + + Block lambda + 1 + 5 + + Lambda expression could be written as a method reference: `this::correct` + + { return correct(x); }); // flag + iTakeLambda(x ->{ if(x == 1) return correct(x); else return correct(x); }); // do not flag + iTakeLambda(x ->{ + foo(); + return correct(x); + }); // do not flag + iTakeLambda(x -> {}); + } + public int correct(int a) { + return 0; + } + } + + interface ALambda { + void doSomething(int a); + } + ]]> + + + cannot rewrite if qualifier is ctor call + 0 + new Foo().correct(x)); + } + public int correct(int a) { + return 0; + } + } + + interface ALambda { + void doSomething(int a); + } + ]]> + + + + foo().correct(x)); + } + public int correct(int a) { + return 0; + } + static Foo foo() { return new Foo(); } + } + + interface ALambda { + void doSomething(int a); + } + ]]> + + + + Ignore methods by default + 0 + + + + Property to consider methods + false + 1 + + Lambda expression could be written as a method reference: `foo()::correct` + + + + + + + can rewrite many different qualifier types without NPE risk + true + 4 + + Lambda expression could be written as a method reference: `"abc"::indexOf` + Lambda expression could be written as a method reference: `this::correct` + Lambda expression could be written as a method reference: `Integer::valueOf` + Lambda expression could be written as a method reference: `String.class::isAssignableFrom` + + > l) {} + static { + iTakeLambda(x -> "abc".indexOf(x)); + iTakeLambda(x -> this.correct(x)); + iTakeLambda(x -> Integer.valueOf(x)); + iTakeClass(x -> String.class.isAssignableFrom(x)); + } + public boolean correct(int a) { + return false; + } + } + + interface ALambda { + boolean doSomething(int a); + } + ]]> + + + Test annotated lambda + 0 + Integer.valueOf(x)); + } + + public boolean correct(int a) { + return false; + } + } + + @Target(ElementType.TYPE_USE) + @interface Annot { + } + + interface ALambda { + boolean doSomething(int a); + } + ]]> + + + test when method call is invalid + 0 + Integer.parseInt(x)); + } + public boolean correct(int a) { + return false; + } + } + + interface ALambda { + boolean doSomething(int a); + } + ]]> + + + + Test when method ref is on receiver + 2 + + Lambda expression could be written as a method reference: `String::isEmpty` + Lambda expression could be written as a method reference: `String::contains` + + x.isEmpty()); + iTakeLambda((x,c) -> x.contains(c)); + } + public boolean correct(int a) { + return false; + } + } + + interface ALambda { + boolean doSomething(String a, CharSequence c); + } + interface ALambda2 { + boolean doSomething(String a); + } + ]]> + + + + foo().bar(x)); + iTakeLambda(x -> ((Foo) foo()).bar(x)); + iTakeLambda(x -> fooField.bar(x)); + // this also may not NPE because it will be converted to String::contains + iTakeLambda((x,c) -> x.contains(c)); + } + public boolean correct(int a) { + return false; + } + static Foo foo() { return new Foo(); } + boolean bar(String x) { return true; } + static Foo fooField; + } + + interface ALambda { + boolean doSomething(String a, CharSequence c); + } + interface ALambda2 { + boolean doSomething(String a); + } + ]]> + + + + + Risk of NPE, ignore = true + true + true + 1 + + Lambda expression could be written as a method reference: `String::contains` + + + + + + Risk of NPE, ignore = false + false + true + 2 + + Lambda expression could be written as a method reference: `fooField::bar` + Lambda expression could be written as a method reference: `String::contains` + + + + + Risk of NPE, ignore = true, ignore method = false + true + false + 1 + + Lambda expression could be written as a method reference: `String::contains` + + + + + + Risk of NPE, ignore npe = false, dont ignore methods + false + false + 4 + + Lambda expression could be written as a method reference: `foo()::bar` + Lambda expression could be written as a method reference: `((Foo) foo())::bar` + Lambda expression could be written as a method reference: `fooField::bar` + Lambda expression could be written as a method reference: `String::contains` + + + + + + + + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ConfusingArgumentToVarargsMethod.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ConfusingArgumentToVarargsMethod.xml new file mode 100644 index 0000000000..81d3545ff1 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ConfusingArgumentToVarargsMethod.xml @@ -0,0 +1,109 @@ + + + + + Unnecessary in asList + 0 + + + + + Necessary array creation + 0 + + + + + + Confusing argument + 1 + + Unclear if a varargs or non-varargs call is intended. Cast to Object or Object[], or pass varargs parameters separately to clarify intent. + + + + + Confusing null argument + 1 + + Unclear if a varargs or non-varargs call is intended. Cast to Object or Object[] to clarify intent. + + + + + Confusing argument, not an array allocation + 1 + + Unclear if a varargs or non-varargs call is intended. Cast to Object or Object[] to clarify intent. + + + + + + + Array creation without elements + 0 + + + + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ImplicitSwitchFallThrough.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ImplicitSwitchFallThrough.xml index ce77c57423..6d86131b0d 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ImplicitSwitchFallThrough.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/ImplicitSwitchFallThrough.xml @@ -422,4 +422,163 @@ record MyRecord(boolean b) { ]]> + + #4948 FP with nested switch stmt + 0 + + + + Switch with loop with break + 3 + 11,14,18 + + + + Switch with loop with break + 1 + 6 + + + + Switch with break to enclosing block + 0 + + + + Switch expr + 0 + 0) { + if (k == 5) { + k--; + continue; + } + break LOP; + } + Supplier getter = () -> { return "2-X-5"; }; + yield getter.get(); + default: + yield "X"; + }; + } +} + ]]> + diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml index e4a8f98a27..72383cc5f4 100644 --- a/pmd-javascript/pom.xml +++ b/pmd-javascript/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-jsp/pom.xml b/pmd-jsp/pom.xml index 61be68c532..eec8282f65 100644 --- a/pmd-jsp/pom.xml +++ b/pmd-jsp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-julia/pom.xml b/pmd-julia/pom.xml index a42e18aaec..6ec7333e73 100644 --- a/pmd-julia/pom.xml +++ b/pmd-julia/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-kotlin/pom.xml b/pmd-kotlin/pom.xml index 5ea491683a..d27eaa6d4f 100644 --- a/pmd-kotlin/pom.xml +++ b/pmd-kotlin/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index 0fd858305c..f4a8683885 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -12,7 +12,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-languages-deps/pom.xml b/pmd-languages-deps/pom.xml index e6f339c8a2..1a85089052 100644 --- a/pmd-languages-deps/pom.xml +++ b/pmd-languages-deps/pom.xml @@ -4,7 +4,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT pmd-languages-deps diff --git a/pmd-lua/pom.xml b/pmd-lua/pom.xml index 24f21403f9..90ee0372cc 100644 --- a/pmd-lua/pom.xml +++ b/pmd-lua/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-matlab/pom.xml b/pmd-matlab/pom.xml index 54166a1612..7c4720f2e0 100644 --- a/pmd-matlab/pom.xml +++ b/pmd-matlab/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-modelica/pom.xml b/pmd-modelica/pom.xml index 58a4e48e2b..f58bc85456 100644 --- a/pmd-modelica/pom.xml +++ b/pmd-modelica/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-objectivec/pom.xml b/pmd-objectivec/pom.xml index cb82109d28..2604418fa1 100644 --- a/pmd-objectivec/pom.xml +++ b/pmd-objectivec/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-perl/pom.xml b/pmd-perl/pom.xml index 8abc31b698..87f9b71de0 100644 --- a/pmd-perl/pom.xml +++ b/pmd-perl/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-php/pom.xml b/pmd-php/pom.xml index a446f353cb..2a0024663e 100644 --- a/pmd-php/pom.xml +++ b/pmd-php/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-plsql/pom.xml b/pmd-plsql/pom.xml index ff0b7c7f6c..a5d78eb138 100644 --- a/pmd-plsql/pom.xml +++ b/pmd-plsql/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java index ca79a806a2..c35c9b1752 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/design/CyclomaticComplexityRule.java @@ -210,8 +210,8 @@ public class CyclomaticComplexityRule extends AbstractPLSQLRule { classEntry.getComplexityAverage(), classEntry.highestDecisionPoints); if (showClassesComplexity) { if (classEntry.getComplexityAverage() >= reportLevel || classEntry.highestDecisionPoints >= reportLevel) { - asCtx(data).addViolation(node, new String[] { "class", node.getImage(), - classEntry.getComplexityAverage() + " (Highest = " + classEntry.highestDecisionPoints + ')', }); + asCtx(data).addViolation(node, "class", node.getImage(), + classEntry.getComplexityAverage() + " (Highest = " + classEntry.highestDecisionPoints + ')'); } } return data; @@ -227,8 +227,8 @@ public class CyclomaticComplexityRule extends AbstractPLSQLRule { classEntry.highestDecisionPoints); if (showClassesComplexity) { if (classEntry.getComplexityAverage() >= reportLevel || classEntry.highestDecisionPoints >= reportLevel) { - asCtx(data).addViolation(node, new String[] { "class", node.getImage(), - classEntry.getComplexityAverage() + " (Highest = " + classEntry.highestDecisionPoints + ')', }); + asCtx(data).addViolation(node, "class", node.getImage(), + classEntry.getComplexityAverage() + " (Highest = " + classEntry.highestDecisionPoints + ')'); } } return data; @@ -276,8 +276,8 @@ public class CyclomaticComplexityRule extends AbstractPLSQLRule { ASTMethodDeclarator methodDeclarator = node.firstChild(ASTMethodDeclarator.class); if (methodEntry.decisionPoints >= reportLevel) { asCtx(data).addViolation(node, - new String[] { "method", methodDeclarator == null ? "" : methodDeclarator.getImage(), - String.valueOf(methodEntry.decisionPoints), }); + "method", methodDeclarator == null ? "" : methodDeclarator.getImage(), + String.valueOf(methodEntry.decisionPoints)); } } return data; @@ -306,8 +306,8 @@ public class CyclomaticComplexityRule extends AbstractPLSQLRule { ASTMethodDeclarator methodDeclarator = node.firstChild(ASTMethodDeclarator.class); if (methodEntry.decisionPoints >= reportLevel) { asCtx(data).addViolation(node, - new String[] { "method", methodDeclarator == null ? "" : methodDeclarator.getImage(), - String.valueOf(methodEntry.decisionPoints), }); + "method", methodDeclarator == null ? "" : methodDeclarator.getImage(), + String.valueOf(methodEntry.decisionPoints)); } } return data; @@ -334,8 +334,8 @@ public class CyclomaticComplexityRule extends AbstractPLSQLRule { ASTMethodDeclarator methodDeclarator = node.firstChild(ASTMethodDeclarator.class); if (methodEntry.decisionPoints >= reportLevel) { asCtx(data).addViolation(node, - new String[] { "method", methodDeclarator == null ? "" : methodDeclarator.getImage(), - String.valueOf(methodEntry.decisionPoints), }); + "method", methodDeclarator == null ? "" : methodDeclarator.getImage(), + String.valueOf(methodEntry.decisionPoints)); } } return data; diff --git a/pmd-python/pom.xml b/pmd-python/pom.xml index 2c0a8595f0..544653426a 100644 --- a/pmd-python/pom.xml +++ b/pmd-python/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-ruby/pom.xml b/pmd-ruby/pom.xml index b5eddc00c3..b3f4438adb 100644 --- a/pmd-ruby/pom.xml +++ b/pmd-ruby/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-scala-modules/pmd-scala-common/pom.xml b/pmd-scala-modules/pmd-scala-common/pom.xml index 13a68664ba..53c5eb2fc4 100644 --- a/pmd-scala-modules/pmd-scala-common/pom.xml +++ b/pmd-scala-modules/pmd-scala-common/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../../pom.xml diff --git a/pmd-scala-modules/pmd-scala_2.12/pom.xml b/pmd-scala-modules/pmd-scala_2.12/pom.xml index f49d0deb67..baaab7828f 100644 --- a/pmd-scala-modules/pmd-scala_2.12/pom.xml +++ b/pmd-scala-modules/pmd-scala_2.12/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd-scala-common - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pmd-scala-common/pom.xml diff --git a/pmd-scala-modules/pmd-scala_2.13/pom.xml b/pmd-scala-modules/pmd-scala_2.13/pom.xml index 46cc4a81ba..4de45c6687 100644 --- a/pmd-scala-modules/pmd-scala_2.13/pom.xml +++ b/pmd-scala-modules/pmd-scala_2.13/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd-scala-common - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pmd-scala-common/pom.xml diff --git a/pmd-swift/pom.xml b/pmd-swift/pom.xml index 16e72f0362..266dba8c63 100644 --- a/pmd-swift/pom.xml +++ b/pmd-swift/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-test-schema/pom.xml b/pmd-test-schema/pom.xml index 4ab3094ccb..0e823d7615 100644 --- a/pmd-test-schema/pom.xml +++ b/pmd-test-schema/pom.xml @@ -11,7 +11,7 @@ pmd net.sourceforge.pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml index 3fe5075ae9..9ffded1716 100644 --- a/pmd-test/pom.xml +++ b/pmd-test/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-tsql/pom.xml b/pmd-tsql/pom.xml index 9c760a2e5a..9be8d9d168 100644 --- a/pmd-tsql/pom.xml +++ b/pmd-tsql/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-velocity/pom.xml b/pmd-velocity/pom.xml index b3d4141a6e..06340fa7b1 100644 --- a/pmd-velocity/pom.xml +++ b/pmd-velocity/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-visualforce/pom.xml b/pmd-visualforce/pom.xml index d361264c2d..735f07a958 100644 --- a/pmd-visualforce/pom.xml +++ b/pmd-visualforce/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml index 3b48f67441..183347631e 100644 --- a/pmd-xml/pom.xml +++ b/pmd-xml/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 53eca0e59a..11d7bef738 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 net.sourceforge.pmd pmd - 7.1.0-SNAPSHOT + 7.2.0-SNAPSHOT pom PMD @@ -81,7 +81,7 @@ - 2024-03-22T07:17:27Z + 2024-04-26T06:14:52Z 8 @@ -99,7 +99,7 @@ 3.2.5 10.14.0 3.3.1 - 3.21.2 + 3.22.0 1.10.14 3.6.3 4.9.3 @@ -113,7 +113,7 @@ -Xmx512m -Dfile.encoding=${project.build.sourceEncoding} ${extraArgLine} - 24-SNAPSHOT + 24 7.0.0 ${settings.localRepository}/net/java/dev/javacc/javacc/${javacc.version}/javacc-${javacc.version}.jar @@ -159,6 +159,12 @@ javacc ${javacc.version} + + + org.apache.ant + ant + ${ant.version} + @@ -361,7 +367,7 @@ org.apache.maven.plugins maven-source-plugin - 3.3.0 + 3.3.1 org.apache.maven.plugins @@ -537,30 +543,25 @@ - - net.sourceforge.pmd - pmd-compat6 - 7.0.0 - net.sourceforge.pmd pmd-core - 7.0.0 + 7.1.0 net.sourceforge.pmd pmd-java - 7.0.0 + 7.1.0 net.sourceforge.pmd pmd-jsp - 7.0.0 + 7.1.0 net.sourceforge.pmd pmd-javascript - 7.0.0 + 7.1.0 @@ -750,6 +751,18 @@ makeAggregateBom + + + + pmd-cli + pmd-dist + +