Merge branch 'master' into pr-5125
This commit is contained in:
commit
60a29f08a5
@ -7699,6 +7699,42 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"bug"
|
"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,
|
"contributorsPerLine": 7,
|
||||||
|
16
.github/dependabot.yml
vendored
16
.github/dependabot.yml
vendored
@ -1,13 +1,23 @@
|
|||||||
version: 2
|
version: 2
|
||||||
|
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||||
updates:
|
updates:
|
||||||
- package-ecosystem: "maven"
|
- package-ecosystem: "maven"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "weekly"
|
interval: "weekly"
|
||||||
target-branch: "master"
|
- package-ecosystem: "bundler"
|
||||||
open-pull-requests-limit: 0
|
directories:
|
||||||
|
- "/"
|
||||||
|
- "/docs"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
groups:
|
||||||
|
all-gems:
|
||||||
|
patterns: [ "*" ]
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "weekly"
|
interval: "weekly"
|
||||||
target-branch: "master"
|
groups:
|
||||||
|
all-actions:
|
||||||
|
patterns: [ "*" ]
|
||||||
|
40
Gemfile.lock
40
Gemfile.lock
@ -1,9 +1,8 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
addressable (2.8.6)
|
addressable (2.8.7)
|
||||||
public_suffix (>= 2.0.2, < 6.0)
|
public_suffix (>= 2.0.2, < 7.0)
|
||||||
base64 (0.2.0)
|
|
||||||
bigdecimal (3.1.8)
|
bigdecimal (3.1.8)
|
||||||
claide (1.1.0)
|
claide (1.1.0)
|
||||||
claide-plugins (0.9.2)
|
claide-plugins (0.9.2)
|
||||||
@ -11,10 +10,10 @@ GEM
|
|||||||
nap
|
nap
|
||||||
open4 (~> 1.3)
|
open4 (~> 1.3)
|
||||||
colored2 (3.1.2)
|
colored2 (3.1.2)
|
||||||
concurrent-ruby (1.2.3)
|
concurrent-ruby (1.3.4)
|
||||||
cork (0.3.0)
|
cork (0.3.0)
|
||||||
colored2 (~> 3.1)
|
colored2 (~> 3.1)
|
||||||
danger (9.4.3)
|
danger (9.5.0)
|
||||||
claide (~> 1.0)
|
claide (~> 1.0)
|
||||||
claide-plugins (>= 0.9.2)
|
claide-plugins (>= 0.9.2)
|
||||||
colored2 (~> 3.1)
|
colored2 (~> 3.1)
|
||||||
@ -24,19 +23,19 @@ GEM
|
|||||||
git (~> 1.13)
|
git (~> 1.13)
|
||||||
kramdown (~> 2.3)
|
kramdown (~> 2.3)
|
||||||
kramdown-parser-gfm (~> 1.0)
|
kramdown-parser-gfm (~> 1.0)
|
||||||
no_proxy_fix
|
|
||||||
octokit (>= 4.0)
|
octokit (>= 4.0)
|
||||||
terminal-table (>= 1, < 4)
|
terminal-table (>= 1, < 4)
|
||||||
differ (0.1.2)
|
differ (0.1.2)
|
||||||
et-orbi (1.2.11)
|
et-orbi (1.2.11)
|
||||||
tzinfo
|
tzinfo
|
||||||
faraday (2.9.0)
|
faraday (2.11.0)
|
||||||
faraday-net_http (>= 2.0, < 3.2)
|
faraday-net_http (>= 2.0, < 3.4)
|
||||||
|
logger
|
||||||
faraday-http-cache (2.5.1)
|
faraday-http-cache (2.5.1)
|
||||||
faraday (>= 0.8)
|
faraday (>= 0.8)
|
||||||
faraday-net_http (3.1.0)
|
faraday-net_http (3.3.0)
|
||||||
net-http
|
net-http
|
||||||
fugit (1.11.0)
|
fugit (1.11.1)
|
||||||
et-orbi (~> 1, >= 1.2.11)
|
et-orbi (~> 1, >= 1.2.11)
|
||||||
raabro (~> 1.4)
|
raabro (~> 1.4)
|
||||||
git (1.19.1)
|
git (1.19.1)
|
||||||
@ -46,16 +45,15 @@ GEM
|
|||||||
rexml
|
rexml
|
||||||
kramdown-parser-gfm (1.1.0)
|
kramdown-parser-gfm (1.1.0)
|
||||||
kramdown (~> 2.0)
|
kramdown (~> 2.0)
|
||||||
liquid (5.5.0)
|
liquid (5.5.1)
|
||||||
|
logger (1.6.0)
|
||||||
logger-colors (1.0.0)
|
logger-colors (1.0.0)
|
||||||
nap (1.1.0)
|
nap (1.1.0)
|
||||||
net-http (0.4.1)
|
net-http (0.4.1)
|
||||||
uri
|
uri
|
||||||
no_proxy_fix (0.1.2)
|
nokogiri (1.16.7-x86_64-linux)
|
||||||
nokogiri (1.16.5-x86_64-linux)
|
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
octokit (8.1.0)
|
octokit (9.1.0)
|
||||||
base64
|
|
||||||
faraday (>= 1, < 3)
|
faraday (>= 1, < 3)
|
||||||
sawyer (~> 0.9)
|
sawyer (~> 0.9)
|
||||||
open4 (1.3.4)
|
open4 (1.3.4)
|
||||||
@ -66,13 +64,13 @@ GEM
|
|||||||
nokogiri (~> 1.13)
|
nokogiri (~> 1.13)
|
||||||
rufus-scheduler (~> 3.8)
|
rufus-scheduler (~> 3.8)
|
||||||
slop (~> 4.9)
|
slop (~> 4.9)
|
||||||
public_suffix (5.0.5)
|
public_suffix (6.0.1)
|
||||||
raabro (1.4.0)
|
raabro (1.4.0)
|
||||||
racc (1.8.0)
|
racc (1.8.1)
|
||||||
rchardet (1.8.0)
|
rchardet (1.8.0)
|
||||||
rexml (3.2.8)
|
rexml (3.3.6)
|
||||||
strscan (>= 3.0.9)
|
strscan
|
||||||
rouge (4.2.1)
|
rouge (4.3.0)
|
||||||
rufus-scheduler (3.9.1)
|
rufus-scheduler (3.9.1)
|
||||||
fugit (~> 1.1, >= 1.1.6)
|
fugit (~> 1.1, >= 1.1.6)
|
||||||
safe_yaml (1.0.5)
|
safe_yaml (1.0.5)
|
||||||
@ -86,7 +84,7 @@ GEM
|
|||||||
tzinfo (2.0.6)
|
tzinfo (2.0.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
unicode-display_width (2.5.0)
|
unicode-display_width (2.5.0)
|
||||||
uri (0.13.0)
|
uri (0.13.1)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
x86_64-linux
|
x86_64-linux
|
||||||
|
@ -126,21 +126,43 @@ echo "Press enter to continue..."
|
|||||||
read -r
|
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=$(
|
STATS=$(
|
||||||
echo "### 📈 Stats"
|
echo "### 📈 Stats"
|
||||||
echo "* $(git log pmd_releases/"${LAST_VERSION}"..HEAD --oneline --no-merges |wc -l) commits"
|
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))"
|
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=$(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 "${TEMP_RELEASE_NOTES}" > docs/pages/release_notes.md
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Updated stats in release notes:"
|
echo "Updated dependencies and stats in release notes:"
|
||||||
|
echo "$DEPENDENCIES"
|
||||||
echo "$STATS"
|
echo "$STATS"
|
||||||
echo
|
echo
|
||||||
echo "Please verify docs/pages/release_notes.md"
|
echo "Please verify docs/pages/release_notes.md"
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
activesupport (7.1.3.3)
|
activesupport (7.2.1)
|
||||||
base64
|
base64
|
||||||
bigdecimal
|
bigdecimal
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||||
connection_pool (>= 2.2.5)
|
connection_pool (>= 2.2.5)
|
||||||
drb
|
drb
|
||||||
i18n (>= 1.6, < 2)
|
i18n (>= 1.6, < 2)
|
||||||
|
logger (>= 1.4.2)
|
||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
mutex_m
|
securerandom (>= 0.3)
|
||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0, >= 2.0.5)
|
||||||
addressable (2.8.6)
|
addressable (2.8.7)
|
||||||
public_suffix (>= 2.0.2, < 6.0)
|
public_suffix (>= 2.0.2, < 7.0)
|
||||||
base64 (0.2.0)
|
base64 (0.2.0)
|
||||||
bigdecimal (3.1.8)
|
bigdecimal (3.1.8)
|
||||||
coffee-script (2.4.1)
|
coffee-script (2.4.1)
|
||||||
@ -21,10 +22,10 @@ GEM
|
|||||||
coffee-script-source (1.12.2)
|
coffee-script-source (1.12.2)
|
||||||
colorator (1.1.0)
|
colorator (1.1.0)
|
||||||
commonmarker (0.23.10)
|
commonmarker (0.23.10)
|
||||||
concurrent-ruby (1.2.3)
|
concurrent-ruby (1.3.4)
|
||||||
connection_pool (2.4.1)
|
connection_pool (2.4.1)
|
||||||
csv (3.3.0)
|
csv (3.3.0)
|
||||||
dnsruby (1.72.1)
|
dnsruby (1.72.2)
|
||||||
simpleidn (~> 0.2.1)
|
simpleidn (~> 0.2.1)
|
||||||
drb (2.2.1)
|
drb (2.2.1)
|
||||||
em-websocket (0.5.3)
|
em-websocket (0.5.3)
|
||||||
@ -34,19 +35,20 @@ GEM
|
|||||||
ffi (>= 1.15.0)
|
ffi (>= 1.15.0)
|
||||||
eventmachine (1.2.7)
|
eventmachine (1.2.7)
|
||||||
execjs (2.9.1)
|
execjs (2.9.1)
|
||||||
faraday (2.9.0)
|
faraday (2.11.0)
|
||||||
faraday-net_http (>= 2.0, < 3.2)
|
faraday-net_http (>= 2.0, < 3.4)
|
||||||
faraday-net_http (3.1.0)
|
logger
|
||||||
|
faraday-net_http (3.3.0)
|
||||||
net-http
|
net-http
|
||||||
ffi (1.16.3)
|
ffi (1.17.0-x86_64-linux-gnu)
|
||||||
forwardable-extended (2.6.0)
|
forwardable-extended (2.6.0)
|
||||||
gemoji (4.1.0)
|
gemoji (4.1.0)
|
||||||
github-pages (231)
|
github-pages (232)
|
||||||
github-pages-health-check (= 1.18.2)
|
github-pages-health-check (= 1.18.2)
|
||||||
jekyll (= 3.9.5)
|
jekyll (= 3.10.0)
|
||||||
jekyll-avatar (= 0.8.0)
|
jekyll-avatar (= 0.8.0)
|
||||||
jekyll-coffeescript (= 1.2.2)
|
jekyll-coffeescript (= 1.2.2)
|
||||||
jekyll-commonmark-ghpages (= 0.4.0)
|
jekyll-commonmark-ghpages (= 0.5.1)
|
||||||
jekyll-default-layout (= 0.1.5)
|
jekyll-default-layout (= 0.1.5)
|
||||||
jekyll-feed (= 0.17.0)
|
jekyll-feed (= 0.17.0)
|
||||||
jekyll-gist (= 1.5.0)
|
jekyll-gist (= 1.5.0)
|
||||||
@ -83,9 +85,10 @@ GEM
|
|||||||
liquid (= 4.0.4)
|
liquid (= 4.0.4)
|
||||||
mercenary (~> 0.3)
|
mercenary (~> 0.3)
|
||||||
minima (= 2.5.1)
|
minima (= 2.5.1)
|
||||||
nokogiri (>= 1.13.6, < 2.0)
|
nokogiri (>= 1.16.2, < 2.0)
|
||||||
rouge (= 3.30.0)
|
rouge (= 3.30.0)
|
||||||
terminal-table (~> 1.4)
|
terminal-table (~> 1.4)
|
||||||
|
webrick (~> 1.8)
|
||||||
github-pages-health-check (1.18.2)
|
github-pages-health-check (1.18.2)
|
||||||
addressable (~> 2.3)
|
addressable (~> 2.3)
|
||||||
dnsruby (~> 1.60)
|
dnsruby (~> 1.60)
|
||||||
@ -98,9 +101,10 @@ GEM
|
|||||||
http_parser.rb (0.8.0)
|
http_parser.rb (0.8.0)
|
||||||
i18n (1.14.5)
|
i18n (1.14.5)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
jekyll (3.9.5)
|
jekyll (3.10.0)
|
||||||
addressable (~> 2.4)
|
addressable (~> 2.4)
|
||||||
colorator (~> 1.0)
|
colorator (~> 1.0)
|
||||||
|
csv (~> 3.0)
|
||||||
em-websocket (~> 0.5)
|
em-websocket (~> 0.5)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
jekyll-sass-converter (~> 1.0)
|
jekyll-sass-converter (~> 1.0)
|
||||||
@ -111,6 +115,7 @@ GEM
|
|||||||
pathutil (~> 0.9)
|
pathutil (~> 0.9)
|
||||||
rouge (>= 1.7, < 4)
|
rouge (>= 1.7, < 4)
|
||||||
safe_yaml (~> 1.0)
|
safe_yaml (~> 1.0)
|
||||||
|
webrick (>= 1.0)
|
||||||
jekyll-avatar (0.8.0)
|
jekyll-avatar (0.8.0)
|
||||||
jekyll (>= 3.0, < 5.0)
|
jekyll (>= 3.0, < 5.0)
|
||||||
jekyll-coffeescript (1.2.2)
|
jekyll-coffeescript (1.2.2)
|
||||||
@ -118,9 +123,9 @@ GEM
|
|||||||
coffee-script-source (~> 1.12)
|
coffee-script-source (~> 1.12)
|
||||||
jekyll-commonmark (1.4.0)
|
jekyll-commonmark (1.4.0)
|
||||||
commonmarker (~> 0.22)
|
commonmarker (~> 0.22)
|
||||||
jekyll-commonmark-ghpages (0.4.0)
|
jekyll-commonmark-ghpages (0.5.1)
|
||||||
commonmarker (~> 0.23.7)
|
commonmarker (>= 0.23.7, < 1.1.0)
|
||||||
jekyll (~> 3.9.0)
|
jekyll (>= 3.9, < 4.0)
|
||||||
jekyll-commonmark (~> 1.4.0)
|
jekyll-commonmark (~> 1.4.0)
|
||||||
rouge (>= 2.0, < 5.0)
|
rouge (>= 2.0, < 5.0)
|
||||||
jekyll-default-layout (0.1.5)
|
jekyll-default-layout (0.1.5)
|
||||||
@ -214,29 +219,29 @@ GEM
|
|||||||
listen (3.9.0)
|
listen (3.9.0)
|
||||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||||
rb-inotify (~> 0.9, >= 0.9.10)
|
rb-inotify (~> 0.9, >= 0.9.10)
|
||||||
|
logger (1.6.0)
|
||||||
mercenary (0.3.6)
|
mercenary (0.3.6)
|
||||||
minima (2.5.1)
|
minima (2.5.1)
|
||||||
jekyll (>= 3.5, < 5.0)
|
jekyll (>= 3.5, < 5.0)
|
||||||
jekyll-feed (~> 0.9)
|
jekyll-feed (~> 0.9)
|
||||||
jekyll-seo-tag (~> 2.1)
|
jekyll-seo-tag (~> 2.1)
|
||||||
minitest (5.23.1)
|
minitest (5.25.1)
|
||||||
mutex_m (0.2.0)
|
|
||||||
net-http (0.4.1)
|
net-http (0.4.1)
|
||||||
uri
|
uri
|
||||||
nokogiri (1.16.5-x86_64-linux)
|
nokogiri (1.16.7-x86_64-linux)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
octokit (4.25.1)
|
octokit (4.25.1)
|
||||||
faraday (>= 1, < 3)
|
faraday (>= 1, < 3)
|
||||||
sawyer (~> 0.9)
|
sawyer (~> 0.9)
|
||||||
pathutil (0.16.2)
|
pathutil (0.16.2)
|
||||||
forwardable-extended (~> 2.6)
|
forwardable-extended (~> 2.6)
|
||||||
public_suffix (5.0.5)
|
public_suffix (5.1.1)
|
||||||
racc (1.8.0)
|
racc (1.8.1)
|
||||||
rb-fsevent (0.11.2)
|
rb-fsevent (0.11.2)
|
||||||
rb-inotify (0.11.1)
|
rb-inotify (0.11.1)
|
||||||
ffi (~> 1.0)
|
ffi (~> 1.0)
|
||||||
rexml (3.2.8)
|
rexml (3.3.6)
|
||||||
strscan (>= 3.0.9)
|
strscan
|
||||||
rouge (3.30.0)
|
rouge (3.30.0)
|
||||||
rubyzip (2.3.2)
|
rubyzip (2.3.2)
|
||||||
safe_yaml (1.0.5)
|
safe_yaml (1.0.5)
|
||||||
@ -248,6 +253,7 @@ GEM
|
|||||||
sawyer (0.9.2)
|
sawyer (0.9.2)
|
||||||
addressable (>= 2.3.5)
|
addressable (>= 2.3.5)
|
||||||
faraday (>= 0.17.3, < 3)
|
faraday (>= 0.17.3, < 3)
|
||||||
|
securerandom (0.3.1)
|
||||||
simpleidn (0.2.3)
|
simpleidn (0.2.3)
|
||||||
strscan (3.1.0)
|
strscan (3.1.0)
|
||||||
terminal-table (1.8.0)
|
terminal-table (1.8.0)
|
||||||
@ -257,7 +263,7 @@ GEM
|
|||||||
tzinfo (2.0.6)
|
tzinfo (2.0.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
unicode-display_width (1.8.0)
|
unicode-display_width (1.8.0)
|
||||||
uri (0.13.0)
|
uri (0.13.1)
|
||||||
webrick (1.8.1)
|
webrick (1.8.1)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
repository: pmd/pmd
|
repository: pmd/pmd
|
||||||
|
|
||||||
pmd:
|
pmd:
|
||||||
version: 7.4.0-SNAPSHOT
|
version: 7.5.0-SNAPSHOT
|
||||||
previous_version: 7.3.0
|
previous_version: 7.4.0
|
||||||
date: 2024-07-26
|
date: 2024-08-30
|
||||||
# release types: major, minor, bugfix
|
# release types: major, minor, bugfix
|
||||||
release_type: minor
|
release_type: minor
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
title: Release process
|
title: Release process
|
||||||
permalink: pmd_projectdocs_committers_releasing.html
|
permalink: pmd_projectdocs_committers_releasing.html
|
||||||
author: Romain Pelisse <rpelisse@users.sourceforge.net>, Andreas Dangel <andreas.dangel@pmd-code.org>
|
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.
|
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`.
|
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.
|
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 "6.34.0", the configuration should look like this:
|
in order to release version "7.2.0", the configuration should look like this:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
pmd:
|
pmd:
|
||||||
@ -78,7 +78,7 @@ pmd:
|
|||||||
release_type: minor
|
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.
|
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.
|
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.
|
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
|
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
|
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.
|
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
|
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
|
```shell
|
||||||
LAST_VERSION=7.1.0
|
LAST_VERSION=7.1.0
|
||||||
NEW_VERSION=7.2.0
|
|
||||||
NEW_VERSION_COMMITISH=HEAD
|
NEW_VERSION_COMMITISH=HEAD
|
||||||
|
STATS_CLOSED_ISSUES=$(echo "$MILESTONE_JSON" | jq .closed_issues)
|
||||||
|
|
||||||
echo "### Stats"
|
echo "### Stats"
|
||||||
echo "* $(git log pmd_releases/${LAST_VERSION}..${NEW_VERSION_COMMITISH} --oneline --no-merges |wc -l) commits"
|
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))"
|
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:
|
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 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
|
### 🐛 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
|
* 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
|
* java-bestpractices
|
||||||
* [#5117](https://github.com/pmd/pmd/issues/5117): \[java] UnusedPrivateMethod for methods annotated with jakarta.annotation.PostConstruct or PreDestroy
|
* [#3602](https://github.com/pmd/pmd/issues/3602): \[java] GuardLogStatement: False positive when compile-time constant is created from external constants
|
||||||
* java-errorprone
|
* [#4731](https://github.com/pmd/pmd/issues/4731): \[java] GuardLogStatement: Documentation is unclear why getters are flagged
|
||||||
* [#1488](https://github.com/pmd/pmd/issues/1488): \[java] MissingStaticMethodInNonInstantiatableClass: False positive with Lombok Builder on Constructor
|
* [#5145](https://github.com/pmd/pmd/issues/5145): \[java] UnusedPrivateMethod: False positive with method calls inside lambda
|
||||||
* javascript-errorprone
|
* [#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
|
||||||
* [#2367](https://github.com/pmd/pmd/issues/2367): \[javascript] InnaccurateNumericLiteral is misspelled
|
* [#5152](https://github.com/pmd/pmd/issues/5152): \[java] GuardLogStatement: Should not need to guard parameterized log messages where the replacement arg is "this"
|
||||||
* [#4716](https://github.com/pmd/pmd/issues/4716): \[javascript] InaccurateNumericLiteral with number 259200000
|
* [#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
|
* plsql-bestpractices
|
||||||
* [#5086](https://github.com/pmd/pmd/pull/5086): \[plsql] Fixed issue with missing optional table alias in MERGE usage
|
* [#5132](https://github.com/pmd/pmd/issues/5132): \[plsql] TomKytesDespair: XPathException for more complex exception handler
|
||||||
* [#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
|
|
||||||
|
|
||||||
### 🚨 API Changes
|
### 🚨 API Changes
|
||||||
|
* pmd-jsp
|
||||||
* javascript
|
* {%jdoc jsp::lang.jsp.ast.JspParserImpl %} is deprecated now. It should have been package-private
|
||||||
* The old rule name `InnaccurateNumericLiteral` has been deprecated. Use the new name
|
because this is an implementation class that should not be used directly.
|
||||||
{%rule ecmascript/errorprone/InaccurateNumericLiteral %} instead.
|
* 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
|
### ✨ 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 %}
|
{% 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)
|
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
|
## 28-June-2024 - 7.3.0
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>pmd</artifactId>
|
<artifactId>pmd</artifactId>
|
||||||
<groupId>net.sourceforge.pmd</groupId>
|
<groupId>net.sourceforge.pmd</groupId>
|
||||||
<version>7.4.0-SNAPSHOT</version>
|
<version>7.5.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<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);
|
+ "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.setIgnoreAnnotations(ignoreAnnotations);
|
||||||
config.setIgnoreLiterals(ignoreLiterals);
|
config.setIgnoreLiterals(ignoreLiterals);
|
||||||
config.setIgnoreIdentifiers(ignoreIdentifiers);
|
config.setIgnoreIdentifiers(ignoreIdentifiers);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.sourceforge.pmd</groupId>
|
<groupId>net.sourceforge.pmd</groupId>
|
||||||
<artifactId>pmd</artifactId>
|
<artifactId>pmd</artifactId>
|
||||||
<version>7.4.0-SNAPSHOT</version>
|
<version>7.5.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import java.util.stream.Collectors;
|
|||||||
import net.sourceforge.pmd.lang.document.TextDocument;
|
import net.sourceforge.pmd.lang.document.TextDocument;
|
||||||
import net.sourceforge.pmd.lang.document.TextPos2d;
|
import net.sourceforge.pmd.lang.document.TextPos2d;
|
||||||
import net.sourceforge.pmd.lang.document.TextRegion;
|
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.SourceLocation;
|
||||||
import com.google.summit.ast.declaration.MethodDeclaration;
|
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>";
|
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.
|
// Store the details instead of wrapping a com.google.summit.ast.Node.
|
||||||
// This is to allow synthetic ASTMethod nodes.
|
// This is to allow synthetic ASTMethod nodes.
|
||||||
// An example is the trigger `invoke` method.
|
// An example is the trigger `invoke` method.
|
||||||
@ -150,4 +157,14 @@ public final class ASTMethod extends AbstractApexNode implements ApexQualifiable
|
|||||||
public int getArity() {
|
public int getArity() {
|
||||||
return parameterTypes.size();
|
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
|
// 2. Add the expected ASTModifier child node
|
||||||
buildModifiers(emptyList()).also { it.setParent(invokeMethod) }
|
buildModifiers(emptyList()).also { it.setParent(invokeMethod) }
|
||||||
// 3. Elide the body CompoundStatement->ASTBlockStatement
|
// 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 {
|
} else {
|
||||||
buildChildren(node, parent = this, exclude = { it in node.modifiers })
|
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) }
|
findDescendants(root, nodeType = ASTProperty::class).forEach { node -> generateFields(node) }
|
||||||
|
|
||||||
// Sort resulting nodes
|
// Sort resulting nodes
|
||||||
findDescendants(root, nodeType = ASTUserClass::class).forEach { node ->
|
findDescendants(root, nodeType = BaseApexClass::class).forEach { node ->
|
||||||
sortUserClassChildren(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
|
* This sorts [ASTField] nodes immediately after [ASTModifierNode] nodes at
|
||||||
* the start of the ordered children.
|
* the start of the ordered children.
|
||||||
*/
|
*/
|
||||||
private fun sortUserClassChildren(node: ASTUserClass) {
|
private fun sortUserClassChildren(node: BaseApexClass<*>) {
|
||||||
val children = ArrayList(node.children().toList())
|
val children = ArrayList(node.children().toList())
|
||||||
|
|
||||||
children.sortBy{ when (it) {
|
children.sortBy{ when (it) {
|
||||||
@ -772,7 +772,13 @@ class ApexTreeBuilder(private val task: ParserTask, private val proc: ApexLangua
|
|||||||
|
|
||||||
/** Generates [ASTField] nodes for the [ASTFieldDeclarationStatements]. */
|
/** Generates [ASTField] nodes for the [ASTFieldDeclarationStatements]. */
|
||||||
private fun generateFields(node: 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
|
node.node.declarations
|
||||||
.map { decl ->
|
.map { decl ->
|
||||||
|
@ -65,4 +65,9 @@ class ApexTreeDumpTest extends BaseTreeDumpTest {
|
|||||||
void switchStatements() {
|
void switchStatements() {
|
||||||
doTest("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>
|
<rule-property name="methodReportLevel">1</rule-property>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
<expected-messages>
|
<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>
|
</expected-messages>
|
||||||
<code-ref id="trigger"/>
|
<code-ref id="trigger"/>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
@ -135,4 +135,18 @@ public class Foo {
|
|||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
<!-- End Schema method invocations -->
|
<!-- 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>
|
</test-data>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.sourceforge.pmd</groupId>
|
<groupId>net.sourceforge.pmd</groupId>
|
||||||
<artifactId>pmd</artifactId>
|
<artifactId>pmd</artifactId>
|
||||||
<version>7.4.0-SNAPSHOT</version>
|
<version>7.5.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -124,7 +124,6 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand<CPDConfiguration>
|
|||||||
configuration.setRendererName(rendererName);
|
configuration.setRendererName(rendererName);
|
||||||
configuration.setSkipBlocksPattern(skipBlocksPattern);
|
configuration.setSkipBlocksPattern(skipBlocksPattern);
|
||||||
configuration.setSkipDuplicates(skipDuplicates);
|
configuration.setSkipDuplicates(skipDuplicates);
|
||||||
configuration.setSkipLexicalErrors(skipLexicalErrors);
|
|
||||||
configuration.setSourceEncoding(encoding.getEncoding());
|
configuration.setSourceEncoding(encoding.getEncoding());
|
||||||
configuration.setInputUri(uri);
|
configuration.setInputUri(uri);
|
||||||
|
|
||||||
@ -133,9 +132,6 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand<CPDConfiguration>
|
|||||||
configuration.setFailOnError(false);
|
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;
|
return configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
package net.sourceforge.pmd.cli;
|
package net.sourceforge.pmd.cli;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
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 static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@ -146,7 +146,7 @@ abstract class BaseCliTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void checkNoErrorOutput() {
|
public void checkNoErrorOutput() {
|
||||||
checkStdErr(equalTo(""));
|
checkStdErr(emptyString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkStdOut(Matcher<? super String> matcher) {
|
public void checkStdOut(Matcher<? super String> matcher) {
|
||||||
|
@ -239,10 +239,24 @@ class CpdCliTest extends BaseCliTest {
|
|||||||
"--skip-lexical-errors")
|
"--skip-lexical-errors")
|
||||||
.verify(r -> {
|
.verify(r -> {
|
||||||
r.checkStdErr(containsPattern("Skipping file: Lexical error in file .*?BadFile\\.java"));
|
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"));
|
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
|
@Test
|
||||||
void testExitCodeWithLexicalErrors() throws Exception {
|
void testExitCodeWithLexicalErrors() throws Exception {
|
||||||
runCli(RECOVERED_ERRORS_OR_VIOLATIONS,
|
runCli(RECOVERED_ERRORS_OR_VIOLATIONS,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.sourceforge.pmd</groupId>
|
<groupId>net.sourceforge.pmd</groupId>
|
||||||
<artifactId>pmd</artifactId>
|
<artifactId>pmd</artifactId>
|
||||||
<version>7.4.0-SNAPSHOT</version>
|
<version>7.5.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.sourceforge.pmd</groupId>
|
<groupId>net.sourceforge.pmd</groupId>
|
||||||
<artifactId>pmd</artifactId>
|
<artifactId>pmd</artifactId>
|
||||||
<version>7.4.0-SNAPSHOT</version>
|
<version>7.5.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -67,7 +67,8 @@ public class CPDConfiguration extends AbstractConfiguration {
|
|||||||
private boolean ignoreIdentifierAndLiteralSequences = false;
|
private boolean ignoreIdentifierAndLiteralSequences = false;
|
||||||
|
|
||||||
@Deprecated
|
@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;
|
private boolean noSkipBlocks = false;
|
||||||
|
|
||||||
|
@ -153,10 +153,6 @@ public final class CpdAnalysis implements AutoCloseable {
|
|||||||
|
|
||||||
@SuppressWarnings("PMD.CloseResource")
|
@SuppressWarnings("PMD.CloseResource")
|
||||||
public void performAnalysis(Consumer<CPDReport> consumer) {
|
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())) {
|
try (SourceManager sourceManager = new SourceManager(files.getCollectedFiles())) {
|
||||||
Map<Language, CpdLexer> tokenizers =
|
Map<Language, CpdLexer> tokenizers =
|
||||||
sourceManager.getTextFiles().stream()
|
sourceManager.getTextFiles().stream()
|
||||||
|
@ -223,7 +223,6 @@ class CpdAnalysisTest {
|
|||||||
PmdReporter reporter = mock(PmdReporter.class);
|
PmdReporter reporter = mock(PmdReporter.class);
|
||||||
config.setReporter(reporter);
|
config.setReporter(reporter);
|
||||||
|
|
||||||
config.setSkipLexicalErrors(true); // must be true, otherwise CPD is aborted with first processing error
|
|
||||||
try (CpdAnalysis cpd = CpdAnalysis.create(config)) {
|
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("foo.dummy"), DummyLanguageModule.CPD_THROW_LEX_EXCEPTION));
|
||||||
assertTrue(cpd.files().addSourceFile(FileId.fromPathLikeString("foo2.dummy"), DummyLanguageModule.CPD_THROW_MALFORMED_SOURCE_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);
|
PmdReporter reporter = mock(PmdReporter.class);
|
||||||
config.setReporter(reporter);
|
config.setReporter(reporter);
|
||||||
|
|
||||||
config.setSkipLexicalErrors(true);
|
|
||||||
try (CpdAnalysis cpd = CpdAnalysis.create(config)) {
|
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("foo.dummy"), DummyLanguageModule.CPD_THROW_LEX_EXCEPTION));
|
||||||
assertTrue(cpd.files().addSourceFile(FileId.fromPathLikeString("foo2.dummy"), DummyLanguageModule.CPD_THROW_MALFORMED_SOURCE_EXCEPTION));
|
assertTrue(cpd.files().addSourceFile(FileId.fromPathLikeString("foo2.dummy"), DummyLanguageModule.CPD_THROW_MALFORMED_SOURCE_EXCEPTION));
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.sourceforge.pmd</groupId>
|
<groupId>net.sourceforge.pmd</groupId>
|
||||||
<artifactId>pmd</artifactId>
|
<artifactId>pmd</artifactId>
|
||||||
<version>7.4.0-SNAPSHOT</version>
|
<version>7.5.0-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</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