Merge branch 'master' into pr-5125
This commit is contained in:
commit
60a29f08a5
@ -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,
|
||||
|
16
.github/dependabot.yml
vendored
16
.github/dependabot.yml
vendored
@ -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: [ "*" ]
|
||||
|
40
Gemfile.lock
40
Gemfile.lock
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
@ -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 %}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 ->
|
||||
|
@ -65,4 +65,9 @@ class ApexTreeDumpTest extends BaseTreeDumpTest {
|
||||
void switchStatements() {
|
||||
doTest("SwitchStatements");
|
||||
}
|
||||
|
||||
@Test
|
||||
void trigger() {
|
||||
doTest("AccountTrigger");
|
||||
}
|
||||
}
|
||||
|
@ -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');
|
||||
}
|
@ -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]
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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));
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user