Merge branch 'master' into pr-5125

This commit is contained in:
Andreas Dangel 2024-08-29 10:10:35 +02:00
commit 60a29f08a5
No known key found for this signature in database
GPG Key ID: 93450DF2DF9A3FA3
95 changed files with 1165 additions and 473 deletions

View File

@ -7699,6 +7699,42 @@
"contributions": [
"bug"
]
},
{
"login": "rbri",
"name": "RBRi",
"avatar_url": "https://avatars.githubusercontent.com/u/2544132?v=4",
"profile": "https://github.com/rbri",
"contributions": [
"bug"
]
},
{
"login": "jbisotti",
"name": "Jamie Bisotti",
"avatar_url": "https://avatars.githubusercontent.com/u/899712?v=4",
"profile": "https://github.com/jbisotti",
"contributions": [
"bug"
]
},
{
"login": "soloturn",
"name": "soloturn",
"avatar_url": "https://avatars.githubusercontent.com/u/825568?v=4",
"profile": "https://github.com/soloturn",
"contributions": [
"bug"
]
},
{
"login": "schosin",
"name": "schosin",
"avatar_url": "https://avatars.githubusercontent.com/u/1669777?v=4",
"profile": "https://github.com/schosin",
"contributions": [
"bug"
]
}
],
"contributorsPerLine": 7,

View File

@ -1,13 +1,23 @@
version: 2
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
updates:
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "weekly"
target-branch: "master"
open-pull-requests-limit: 0
- package-ecosystem: "bundler"
directories:
- "/"
- "/docs"
schedule:
interval: "weekly"
groups:
all-gems:
patterns: [ "*" ]
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
target-branch: "master"
groups:
all-actions:
patterns: [ "*" ]

View File

@ -1,9 +1,8 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
base64 (0.2.0)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
bigdecimal (3.1.8)
claide (1.1.0)
claide-plugins (0.9.2)
@ -11,10 +10,10 @@ GEM
nap
open4 (~> 1.3)
colored2 (3.1.2)
concurrent-ruby (1.2.3)
concurrent-ruby (1.3.4)
cork (0.3.0)
colored2 (~> 3.1)
danger (9.4.3)
danger (9.5.0)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
colored2 (~> 3.1)
@ -24,19 +23,19 @@ GEM
git (~> 1.13)
kramdown (~> 2.3)
kramdown-parser-gfm (~> 1.0)
no_proxy_fix
octokit (>= 4.0)
terminal-table (>= 1, < 4)
differ (0.1.2)
et-orbi (1.2.11)
tzinfo
faraday (2.9.0)
faraday-net_http (>= 2.0, < 3.2)
faraday (2.11.0)
faraday-net_http (>= 2.0, < 3.4)
logger
faraday-http-cache (2.5.1)
faraday (>= 0.8)
faraday-net_http (3.1.0)
faraday-net_http (3.3.0)
net-http
fugit (1.11.0)
fugit (1.11.1)
et-orbi (~> 1, >= 1.2.11)
raabro (~> 1.4)
git (1.19.1)
@ -46,16 +45,15 @@ GEM
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (5.5.0)
liquid (5.5.1)
logger (1.6.0)
logger-colors (1.0.0)
nap (1.1.0)
net-http (0.4.1)
uri
no_proxy_fix (0.1.2)
nokogiri (1.16.5-x86_64-linux)
nokogiri (1.16.7-x86_64-linux)
racc (~> 1.4)
octokit (8.1.0)
base64
octokit (9.1.0)
faraday (>= 1, < 3)
sawyer (~> 0.9)
open4 (1.3.4)
@ -66,13 +64,13 @@ GEM
nokogiri (~> 1.13)
rufus-scheduler (~> 3.8)
slop (~> 4.9)
public_suffix (5.0.5)
public_suffix (6.0.1)
raabro (1.4.0)
racc (1.8.0)
racc (1.8.1)
rchardet (1.8.0)
rexml (3.2.8)
strscan (>= 3.0.9)
rouge (4.2.1)
rexml (3.3.6)
strscan
rouge (4.3.0)
rufus-scheduler (3.9.1)
fugit (~> 1.1, >= 1.1.6)
safe_yaml (1.0.5)
@ -86,7 +84,7 @@ GEM
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
uri (0.13.0)
uri (0.13.1)
PLATFORMS
x86_64-linux

View File

@ -126,21 +126,43 @@ echo "Press enter to continue..."
read -r
# calculating stats for release notes
# determine current milestone
MILESTONE_JSON=$(curl -s "https://api.github.com/repos/pmd/pmd/milestones?state=all&direction=desc&per_page=5"|jq ".[] | select(.title == \"$RELEASE_VERSION\")")
MILESTONE=$(echo "$MILESTONE_JSON" | jq .number)
# determine dependency updates
DEPENDENCIES_JSON=$(curl -s "https://api.github.com/repos/pmd/pmd/issues?labels=dependencies&state=closed&direction=asc&per_page=50&page=1&milestone=${MILESTONE}")
DEPENDENCIES_COUNT=$(echo "$DEPENDENCIES_JSON" | jq length)
DEPENDENCIES=""
if [ $DEPENDENCIES_COUNT -gt 0 ]; then
DEPENDENCIES=$(
echo "### 📦 Dependency updates"
echo "$DEPENDENCIES_JSON" | jq --raw-output '.[] | "* [#\(.number)](https://github.com/pmd/pmd/issues/\(.number)): \(.title)"'
)
else
DEPENDENCIES=$(
echo "### 📦 Dependency updates"
echo "No dependency updates"
)
fi
# calculating stats for release notes (excluding dependency updates)
STATS_CLOSED_ISSUES=$(echo "$MILESTONE_JSON" | jq .closed_issues)
STATS=$(
echo "### 📈 Stats"
echo "* $(git log pmd_releases/"${LAST_VERSION}"..HEAD --oneline --no-merges |wc -l) commits"
echo "* $(curl -s "https://api.github.com/repos/pmd/pmd/milestones?state=all&direction=desc&per_page=5"|jq ".[] | select(.title == \"$RELEASE_VERSION\") | .closed_issues") closed tickets & PRs"
echo "* $(($STATS_CLOSED_ISSUES - $DEPENDENCIES_COUNT)) closed tickets & PRs"
echo "* Days since last release: $(( ( $(date +%s) - $(git log --max-count=1 --format="%at" pmd_releases/"${LAST_VERSION}") ) / 86400))"
)
TEMP_RELEASE_NOTES=$(cat docs/pages/release_notes.md)
TEMP_RELEASE_NOTES=${TEMP_RELEASE_NOTES/\{\% endtocmaker \%\}/${STATS//\&/\\\&}$'\n'$'\n'\{\% endtocmaker \%\}}
TEMP_RELEASE_NOTES=${TEMP_RELEASE_NOTES/\{\% endtocmaker \%\}/${DEPENDENCIES//\&/\\\&}$'\n'$'\n'${STATS//\&/\\\&}$'\n'$'\n'\{\% endtocmaker \%\}}
echo "${TEMP_RELEASE_NOTES}" > docs/pages/release_notes.md
echo
echo "Updated stats in release notes:"
echo "Updated dependencies and stats in release notes:"
echo "$DEPENDENCIES"
echo "$STATS"
echo
echo "Please verify docs/pages/release_notes.md"

View File

@ -1,18 +1,19 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.1.3.3)
activesupport (7.2.1)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
base64 (0.2.0)
bigdecimal (3.1.8)
coffee-script (2.4.1)
@ -21,10 +22,10 @@ GEM
coffee-script-source (1.12.2)
colorator (1.1.0)
commonmarker (0.23.10)
concurrent-ruby (1.2.3)
concurrent-ruby (1.3.4)
connection_pool (2.4.1)
csv (3.3.0)
dnsruby (1.72.1)
dnsruby (1.72.2)
simpleidn (~> 0.2.1)
drb (2.2.1)
em-websocket (0.5.3)
@ -34,19 +35,20 @@ GEM
ffi (>= 1.15.0)
eventmachine (1.2.7)
execjs (2.9.1)
faraday (2.9.0)
faraday-net_http (>= 2.0, < 3.2)
faraday-net_http (3.1.0)
faraday (2.11.0)
faraday-net_http (>= 2.0, < 3.4)
logger
faraday-net_http (3.3.0)
net-http
ffi (1.16.3)
ffi (1.17.0-x86_64-linux-gnu)
forwardable-extended (2.6.0)
gemoji (4.1.0)
github-pages (231)
github-pages (232)
github-pages-health-check (= 1.18.2)
jekyll (= 3.9.5)
jekyll (= 3.10.0)
jekyll-avatar (= 0.8.0)
jekyll-coffeescript (= 1.2.2)
jekyll-commonmark-ghpages (= 0.4.0)
jekyll-commonmark-ghpages (= 0.5.1)
jekyll-default-layout (= 0.1.5)
jekyll-feed (= 0.17.0)
jekyll-gist (= 1.5.0)
@ -83,9 +85,10 @@ GEM
liquid (= 4.0.4)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.13.6, < 2.0)
nokogiri (>= 1.16.2, < 2.0)
rouge (= 3.30.0)
terminal-table (~> 1.4)
webrick (~> 1.8)
github-pages-health-check (1.18.2)
addressable (~> 2.3)
dnsruby (~> 1.60)
@ -98,9 +101,10 @@ GEM
http_parser.rb (0.8.0)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
jekyll (3.9.5)
jekyll (3.10.0)
addressable (~> 2.4)
colorator (~> 1.0)
csv (~> 3.0)
em-websocket (~> 0.5)
i18n (>= 0.7, < 2)
jekyll-sass-converter (~> 1.0)
@ -111,6 +115,7 @@ GEM
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
webrick (>= 1.0)
jekyll-avatar (0.8.0)
jekyll (>= 3.0, < 5.0)
jekyll-coffeescript (1.2.2)
@ -118,9 +123,9 @@ GEM
coffee-script-source (~> 1.12)
jekyll-commonmark (1.4.0)
commonmarker (~> 0.22)
jekyll-commonmark-ghpages (0.4.0)
commonmarker (~> 0.23.7)
jekyll (~> 3.9.0)
jekyll-commonmark-ghpages (0.5.1)
commonmarker (>= 0.23.7, < 1.1.0)
jekyll (>= 3.9, < 4.0)
jekyll-commonmark (~> 1.4.0)
rouge (>= 2.0, < 5.0)
jekyll-default-layout (0.1.5)
@ -214,29 +219,29 @@ GEM
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.6.0)
mercenary (0.3.6)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.23.1)
mutex_m (0.2.0)
minitest (5.25.1)
net-http (0.4.1)
uri
nokogiri (1.16.5-x86_64-linux)
nokogiri (1.16.7-x86_64-linux)
racc (~> 1.4)
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (5.0.5)
racc (1.8.0)
public_suffix (5.1.1)
racc (1.8.1)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rexml (3.2.8)
strscan (>= 3.0.9)
rexml (3.3.6)
strscan
rouge (3.30.0)
rubyzip (2.3.2)
safe_yaml (1.0.5)
@ -248,6 +253,7 @@ GEM
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
securerandom (0.3.1)
simpleidn (0.2.3)
strscan (3.1.0)
terminal-table (1.8.0)
@ -257,7 +263,7 @@ GEM
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (1.8.0)
uri (0.13.0)
uri (0.13.1)
webrick (1.8.1)
PLATFORMS

View File

@ -1,9 +1,9 @@
repository: pmd/pmd
pmd:
version: 7.4.0-SNAPSHOT
previous_version: 7.3.0
date: 2024-07-26
version: 7.5.0-SNAPSHOT
previous_version: 7.4.0
date: 2024-08-30
# release types: major, minor, bugfix
release_type: minor

View File

@ -2,7 +2,7 @@
title: Release process
permalink: pmd_projectdocs_committers_releasing.html
author: Romain Pelisse <rpelisse@users.sourceforge.net>, Andreas Dangel <andreas.dangel@pmd-code.org>
last_updated: April 2024
last_updated: July 2024 (7.5.0)
---
This page describes the current status of the release process.
@ -67,8 +67,8 @@ news posts can be changed afterward (although that's an entirely manual process)
You can find the release notes here: `docs/pages/release_notes.md`.
The date (`date +%d-%B-%Y`) and the version (remove the SNAPSHOT) must be updated in `docs/_config.yml`, e.g.
in order to release version "6.34.0", the configuration should look like this:
The date (`date +%Y-%m-%d`) and the version (remove the SNAPSHOT) must be updated in `docs/_config.yml`, e.g.
in order to release version "7.2.0", the configuration should look like this:
```yaml
pmd:
@ -78,7 +78,7 @@ pmd:
release_type: minor
```
The release type could be one of "bugfix" (e.g. 7.1.x), "minor" (7.x.0), or "major" (x.0.0).
The release type could be one of "bugfix" (e.g. 7.2.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.
@ -95,25 +95,50 @@ not pmd-cli and pmd-dist.
In case, there is no need for a new pmd-designer version, we could stick to the latest already available version.
Then we can skip the release of pmd-designer and immediately start the second phase of the release.
Starting with PMD 7.5.0 we use Dependabot to update dependencies. Dependabot will create pull requests
labeled with `dependencies`. When we merge such a pull request, we should assign it to the correct
milestone. It is important, that the due date of the milestone is set correctly, otherwise the query won't find
the milestone number.
Then we can query which PRs have been merged and generate a section for the release notes:
```shell
NEW_VERSION=7.2.0
MILESTONE_JSON=$(curl -s "https://api.github.com/repos/pmd/pmd/milestones?state=all&direction=desc&per_page=5"|jq ".[] | select(.title == \"$NEW_VERSION\")")
MILESTONE=$(echo "$MILESTONE_JSON" | jq .number)
# determine dependency updates
DEPENDENCIES_JSON=$(curl -s "https://api.github.com/repos/pmd/pmd/issues?labels=dependencies&state=closed&direction=asc&per_page=50&page=1&milestone=${MILESTONE}")
DEPENDENCIES_COUNT=$(echo "$DEPENDENCIES_JSON" | jq length)
if [ $DEPENDENCIES_COUNT -gt 0 ]; then
echo "### 📦 Dependency updates"
echo "$DEPENDENCIES_JSON" | jq --raw-output '.[] | "* [#\(.number)](https://github.com/pmd/pmd/issues/\(.number)): \(.title)"'
else
echo "### 📦 Dependency updates"
echo "No dependency updates"
fi
```
This section needs to be added to the release notes at the end.
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
to the release notes as the last section (after "Dependency updates"). To count the closed issues and pull requests, the milestone
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 <https://github.com/pmd/pmd/milestones>. The following snippet will
create the numbers, that can be attached to the release notes as a last section:
create the numbers, that can be attached to the release notes as a last section. Note: It uses part of the
above code snippet (e.g. NEW_VERSION, MILESTONE, DEPENDENCIES_COUNT):
```shell
LAST_VERSION=7.1.0
NEW_VERSION=7.2.0
NEW_VERSION_COMMITISH=HEAD
STATS_CLOSED_ISSUES=$(echo "$MILESTONE_JSON" | jq .closed_issues)
echo "### Stats"
echo "* $(git log pmd_releases/${LAST_VERSION}..${NEW_VERSION_COMMITISH} --oneline --no-merges |wc -l) commits"
echo "* $(curl -s "https://api.github.com/repos/pmd/pmd/milestones?state=all&direction=desc&per_page=5"|jq ".[] | select(.title == \"$NEW_VERSION\") | .closed_issues") closed tickets & PRs"
echo "* $(($STATS_CLOSED_ISSUES - $DEPENDENCIES_COUNT)) closed tickets & PRs"
echo "* Days since last release: $(( ( $(date +%s) - $(git log --max-count=1 --format="%at" pmd_releases/${LAST_VERSION}) ) / 86400))"
```
Note: this part is also integrated into `do-release.sh`.
Note: both shell snippets are also integrated into `do-release.sh`.
Check in all (version) changes to branch master or any other branch, from which the release takes place:

File diff suppressed because it is too large Load Diff

View File

@ -14,59 +14,33 @@ This is a {{ site.pmd.release_type }} release.
### 🚀 New and noteworthy
### 🌟 New and changed rules
#### New Rules
* The new Apex rule {%rule apex/performance/AvoidNonRestrictiveQueries %} finds SOQL and SOSL queries without a where
or limit statement. This can quickly cause governor limit exceptions.
#### Changed rules
* {%rule apex/codestyle/ClassNamingConventions %}: Two new properties to configure different patterns
for inner classes and interfaces: `innerClassPattern` and `innerInterfacePattern`.
#### Renamed rules
* {%rule ecmascript/errorprone/InaccurateNumericLiteral %} has been renamed from `InnaccurateNumericLiteral`.
The old rule name still works but is deprecated.
### 🐛 Fixed Issues
* apex
* [#5094](https://github.com/pmd/pmd/issues/5094): \[apex] "No adapter exists for type" error message printed to stdout instead of stderr
* apex-bestpractices
* [#5095](https://github.com/pmd/pmd/issues/5095): \[apex] ApexUnitTestShouldNotUseSeeAllDataTrue false negative due to casing (regression in PMD 7)
* apex-codestyle
* [#4800](https://github.com/pmd/pmd/issues/4800): \[apex] ClassNamingConvention: Support naming convention for *inner* classes
* apex-performance
* [#635](https://github.com/pmd/pmd/issues/635): \[apex] New Rule: Avoid soql/sosl queries without a where clause or limit statement
* [#5139](https://github.com/pmd/pmd/issues/5139): \[apex] OperationWithHighCostInLoop: false negative for triggers
* java
* [#5167](https://github.com/pmd/pmd/issues/5167): \[java] java.lang.IllegalArgumentException: \<?\> cannot be a wildcard bound
* java-bestpractices
* [#5117](https://github.com/pmd/pmd/issues/5117): \[java] UnusedPrivateMethod for methods annotated with jakarta.annotation.PostConstruct or PreDestroy
* java-errorprone
* [#1488](https://github.com/pmd/pmd/issues/1488): \[java] MissingStaticMethodInNonInstantiatableClass: False positive with Lombok Builder on Constructor
* javascript-errorprone
* [#2367](https://github.com/pmd/pmd/issues/2367): \[javascript] InnaccurateNumericLiteral is misspelled
* [#4716](https://github.com/pmd/pmd/issues/4716): \[javascript] InaccurateNumericLiteral with number 259200000
* plsql
* [#5086](https://github.com/pmd/pmd/pull/5086): \[plsql] Fixed issue with missing optional table alias in MERGE usage
* [#5087](https://github.com/pmd/pmd/pull/5087): \[plsql] Add support for SQL_MACRO
* [#5088](https://github.com/pmd/pmd/pull/5088): \[plsql] Add support for 'DEFAULT' clause on the arguments of some oracle functions
* cli
* [#5120](https://github.com/pmd/pmd/issues/5120): \[cli] Can't start designer under Windows
* [#3602](https://github.com/pmd/pmd/issues/3602): \[java] GuardLogStatement: False positive when compile-time constant is created from external constants
* [#4731](https://github.com/pmd/pmd/issues/4731): \[java] GuardLogStatement: Documentation is unclear why getters are flagged
* [#5145](https://github.com/pmd/pmd/issues/5145): \[java] UnusedPrivateMethod: False positive with method calls inside lambda
* [#5151](https://github.com/pmd/pmd/issues/5151): \[java] GuardLogStatement: Should not need to guard parameterized log messages where the replacement arg is a constant from another class
* [#5152](https://github.com/pmd/pmd/issues/5152): \[java] GuardLogStatement: Should not need to guard parameterized log messages where the replacement arg is "this"
* [#5153](https://github.com/pmd/pmd/issues/5153): \[java] GuardLogStatement: Should not need to guard parameterized log messages where the replacement arg is an array element
* plsql-bestpractices
* [#5132](https://github.com/pmd/pmd/issues/5132): \[plsql] TomKytesDespair: XPathException for more complex exception handler
### 🚨 API Changes
* javascript
* The old rule name `InnaccurateNumericLiteral` has been deprecated. Use the new name
{%rule ecmascript/errorprone/InaccurateNumericLiteral %} instead.
* pmd-jsp
* {%jdoc jsp::lang.jsp.ast.JspParserImpl %} is deprecated now. It should have been package-private
because this is an implementation class that should not be used directly.
* pmd-velocity
* {%jdoc velocity::lang.velocity.ast.VtlParserImpl %} is deprecated now. It should have been package-private
because this is an implementation class that should not be used directly.
* pmd-visualforce
* {%jdoc visualforce::lang.visualforce.ast.VfParserImpl %} is deprecated now. It should have been package-private
because this is an implementation class that should not be used directly.
### ✨ External Contributions
* [#5048](https://github.com/pmd/pmd/pull/5048): \[apex] Added Inner Classes to Apex Class Naming Conventions Rule - [Justin Stroud](https://github.com/justinstroudbah) (@justinstroudbah / @sgnl-labs)
* [#5086](https://github.com/pmd/pmd/pull/5086): \[plsql] Fixed issue with missing optional table alias in MERGE usage - [Arjen Duursma](https://github.com/duursma) (@duursma)
* [#5087](https://github.com/pmd/pmd/pull/5087): \[plsql] Add support for SQL_MACRO - [Arjen Duursma](https://github.com/duursma) (@duursma)
* [#5088](https://github.com/pmd/pmd/pull/5088): \[plsql] Add support for 'DEFAULT' clause on the arguments of some oracle functions - [Arjen Duursma](https://github.com/duursma) (@duursma)
* [#5107](https://github.com/pmd/pmd/pull/5107): \[doc] Update maven.md - Typo fixed for maven target - [karthikaiyasamy](https://github.com/karthikaiyasamy) (@karthikaiyasamy)
* [#5109](https://github.com/pmd/pmd/pull/5109): \[java] Exclude constructor with lombok.Builder for MissingStaticMethodInNonInstantiatableClass - [Krzysztof Debski](https://github.com/kdebski85) (@kdebski85)
* [#5118](https://github.com/pmd/pmd/pull/5118): \[java] FP for UnusedPrivateMethod with Jakarta @<!-- -->PostConstruct/PreDestroy annotations - [Krzysztof Debski](https://github.com/kdebski85) (@kdebski85)
* [#5121](https://github.com/pmd/pmd/pull/5121): \[plsql] Fixed issue with missing optional table alias in MERGE usage - [Arjen Duursma](https://github.com/duursma) (@duursma)
{% endtocmaker %}

View File

@ -5,6 +5,86 @@ 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-July-2024 - 7.4.0
The PMD team is pleased to announce PMD 7.4.0.
This is a minor release.
### Table Of Contents
* [🌟 New and changed rules](#new-and-changed-rules)
* [New Rules](#new-rules)
* [Changed rules](#changed-rules)
* [Renamed rules](#renamed-rules)
* [🐛 Fixed Issues](#fixed-issues)
* [🚨 API Changes](#api-changes)
* [✨ External Contributions](#external-contributions)
* [📈 Stats](#stats)
### 🌟 New and changed rules
#### New Rules
* The new Apex rule [`AvoidNonRestrictiveQueries`](https://docs.pmd-code.org/pmd-doc-7.4.0/pmd_rules_apex_performance.html#avoidnonrestrictivequeries) finds SOQL and SOSL queries without a where
or limit statement. This can quickly cause governor limit exceptions.
#### Changed rules
* [`ClassNamingConventions`](https://docs.pmd-code.org/pmd-doc-7.4.0/pmd_rules_apex_codestyle.html#classnamingconventions) (Apex Codestyle): Two new properties to configure different patterns
for inner classes and interfaces: `innerClassPattern` and `innerInterfacePattern`.
#### Renamed rules
* [`InaccurateNumericLiteral`](https://docs.pmd-code.org/pmd-doc-7.4.0/pmd_rules_ecmascript_errorprone.html#inaccuratenumericliteral) (JavaScript Error Prone) has been renamed from `InnaccurateNumericLiteral`.
The old rule name still works but is deprecated.
### 🐛 Fixed Issues
* apex
* [#5094](https://github.com/pmd/pmd/issues/5094): \[apex] "No adapter exists for type" error message printed to stdout instead of stderr
* apex-bestpractices
* [#5095](https://github.com/pmd/pmd/issues/5095): \[apex] ApexUnitTestShouldNotUseSeeAllDataTrue false negative due to casing (regression in PMD 7)
* apex-codestyle
* [#4800](https://github.com/pmd/pmd/issues/4800): \[apex] ClassNamingConvention: Support naming convention for *inner* classes
* apex-performance
* [#635](https://github.com/pmd/pmd/issues/635): \[apex] New Rule: Avoid soql/sosl queries without a where clause or limit statement
* java-bestpractices
* [#5106](https://github.com/pmd/pmd/issues/5106): \[java] AccessorClassGeneration: Node was null for default constructor
* [#5110](https://github.com/pmd/pmd/issues/5110): \[java] UnusedPrivateMethod for method referenced by lombok.Builder.ObtainVia
* [#5117](https://github.com/pmd/pmd/issues/5117): \[java] UnusedPrivateMethod for methods annotated with jakarta.annotation.PostConstruct or PreDestroy
* java-errorprone
* [#1488](https://github.com/pmd/pmd/issues/1488): \[java] MissingStaticMethodInNonInstantiatableClass: False positive with Lombok Builder on Constructor
* javascript-errorprone
* [#2367](https://github.com/pmd/pmd/issues/2367): \[javascript] InnaccurateNumericLiteral is misspelled
* [#4716](https://github.com/pmd/pmd/issues/4716): \[javascript] InaccurateNumericLiteral with number 259200000
* plsql
* [#5086](https://github.com/pmd/pmd/pull/5086): \[plsql] Fixed issue with missing optional table alias in MERGE usage
* [#5087](https://github.com/pmd/pmd/pull/5087): \[plsql] Add support for SQL_MACRO
* [#5088](https://github.com/pmd/pmd/pull/5088): \[plsql] Add support for 'DEFAULT' clause on the arguments of some oracle functions
* [#5133](https://github.com/pmd/pmd/issues/5133): \[plsql] AssertionError: Root of the tree should implement RootNode for a PL/SQL type declaration
* cli
* [#5120](https://github.com/pmd/pmd/issues/5120): \[cli] Can't start designer under Windows
* core
* [#5091](https://github.com/pmd/pmd/issues/5091): \[core] PMD CPD v7.3.0 gives deprecation warning for skipLexicalErrors even when not used
### 🚨 API Changes
* javascript
* The old rule name `InnaccurateNumericLiteral` has been deprecated. Use the new name
[`InaccurateNumericLiteral`](https://docs.pmd-code.org/pmd-doc-7.4.0/pmd_rules_ecmascript_errorprone.html#inaccuratenumericliteral) instead.
### ✨ External Contributions
* [#5048](https://github.com/pmd/pmd/pull/5048): \[apex] Added Inner Classes to Apex Class Naming Conventions Rule - [Justin Stroud](https://github.com/justinstroudbah) (@justinstroudbah / @sgnl-labs)
* [#5086](https://github.com/pmd/pmd/pull/5086): \[plsql] Fixed issue with missing optional table alias in MERGE usage - [Arjen Duursma](https://github.com/duursma) (@duursma)
* [#5087](https://github.com/pmd/pmd/pull/5087): \[plsql] Add support for SQL_MACRO - [Arjen Duursma](https://github.com/duursma) (@duursma)
* [#5088](https://github.com/pmd/pmd/pull/5088): \[plsql] Add support for 'DEFAULT' clause on the arguments of some oracle functions - [Arjen Duursma](https://github.com/duursma) (@duursma)
* [#5107](https://github.com/pmd/pmd/pull/5107): \[doc] Update maven.md - Typo fixed for maven target - [karthikaiyasamy](https://github.com/karthikaiyasamy) (@karthikaiyasamy)
* [#5109](https://github.com/pmd/pmd/pull/5109): \[java] Exclude constructor with lombok.Builder for MissingStaticMethodInNonInstantiatableClass - [Krzysztof Debski](https://github.com/kdebski85) (@kdebski85)
* [#5111](https://github.com/pmd/pmd/pull/5111): \[java] Fix UnusedPrivateMethod for @<!-- -->lombok.Builder.ObtainVia - [Krzysztof Debski](https://github.com/kdebski85) (@kdebski85)
* [#5118](https://github.com/pmd/pmd/pull/5118): \[java] FP for UnusedPrivateMethod with Jakarta @<!-- -->PostConstruct/PreDestroy annotations - [Krzysztof Debski](https://github.com/kdebski85) (@kdebski85)
* [#5121](https://github.com/pmd/pmd/pull/5121): \[plsql] Fixed issue with missing optional table alias in MERGE usage - [Arjen Duursma](https://github.com/duursma) (@duursma)
### 📈 Stats
* 81 commits
* 32 closed tickets & PRs
* Days since last release: 27
## 28-June-2024 - 7.3.0

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>pmd</artifactId>
<groupId>net.sourceforge.pmd</groupId>
<version>7.4.0-SNAPSHOT</version>
<version>7.5.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -111,9 +111,6 @@ public class CPDTask extends Task {
+ "Use failOnError=\"false\" to not fail the build.", Project.MSG_WARN);
}
// implicitly enable skipLexicalErrors, so that we can fail the build at the end. A report is created in any case.
config.setSkipLexicalErrors(true);
config.setIgnoreAnnotations(ignoreAnnotations);
config.setIgnoreLiterals(ignoreLiterals);
config.setIgnoreIdentifiers(ignoreIdentifiers);

View File

@ -7,7 +7,7 @@
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>7.4.0-SNAPSHOT</version>
<version>7.5.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -10,6 +10,7 @@ import java.util.stream.Collectors;
import net.sourceforge.pmd.lang.document.TextDocument;
import net.sourceforge.pmd.lang.document.TextPos2d;
import net.sourceforge.pmd.lang.document.TextRegion;
import net.sourceforge.pmd.lang.rule.xpath.NoAttribute;
import com.google.summit.ast.SourceLocation;
import com.google.summit.ast.declaration.MethodDeclaration;
@ -27,6 +28,12 @@ public final class ASTMethod extends AbstractApexNode implements ApexQualifiable
*/
private static final String STATIC_INIT_ID = "<clinit>";
/**
* Internal name used by the synthetic trigger method.
* @see #isTriggerBlock()
*/
private static final String TRIGGER_INVOKE_ID = "<invoke>";
// Store the details instead of wrapping a com.google.summit.ast.Node.
// This is to allow synthetic ASTMethod nodes.
// An example is the trigger `invoke` method.
@ -150,4 +157,14 @@ public final class ASTMethod extends AbstractApexNode implements ApexQualifiable
public int getArity() {
return parameterTypes.size();
}
/**
* Checks whether this method is the synthetic trigger method.
* @return true if this method is the synthetic trigger method
* @since 7.5.0
*/
@NoAttribute
public boolean isTriggerBlock() {
return TRIGGER_INVOKE_ID.equals(internalName);
}
}

View File

@ -229,7 +229,7 @@ class ApexTreeBuilder(private val task: ParserTask, private val proc: ApexLangua
// 2. Add the expected ASTModifier child node
buildModifiers(emptyList()).also { it.setParent(invokeMethod) }
// 3. Elide the body CompoundStatement->ASTBlockStatement
node.body.forEach { buildChildren(it, parent = invokeMethod as AbstractApexNode) }
node.body.forEach { buildAndSetParent(it, parent = invokeMethod as AbstractApexNode) }
} else {
buildChildren(node, parent = this, exclude = { it in node.modifiers })
}
@ -737,18 +737,18 @@ class ApexTreeBuilder(private val task: ParserTask, private val proc: ApexLangua
findDescendants(root, nodeType = ASTProperty::class).forEach { node -> generateFields(node) }
// Sort resulting nodes
findDescendants(root, nodeType = ASTUserClass::class).forEach { node ->
findDescendants(root, nodeType = BaseApexClass::class).forEach { node ->
sortUserClassChildren(node)
}
}
/**
* Sort children of [ASTUserClass] in historical order.
* Sort children of [BaseApexClass] (ASTUserClass, ASTUserTrigger, ...) in historical order.
*
* This sorts [ASTField] nodes immediately after [ASTModifierNode] nodes at
* the start of the ordered children.
*/
private fun sortUserClassChildren(node: ASTUserClass) {
private fun sortUserClassChildren(node: BaseApexClass<*>) {
val children = ArrayList(node.children().toList())
children.sortBy{ when (it) {
@ -772,7 +772,13 @@ class ApexTreeBuilder(private val task: ParserTask, private val proc: ApexLangua
/** Generates [ASTField] nodes for the [ASTFieldDeclarationStatements]. */
private fun generateFields(node: ASTFieldDeclarationStatements) {
val parent = node.parent as BaseApexClass<*>
val parent = if (node.parent is BaseApexClass<*>) {
node.parent as BaseApexClass<*>
} else if (node.parent is ASTMethod && (node.parent as ASTMethod).isTriggerBlock) {
node.parent.parent as BaseApexClass<*>
} else {
throw IllegalStateException("Unexpected apex tree - field declaration $node cannot appear hear")
}
node.node.declarations
.map { decl ->

View File

@ -65,4 +65,9 @@ class ApexTreeDumpTest extends BaseTreeDumpTest {
void switchStatements() {
doTest("SwitchStatements");
}
@Test
void trigger() {
doTest("AccountTrigger");
}
}

View File

@ -0,0 +1,9 @@
// see https://github.com/pmd/pmd/issues/5139
trigger AccountTrigger on Account (before insert, before update) {
integer i = 0;
for (i = 0; i <15; i++) {
SObjectType token = Schema.getGlobalDescribe().get('Account');
}
integer anotherField = 2;
System.debug('test');
}

View File

@ -0,0 +1,50 @@
+- ApexFile[@DefiningType = "AccountTrigger", @RealLoc = true]
+- UserTrigger[@DefiningType = "AccountTrigger", @Image = "AccountTrigger", @Nested = false, @RealLoc = true, @SimpleName = "AccountTrigger", @TargetName = "Account", @Usages = (TriggerUsage.BEFORE_INSERT, TriggerUsage.BEFORE_UPDATE)]
+- ModifierNode[@Abstract = false, @DefiningType = "AccountTrigger", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- Field[@DefiningType = "AccountTrigger", @Image = "i", @Name = "i", @RealLoc = true, @Type = "Integer", @Value = "0"]
| +- ModifierNode[@Abstract = false, @DefiningType = "AccountTrigger", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- Field[@DefiningType = "AccountTrigger", @Image = "anotherField", @Name = "anotherField", @RealLoc = true, @Type = "Integer", @Value = "2"]
| +- ModifierNode[@Abstract = false, @DefiningType = "AccountTrigger", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- Method[@Arity = 0, @CanonicalName = "invoke", @Constructor = false, @DefiningType = "AccountTrigger", @Image = "invoke", @RealLoc = false, @ReturnType = "void", @StaticInitializer = false]
+- ModifierNode[@Abstract = false, @DefiningType = "AccountTrigger", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- FieldDeclarationStatements[@DefiningType = "AccountTrigger", @RealLoc = true, @TypeArguments = (), @TypeName = "Integer"]
| +- ModifierNode[@Abstract = false, @DefiningType = "AccountTrigger", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- FieldDeclaration[@DefiningType = "AccountTrigger", @Image = "i", @Name = "i", @RealLoc = true]
| +- LiteralExpression[@Boolean = false, @Decimal = false, @DefiningType = "AccountTrigger", @Double = false, @Image = "0", @Integer = true, @LiteralType = LiteralType.INTEGER, @Long = false, @Name = null, @Null = false, @RealLoc = true, @String = false]
| +- VariableExpression[@DefiningType = "AccountTrigger", @Image = "i", @RealLoc = true]
| +- EmptyReferenceExpression[@DefiningType = null, @RealLoc = false]
+- ForLoopStatement[@DefiningType = "AccountTrigger", @RealLoc = true]
| +- StandardCondition[@DefiningType = "AccountTrigger", @RealLoc = true]
| | +- BooleanExpression[@DefiningType = "AccountTrigger", @Op = BooleanOperator.LESS_THAN, @RealLoc = true]
| | +- VariableExpression[@DefiningType = "AccountTrigger", @Image = "i", @RealLoc = true]
| | | +- EmptyReferenceExpression[@DefiningType = null, @RealLoc = false]
| | +- LiteralExpression[@Boolean = false, @Decimal = false, @DefiningType = "AccountTrigger", @Double = false, @Image = "15", @Integer = true, @LiteralType = LiteralType.INTEGER, @Long = false, @Name = null, @Null = false, @RealLoc = true, @String = false]
| +- Expression[@DefiningType = "AccountTrigger", @RealLoc = true]
| | +- AssignmentExpression[@DefiningType = "AccountTrigger", @Op = AssignmentOperator.EQUALS, @RealLoc = true]
| | +- VariableExpression[@DefiningType = "AccountTrigger", @Image = "i", @RealLoc = true]
| | | +- EmptyReferenceExpression[@DefiningType = null, @RealLoc = false]
| | +- LiteralExpression[@Boolean = false, @Decimal = false, @DefiningType = "AccountTrigger", @Double = false, @Image = "0", @Integer = true, @LiteralType = LiteralType.INTEGER, @Long = false, @Name = null, @Null = false, @RealLoc = true, @String = false]
| +- BlockStatement[@CurlyBrace = true, @DefiningType = "AccountTrigger", @RealLoc = true]
| | +- VariableDeclarationStatements[@DefiningType = "AccountTrigger", @RealLoc = true]
| | +- ModifierNode[@Abstract = false, @DefiningType = "AccountTrigger", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| | +- VariableDeclaration[@DefiningType = "AccountTrigger", @Image = "token", @RealLoc = true, @Type = "SObjectType"]
| | +- MethodCallExpression[@DefiningType = "AccountTrigger", @FullMethodName = "get", @InputParametersSize = 1, @MethodName = "get", @RealLoc = true]
| | | +- ReferenceExpression[@DefiningType = "AccountTrigger", @Image = "", @RealLoc = false, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
| | | | +- MethodCallExpression[@DefiningType = "AccountTrigger", @FullMethodName = "Schema.getGlobalDescribe", @InputParametersSize = 0, @MethodName = "getGlobalDescribe", @RealLoc = true]
| | | | +- ReferenceExpression[@DefiningType = "AccountTrigger", @Image = "Schema", @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
| | | +- LiteralExpression[@Boolean = false, @Decimal = false, @DefiningType = "AccountTrigger", @Double = false, @Image = "Account", @Integer = false, @LiteralType = LiteralType.STRING, @Long = false, @Name = null, @Null = false, @RealLoc = true, @String = true]
| | +- VariableExpression[@DefiningType = "AccountTrigger", @Image = "token", @RealLoc = true]
| | +- EmptyReferenceExpression[@DefiningType = null, @RealLoc = false]
| +- PostfixExpression[@DefiningType = "AccountTrigger", @Op = PostfixOperator.INCREMENT, @RealLoc = true]
| +- VariableExpression[@DefiningType = "AccountTrigger", @Image = "i", @RealLoc = true]
| +- EmptyReferenceExpression[@DefiningType = null, @RealLoc = false]
+- FieldDeclarationStatements[@DefiningType = "AccountTrigger", @RealLoc = true, @TypeArguments = (), @TypeName = "Integer"]
| +- ModifierNode[@Abstract = false, @DefiningType = "AccountTrigger", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- FieldDeclaration[@DefiningType = "AccountTrigger", @Image = "anotherField", @Name = "anotherField", @RealLoc = true]
| +- LiteralExpression[@Boolean = false, @Decimal = false, @DefiningType = "AccountTrigger", @Double = false, @Image = "2", @Integer = true, @LiteralType = LiteralType.INTEGER, @Long = false, @Name = null, @Null = false, @RealLoc = true, @String = false]
| +- VariableExpression[@DefiningType = "AccountTrigger", @Image = "anotherField", @RealLoc = true]
| +- EmptyReferenceExpression[@DefiningType = null, @RealLoc = false]
+- ExpressionStatement[@DefiningType = "AccountTrigger", @RealLoc = true]
+- MethodCallExpression[@DefiningType = "AccountTrigger", @FullMethodName = "System.debug", @InputParametersSize = 1, @MethodName = "debug", @RealLoc = true]
+- ReferenceExpression[@DefiningType = "AccountTrigger", @Image = "System", @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
+- LiteralExpression[@Boolean = false, @Decimal = false, @DefiningType = "AccountTrigger", @Double = false, @Image = "test", @Integer = false, @LiteralType = LiteralType.STRING, @Long = false, @Name = null, @Null = false, @RealLoc = true, @String = true]

View File

@ -263,7 +263,7 @@ trigger CaseAssignLevel on CaseAssignLevel__c (after delete, after insert, after
<rule-property name="methodReportLevel">1</rule-property>
<expected-problems>1</expected-problems>
<expected-messages>
<message>The trigger 'CaseAssignLevel' has a cyclomatic complexity of 9.</message>
<message>The trigger 'CaseAssignLevel' has a cyclomatic complexity of 12.</message>
</expected-messages>
<code-ref id="trigger"/>
</test-code>

View File

@ -135,4 +135,18 @@ public class Foo {
]]></code>
</test-code>
<!-- End Schema method invocations -->
<test-code>
<description>#5139 [apex] OperationWithHighCostInLoop not firing in triggers</description>
<expected-problems>1</expected-problems>
<expected-linenumbers>4</expected-linenumbers>
<code><![CDATA[
trigger AccountTrigger on Account (before insert, before update) {
integer i = 0;
for (i = 0; i <15; i++) {
SObjectType token = Schema.getGlobalDescribe().get('Account');
}
}
]]></code>
</test-code>
</test-data>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>7.4.0-SNAPSHOT</version>
<version>7.5.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -124,7 +124,6 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand<CPDConfiguration>
configuration.setRendererName(rendererName);
configuration.setSkipBlocksPattern(skipBlocksPattern);
configuration.setSkipDuplicates(skipDuplicates);
configuration.setSkipLexicalErrors(skipLexicalErrors);
configuration.setSourceEncoding(encoding.getEncoding());
configuration.setInputUri(uri);
@ -133,9 +132,6 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand<CPDConfiguration>
configuration.setFailOnError(false);
}
// implicitly enable skipLexicalErrors, so that we can fail the build at the end. A report is created in any case.
configuration.setSkipLexicalErrors(true);
return configuration;
}

View File

@ -5,7 +5,7 @@
package net.sourceforge.pmd.cli;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.emptyString;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.ByteArrayOutputStream;
@ -146,7 +146,7 @@ abstract class BaseCliTest {
}
public void checkNoErrorOutput() {
checkStdErr(equalTo(""));
checkStdErr(emptyString());
}
public void checkStdOut(Matcher<? super String> matcher) {

View File

@ -239,10 +239,24 @@ class CpdCliTest extends BaseCliTest {
"--skip-lexical-errors")
.verify(r -> {
r.checkStdErr(containsPattern("Skipping file: Lexical error in file .*?BadFile\\.java"));
r.checkStdErr(containsString("--skip-lexical-errors is deprecated. Use --no-fail-on-error instead."));
r.checkStdOut(containsString("Found a 5 line (13 tokens) duplication"));
});
}
/**
* @see <a href="https://github.com/pmd/pmd/issues/5091">[core] PMD CPD v7.3.0 gives deprecation warning for skipLexicalErrors even when not used #5091</a>
* @throws Exception
*/
@Test
void noWarningsWithoutSkipLexicalErrors() throws Exception {
runCliSuccessfully("--minimum-tokens", "340", "--language", "java", "--dir", SRC_DIR, "--format", "text")
.verify(r -> {
r.checkNoErrorOutput();
r.checkStdOut(emptyString());
});
}
@Test
void testExitCodeWithLexicalErrors() throws Exception {
runCli(RECOVERED_ERRORS_OR_VIOLATIONS,

View File

@ -7,7 +7,7 @@
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>7.4.0-SNAPSHOT</version>
<version>7.5.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>7.4.0-SNAPSHOT</version>
<version>7.5.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -67,7 +67,8 @@ public class CPDConfiguration extends AbstractConfiguration {
private boolean ignoreIdentifierAndLiteralSequences = false;
@Deprecated
private boolean skipLexicalErrors = false;
// Note: The default value was false until up to 7.3.0 and is true since 7.4.0
private boolean skipLexicalErrors = true;
private boolean noSkipBlocks = false;

View File

@ -153,10 +153,6 @@ public final class CpdAnalysis implements AutoCloseable {
@SuppressWarnings("PMD.CloseResource")
public void performAnalysis(Consumer<CPDReport> consumer) {
if (configuration.isSkipLexicalErrors()) {
LOGGER.warn("The option skipLexicalErrors is deprecated. Use failOnError instead.");
}
try (SourceManager sourceManager = new SourceManager(files.getCollectedFiles())) {
Map<Language, CpdLexer> tokenizers =
sourceManager.getTextFiles().stream()

View File

@ -223,7 +223,6 @@ class CpdAnalysisTest {
PmdReporter reporter = mock(PmdReporter.class);
config.setReporter(reporter);
config.setSkipLexicalErrors(true); // must be true, otherwise CPD is aborted with first processing error
try (CpdAnalysis cpd = CpdAnalysis.create(config)) {
assertTrue(cpd.files().addSourceFile(FileId.fromPathLikeString("foo.dummy"), DummyLanguageModule.CPD_THROW_LEX_EXCEPTION));
assertTrue(cpd.files().addSourceFile(FileId.fromPathLikeString("foo2.dummy"), DummyLanguageModule.CPD_THROW_MALFORMED_SOURCE_EXCEPTION));
@ -252,7 +251,6 @@ class CpdAnalysisTest {
PmdReporter reporter = mock(PmdReporter.class);
config.setReporter(reporter);
config.setSkipLexicalErrors(true);
try (CpdAnalysis cpd = CpdAnalysis.create(config)) {
assertTrue(cpd.files().addSourceFile(FileId.fromPathLikeString("foo.dummy"), DummyLanguageModule.CPD_THROW_LEX_EXCEPTION));
assertTrue(cpd.files().addSourceFile(FileId.fromPathLikeString("foo2.dummy"), DummyLanguageModule.CPD_THROW_MALFORMED_SOURCE_EXCEPTION));

View File

@ -7,7 +7,7 @@
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>7.4.0-SNAPSHOT</version>
<version>7.5.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Some files were not shown because too many files have changed in this diff Show More