forked from phoedos/pmd
Merge branch 'pmd/7.0.x' into pmd7-junit5-part2
This commit is contained in:
commit
a4422cf2e6
@ -492,7 +492,8 @@
|
||||
"profile": "https://github.com/pzygielo",
|
||||
"contributions": [
|
||||
"code",
|
||||
"bug"
|
||||
"bug",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -3269,7 +3270,8 @@
|
||||
"profile": "https://github.com/jborgers",
|
||||
"contributions": [
|
||||
"bug",
|
||||
"code"
|
||||
"code",
|
||||
"talk"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -6522,7 +6524,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/36415196?v=4",
|
||||
"profile": "https://github.com/dykov",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -6540,7 +6543,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/178883?v=4",
|
||||
"profile": "https://github.com/gredler",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -6559,7 +6563,8 @@
|
||||
"profile": "https://github.com/JerritEic",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
"doc",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -6777,7 +6782,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/90252673?v=4",
|
||||
"profile": "https://github.com/abyss638",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -6798,7 +6804,8 @@
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},{
|
||||
},
|
||||
{
|
||||
"login": "pacvz",
|
||||
"name": "pacvz",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/35453365?v=4",
|
||||
@ -6806,6 +6813,133 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mohan-chinnappan-n",
|
||||
"name": "mohan-chinnappan-n",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5963194?v=4",
|
||||
"profile": "https://mohan-chinnappan-n.github.io/about/cv.html",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Suvashri",
|
||||
"name": "Suvashri",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/112872981?v=4",
|
||||
"profile": "https://github.com/Suvashri",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "osiegmar",
|
||||
"name": "Oliver Siegmar",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1918869?v=4",
|
||||
"profile": "https://github.com/osiegmar",
|
||||
"contributions": [
|
||||
"financial"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "OlegAndreych",
|
||||
"name": "Oleg Andreych",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2041351?v=4",
|
||||
"profile": "https://github.com/OlegAndreych",
|
||||
"contributions": [
|
||||
"code",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lfalcantar",
|
||||
"name": "Luis Alcantar",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/13026131?v=4",
|
||||
"profile": "https://github.com/lfalcantar",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "LynnBroe",
|
||||
"name": "Lynn",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/109954313?v=4",
|
||||
"profile": "https://github.com/LynnBroe",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "sashashura",
|
||||
"name": "Alex",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/93376818?v=4",
|
||||
"profile": "https://github.com/sashashura",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "koalalam",
|
||||
"name": "koalalam",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5452429?v=4",
|
||||
"profile": "https://github.com/koalalam",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "garydgregory",
|
||||
"name": "Gary Gregory",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1187639?v=4",
|
||||
"profile": "https://github.com/garydgregory",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "vanguard-1024",
|
||||
"name": "Austin",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/87691060?v=4",
|
||||
"profile": "https://github.com/vanguard-1024",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ewantempero",
|
||||
"name": "Ewan Tempero",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/8744237?v=4",
|
||||
"profile": "http://www.cs.auckland.ac.nz/~ewan",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "cbfiddle",
|
||||
"name": "cbfiddle",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6628505?v=4",
|
||||
"profile": "https://github.com/cbfiddle",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "MartGit",
|
||||
"name": "MartGit",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1518723?v=4",
|
||||
"profile": "https://github.com/MartGit",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Alexx-G",
|
||||
"name": "Alex",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3869268?v=4",
|
||||
"profile": "https://github.com/Alexx-G",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
23
.ci/build.sh
23
.ci/build.sh
@ -42,17 +42,20 @@ function build() {
|
||||
./mvnw clean install --show-version --errors --batch-mode --no-transfer-progress "${PMD_MAVEN_EXTRA_OPTS[@]}"
|
||||
pmd_ci_log_group_end
|
||||
|
||||
# Danger is executed only on the linux runner
|
||||
if [ "$(pmd_ci_utils_get_os)" = "linux" ]; then
|
||||
pmd_ci_log_group_start "Executing danger"
|
||||
regression_tester_setup_ci
|
||||
regression_tester_executeDanger
|
||||
pmd_ci_log_group_end
|
||||
# Execute danger and dogfood only for pull requests in our own repository
|
||||
if [[ "${PMD_CI_IS_FORK}" = "false" && -n "${PMD_CI_PULL_REQUEST_NUMBER}" ]]; then
|
||||
# Danger is executed only on the linux runner
|
||||
if [ "$(pmd_ci_utils_get_os)" = "linux" ]; then
|
||||
pmd_ci_log_group_start "Executing danger"
|
||||
regression_tester_setup_ci
|
||||
regression_tester_executeDanger
|
||||
pmd_ci_log_group_end
|
||||
|
||||
# also run dogfood for PRs (only on linux)
|
||||
pmd_ci_log_group_start "Executing PMD dogfood test with ${PMD_CI_MAVEN_PROJECT_VERSION}"
|
||||
pmd_ci_dogfood
|
||||
pmd_ci_log_group_end
|
||||
# also run dogfood for PRs (only on linux)
|
||||
pmd_ci_log_group_start "Executing PMD dogfood test with ${PMD_CI_MAVEN_PROJECT_VERSION}"
|
||||
pmd_ci_dogfood
|
||||
pmd_ci_log_group_end
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
@ -169,4 +169,12 @@ EOF
|
||||
<tag>v2.3.0</tag>
|
||||
<src-subpath>samples</src-subpath>
|
||||
</project>
|
||||
|
||||
<project>
|
||||
<name>java-regression-tests</name>
|
||||
<type>git</type>
|
||||
<connection>https://github.com/pmd/java-regression-tests</connection>
|
||||
<tag>main</tag>
|
||||
<auxclasspath-command>realpath java-regression-tests-*.jar</auxclasspath-command>
|
||||
</project>
|
||||
</projectlist>
|
||||
|
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@ -15,9 +15,17 @@ on:
|
||||
- cron: '0 4 1 * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
# read to fetch code (actions/checkout)
|
||||
# write to push code to gh-pages, create releases
|
||||
# note: forked repositories will have maximum read access
|
||||
contents: write
|
||||
continue-on-error: false
|
||||
strategy:
|
||||
matrix:
|
||||
|
3
.github/workflows/git-repo-sync.yml
vendored
3
.github/workflows/git-repo-sync.yml
vendored
@ -10,6 +10,9 @@ on:
|
||||
- '**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
29
Gemfile.lock
29
Gemfile.lock
@ -1,8 +1,8 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
addressable (2.8.1)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
claide (1.1.0)
|
||||
claide-plugins (0.9.2)
|
||||
cork
|
||||
@ -12,7 +12,7 @@ GEM
|
||||
concurrent-ruby (1.1.10)
|
||||
cork (0.3.0)
|
||||
colored2 (~> 3.1)
|
||||
danger (8.6.1)
|
||||
danger (9.0.0)
|
||||
claide (~> 1.0)
|
||||
claide-plugins (>= 0.9.2)
|
||||
colored2 (~> 3.1)
|
||||
@ -23,12 +23,12 @@ GEM
|
||||
kramdown (~> 2.3)
|
||||
kramdown-parser-gfm (~> 1.0)
|
||||
no_proxy_fix
|
||||
octokit (~> 4.7)
|
||||
octokit (~> 5.0)
|
||||
terminal-table (>= 1, < 4)
|
||||
differ (0.1.2)
|
||||
et-orbi (1.2.7)
|
||||
tzinfo
|
||||
faraday (1.10.0)
|
||||
faraday (1.10.2)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
@ -43,7 +43,7 @@ GEM
|
||||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-http-cache (2.4.0)
|
||||
faraday-http-cache (2.4.1)
|
||||
faraday (>= 0.8)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.0.4)
|
||||
@ -53,25 +53,26 @@ GEM
|
||||
faraday-patron (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.3)
|
||||
fugit (1.5.3)
|
||||
fugit (1.7.1)
|
||||
et-orbi (~> 1, >= 1.2.7)
|
||||
raabro (~> 1.4)
|
||||
git (1.11.0)
|
||||
git (1.12.0)
|
||||
addressable (~> 2.8)
|
||||
rchardet (~> 1.8)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (5.3.0)
|
||||
liquid (5.4.0)
|
||||
logger-colors (1.0.0)
|
||||
mini_portile2 (2.8.0)
|
||||
multipart-post (2.2.3)
|
||||
nap (1.1.0)
|
||||
no_proxy_fix (0.1.2)
|
||||
nokogiri (1.13.7)
|
||||
nokogiri (1.13.8)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
octokit (4.25.1)
|
||||
octokit (5.6.1)
|
||||
faraday (>= 1, < 3)
|
||||
sawyer (~> 0.9)
|
||||
open4 (1.3.4)
|
||||
@ -82,12 +83,12 @@ GEM
|
||||
nokogiri (~> 1.13)
|
||||
rufus-scheduler (~> 3.8)
|
||||
slop (~> 4.6)
|
||||
public_suffix (4.0.7)
|
||||
public_suffix (5.0.0)
|
||||
raabro (1.4.0)
|
||||
racc (1.6.0)
|
||||
rchardet (1.8.0)
|
||||
rexml (3.2.5)
|
||||
rouge (3.29.0)
|
||||
rouge (4.0.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
rufus-scheduler (3.8.2)
|
||||
fugit (~> 1.1, >= 1.1.6)
|
||||
@ -100,7 +101,7 @@ GEM
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
tzinfo (2.0.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (2.2.0)
|
||||
unicode-display_width (2.3.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
@ -116,7 +116,7 @@ echo "* Days since last release: $(( ( $(date +%s) - $(git log --max-count=1 --f
|
||||
)
|
||||
|
||||
TEMP_RELEASE_NOTES=$(cat docs/pages/release_notes.md)
|
||||
TEMP_RELEASE_NOTES=${TEMP_RELEASE_NOTES/\{\% endtocmaker \%\}/$STATS$'\n'$'\n'\{\% endtocmaker \%\}$'\n'}
|
||||
TEMP_RELEASE_NOTES=${TEMP_RELEASE_NOTES/\{\% endtocmaker \%\}/${STATS//\&/\\\&}$'\n'$'\n'\{\% endtocmaker \%\}$'\n'}
|
||||
echo "${TEMP_RELEASE_NOTES}" > docs/pages/release_notes.md
|
||||
|
||||
echo
|
||||
|
@ -1,20 +1,20 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (6.0.5.1)
|
||||
activesupport (6.0.6)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
zeitwerk (~> 2.2, >= 2.2.2)
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
addressable (2.8.1)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.11.1)
|
||||
colorator (1.1.0)
|
||||
commonmarker (0.23.5)
|
||||
commonmarker (0.23.6)
|
||||
concurrent-ruby (1.1.10)
|
||||
dnsruby (1.61.9)
|
||||
simpleidn (~> 0.1)
|
||||
@ -25,10 +25,10 @@ GEM
|
||||
ffi (>= 1.15.0)
|
||||
eventmachine (1.2.7)
|
||||
execjs (2.8.1)
|
||||
faraday (2.3.0)
|
||||
faraday-net_http (~> 2.0)
|
||||
faraday (2.5.2)
|
||||
faraday-net_http (>= 2.0, < 3.1)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-net_http (2.0.3)
|
||||
faraday-net_http (3.0.0)
|
||||
ffi (1.15.5)
|
||||
forwardable-extended (2.6.0)
|
||||
gemoji (3.0.1)
|
||||
@ -211,8 +211,8 @@ GEM
|
||||
jekyll (>= 3.5, < 5.0)
|
||||
jekyll-feed (~> 0.9)
|
||||
jekyll-seo-tag (~> 2.1)
|
||||
minitest (5.16.2)
|
||||
nokogiri (1.13.7)
|
||||
minitest (5.16.3)
|
||||
nokogiri (1.13.8)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
octokit (4.25.1)
|
||||
@ -222,7 +222,7 @@ GEM
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (4.0.7)
|
||||
racc (1.6.0)
|
||||
rb-fsevent (0.11.1)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.2.5)
|
||||
|
@ -2,7 +2,7 @@ repository: pmd/pmd
|
||||
|
||||
pmd:
|
||||
version: 7.0.0-SNAPSHOT
|
||||
previous_version: 6.49.0
|
||||
previous_version: 6.50.0
|
||||
date: ??-?????-2022
|
||||
release_type: major
|
||||
|
||||
|
@ -58,6 +58,9 @@ entries:
|
||||
- title: PMD Report formats
|
||||
url: /pmd_userdocs_report_formats.html
|
||||
output: web, pdf
|
||||
- title: 3rd party rulesets
|
||||
output: web, pdf
|
||||
url: /pmd_userdocs_3rdpartyrulesets.html
|
||||
- title: null
|
||||
output: web, pdf
|
||||
subfolders:
|
||||
@ -502,6 +505,9 @@ entries:
|
||||
- title: Old release notes
|
||||
url: /pmd_release_notes_old.html
|
||||
output: web, pdf
|
||||
- title: Decisions
|
||||
url: /pmd_projectdocs_decisions.html
|
||||
output: web, pdf
|
||||
- title: null
|
||||
output: web, pdf
|
||||
subfolders:
|
||||
|
@ -246,6 +246,12 @@ the breaking API changes will be performed in 7.0.0.
|
||||
an API is tagged as `@Deprecated` or not in the latest minor release. During the development of 7.0.0,
|
||||
we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %}
|
||||
|
||||
#### 6.50.0
|
||||
|
||||
##### CPD CLI
|
||||
|
||||
* CPD now supports the `--ignore-literal-sequences` argument when analyzing Lua code.
|
||||
|
||||
#### 6.49.0
|
||||
|
||||
##### Deprecated API
|
||||
|
File diff suppressed because it is too large
Load Diff
14
docs/pages/pmd/projectdocs/decisions.md
Normal file
14
docs/pages/pmd/projectdocs/decisions.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
title: Architecture Decisions
|
||||
sidebar: pmd_sidebar
|
||||
permalink: pmd_projectdocs_decisions.html
|
||||
last_updated: July 2022
|
||||
---
|
||||
|
||||
<ul>
|
||||
{% for page in site.pages %}
|
||||
{% if page.adr == true and page.adr_status != "" %}
|
||||
<li><a href="{{ page.url }}">{{ page.title }}</a> ({{ page.adr_status }})</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
70
docs/pages/pmd/projectdocs/decisions/adr-1.md
Normal file
70
docs/pages/pmd/projectdocs/decisions/adr-1.md
Normal file
@ -0,0 +1,70 @@
|
||||
---
|
||||
title: ADR 1 - Use architecture decision records
|
||||
sidebar: pmd_sidebar
|
||||
permalink: pmd_projectdocs_decisions_adr_1.html
|
||||
sidebaractiveurl: /pmd_projectdocs_decisions.html
|
||||
adr: true
|
||||
# Proposed / Accepted / Deprecated / Superseded
|
||||
adr_status: "Accepted"
|
||||
last_updated: September 2022
|
||||
---
|
||||
|
||||
# Context
|
||||
|
||||
PMD has grown over 20 years as an open-source project. Along the way many decisions have been made, but they are not
|
||||
explicitly documented. PMD is also developed by many individuals and the original developers might
|
||||
not even be around anymore.
|
||||
|
||||
Without having documentation records about decisions it is hard for new developers to understand the reasons
|
||||
of past decisions. This might lead to either ignore these past (unknown) decisions and change it without
|
||||
fully understanding its consequences. This could create new issues down the road, e.g. a decision supporting
|
||||
a requirement that is not tested.
|
||||
|
||||
On the other hand, accepting the past decisions without challenging it might slow down the project and
|
||||
possible innovations. It could lead to a situation where the developers are afraid to change anything
|
||||
in order to not break the system.
|
||||
|
||||
Past decisions have been made within context and the context can change. Therefore, past decisions can still be
|
||||
valid today, or they don't apply anymore. In that case, the decision should be revisited.
|
||||
|
||||
See also the blog post [Documenting Architecture Decisions](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions)
|
||||
by Michael Nygard.
|
||||
|
||||
There are many templates around to choose from. <https://github.com/joelparkerhenderson/architecture-decision-record>
|
||||
gives a nice summary. The page <https://adr.github.io/> gives a good overview on ADR and for adr-related tooling.
|
||||
|
||||
# Decision
|
||||
|
||||
We will document the decisions we make as a project as a collection of "Architecture Decision Records".
|
||||
In order to keep it simple, we will use only a simple template proposed by Michael Nygard.
|
||||
The documents are stored together with the source code and are part of the generated documentation site.
|
||||
|
||||
A new ADR should be proposed with a pull request to open the discussion.
|
||||
The initial status of the new ADR is "Proposed". When maintainer consensus is reached during the PR
|
||||
review, then the status is changed to "Accepted" when the PR is merged.
|
||||
A new entry in the "Change History" section should be added, when the PR is merged.
|
||||
|
||||
In order to propose a change to an existing ADR a new pull request should be opened which modifies the ADR.
|
||||
The change can be to amend the ADR or to challenge it and maybe deprecate it. A new entry in the
|
||||
"Change History" section should be added to summary the change. When maintainer consensus is reached
|
||||
during the PR review, then the PR can be merged and the ADR is updated.
|
||||
|
||||
# Status
|
||||
|
||||
{{ page.adr_status }} (Last updated: {{ page.last_updated }})
|
||||
|
||||
# Consequences
|
||||
|
||||
Explicitly documenting decisions has the benefit that new developers joining the projects know about the decisions
|
||||
and can read the context and consequences of the decisions. This will likely also improve the overall quality
|
||||
as the decisions need to be formulated and written down. Everybody is on the same page.
|
||||
|
||||
However, this also adds additional tasks, and it takes time to write down and document the decisions.
|
||||
|
||||
# Change History
|
||||
|
||||
2022-09-30: Status changed to "Accepted".
|
||||
|
||||
2022-09-06: Added section "Change History" to the template. Added "Last updated" to "Status" section.
|
||||
|
||||
2022-07-28: Proposed initial version.
|
71
docs/pages/pmd/projectdocs/decisions/adr-2.md
Normal file
71
docs/pages/pmd/projectdocs/decisions/adr-2.md
Normal file
@ -0,0 +1,71 @@
|
||||
---
|
||||
title: ADR 2 - Policy on the use of Kotlin for development
|
||||
sidebar: pmd_sidebar
|
||||
permalink: pmd_projectdocs_decisions_adr_2.html
|
||||
sidebaractiveurl: /pmd_projectdocs_decisions.html
|
||||
adr: true
|
||||
# Proposed / Accepted / Deprecated / Superseded
|
||||
adr_status: "Accepted"
|
||||
last_updated: September 2022
|
||||
---
|
||||
|
||||
# Context
|
||||
|
||||
We currently use Kotlin only for unit tests at some places (e.g. pmd-lang-test module provides a couple of base
|
||||
test classes). We were cautious to expand Kotlin because of poor development support outside JetBrain's
|
||||
IntelliJ IDEA. E.g. the [Kotlin Plugin for Eclipse](https://marketplace.eclipse.org/content/kotlin-plugin-eclipse)
|
||||
doesn't work properly as described in the reviews.
|
||||
|
||||
For VS Code there is a [Kotlin Plugin](https://marketplace.visualstudio.com/items?itemName=mathiasfrohlich.Kotlin)
|
||||
with basic features. Online IDEs like gitpod.io and GitHub Codespaces are often based on VS Code.
|
||||
|
||||
Using Kotlin means, that we accept, that PMD can only be developed with IntelliJ IDEA. This feels like a vendor lock-in.
|
||||
|
||||
Also, bringing in a mix of languages might make maintenance a bit harder and make it harder for new contributors.
|
||||
However - PMD is a tool that deals with many, many languages anyway, so this is maybe not a real argument.
|
||||
|
||||
Nevertheless, extending the usage of Kotlin within PMD can also increase contributions.
|
||||
|
||||
# Decision
|
||||
|
||||
We are generally open to the idea to increase usage of Kotlin within PMD. In order to gain experience
|
||||
and to keep it within bounds and therefore maintainable we came up with the following rules:
|
||||
|
||||
* The module `pmd-core` should stay in plain Java. This helps in keeping binary compatibility when changing sources.
|
||||
`pmd-core` contains the main APIs for all language modules. We currently release all modules at the same time,
|
||||
so this is not a real problem for now. But that might change in the future: Because only few language modules have
|
||||
actual changes per release, it doesn't really make sense to release everything as long as the modules stay
|
||||
compatible. But that's another story.
|
||||
* For (unit) testing, Kotlin can be used in `pmd-core` and in the language modules. The test frameworks can also
|
||||
use Kotlin (`pmd-test` doesn't yet, `pmd-lang-test` does already).
|
||||
* Additionally: from now on, we allow to have the individual language modules be implemented in different languages
|
||||
when it makes sense. So, a language module might decide to use plain Java (like now) or also Kotlin.
|
||||
* When mixing languages (e.g. Java + Kotlin), we need to care that the modules can still be used with plain Java.
|
||||
E.g. when writing custom rules: `pmd-java` provides a couple of APIs for rules (like symbol table, type resolution)
|
||||
and we should not force the users to use Kotlin (at least not for language modules which already exist and
|
||||
for which users might have written custom rules in Java already).
|
||||
* It is also possible to write the entire language module in Kotlin only. Then the rules would be written in Kotlin
|
||||
as well. And the possible problems when mixing languages are gone. But that applies only for new language modules.
|
||||
* When refactoring an existing language module from Java only to introduce Kotlin, care needs to be taken to
|
||||
not make incompatible changes. If compatibility (binary or source) can't be maintained, then that would be a
|
||||
major version change.
|
||||
|
||||
# Status
|
||||
|
||||
{{ page.adr_status }} (Last updated: {{ page.last_updated }})
|
||||
|
||||
# Consequences
|
||||
|
||||
Allowing more Kotlin in PMD can attract new contributions. It might make it easier to develop small DSLs.
|
||||
In the future we might also consider to use other languages than Kotlin, e.g. for `pmd-scala` Scala might make sense.
|
||||
|
||||
On the other side, other IDEs than IntelliJ IDEA will have a difficult time to deal with PMD's source code
|
||||
when Kotlin is used. Eclipse can't be used practically anymore.
|
||||
|
||||
Maintaining a polyglot code base with multiple languages is likely to be more challenging.
|
||||
|
||||
# Change History
|
||||
|
||||
2022-09-30: Changed status to "Accepted".
|
||||
|
||||
2022-07-28: Proposed initial version.
|
34
docs/pages/pmd/projectdocs/decisions/adr-NNN.md
Normal file
34
docs/pages/pmd/projectdocs/decisions/adr-NNN.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
title: ADR NNN - Template
|
||||
sidebar: pmd_sidebar
|
||||
permalink: pmd_projectdocs_decisions_adr_NNN.html
|
||||
sidebaractiveurl: /pmd_projectdocs_decisions.html
|
||||
adr: true
|
||||
# Proposed / Accepted / Deprecated / Superseded
|
||||
adr_status: ""
|
||||
last_updated: July 2022
|
||||
---
|
||||
|
||||
<!-- https://github.com/joelparkerhenderson/architecture-decision-record/blob/main/templates/decision-record-template-by-michael-nygard/index.md -->
|
||||
|
||||
# Context
|
||||
|
||||
What is the issue that we're seeing that is motivating this decision or change?
|
||||
|
||||
# Decision
|
||||
|
||||
What is the change that we're proposing and/or doing?
|
||||
|
||||
# Status
|
||||
|
||||
{{ page.adr_status }} (Last updated: {{ page.last_updated }})
|
||||
|
||||
# Consequences
|
||||
|
||||
What becomes easier or more difficult to do because of this change?
|
||||
|
||||
# Change History
|
||||
|
||||
YYYY-MM-DD: Add xyz.
|
||||
|
||||
YYYY-MM-DD: Proposed initial version.
|
@ -9,26 +9,43 @@ author: Tom Copeland <tom@infoether.org>
|
||||
|
||||
### Salesforce / Apex Language Module
|
||||
|
||||
* October 2020 - [Salesforce CLI Scanner Custom XPath Rules - Part 1](https://bobbuzzard.blogspot.com/2020/10/salesforce-cli-scanner-custom-xpath.html),
|
||||
[Salesforce CLI Scanner Custom XPath Rules - Part 2](http://bobbuzzard.blogspot.com/2020/10/salesforce-cli-scanner-custom-xpath_11.html)
|
||||
by [Keir Bowden](https://twitter.com/bob_buzzard)
|
||||
|
||||
* March 2020 - [Helping Salesforce developers create readable and maintainable Apex code](https://gearset.com/blog/helping-sf-developers-create-readable-and-maintainable-apex-code)
|
||||
|
||||
* July 2019 - [Apex PMD \| Static code analysis - Apex Hours](https://youtu.be/34PxAHtAavU)
|
||||
|
||||
* June 2019 - [Pluralsight](https://www.pluralsight.com/authors/don-robins) Course about leveraging PMD usage for Salesforce by [Robert Sösemann](https://github.com/rsoesemann) (Apex Language Module Contributor) [Play by Play: Automated Code Analysis in Salesforce - a Tools Deep-Dive](https://www.pluralsight.com/courses/play-by-play-automated-code-analysis-in-salesforce)
|
||||
* June 2019 - [Pluralsight](https://www.pluralsight.com/authors/don-robins) Course about leveraging PMD usage for
|
||||
Salesforce by [Robert Sösemann](https://github.com/rsoesemann) (Apex Language Module Contributor)
|
||||
[Play by Play: Automated Code Analysis in Salesforce - a Tools Deep-Dive](https://www.pluralsight.com/courses/play-by-play-automated-code-analysis-in-salesforce)
|
||||
|
||||
* June 2018 - [Salesforce Way Podcast](https://salesforceway.com/podcast/podcast/) with [Robert Sösemann](https://github.com/rsoesemann) [Static Code Analysis with PMD for Apex](https://salesforceway.com/podcast/podcast/static-code-analysis-with-pmd-for-apex/)
|
||||
* June 2018 - [Salesforce Way Podcast](https://salesforceway.com/podcast/podcast/) with
|
||||
[Robert Sösemann](https://github.com/rsoesemann) [Static Code Analysis with PMD for Apex](https://salesforceway.com/podcast/podcast/static-code-analysis-with-pmd-for-apex/)
|
||||
|
||||
* January 2018 - [Webinar: How to contribute Apex rules to PMD with Robert Sösemann](https://www.youtube.com/watch?v=7_Ex9WWS_3Q)
|
||||
* January 2018 - [Webinar: How to contribute Apex rules to PMD with Robert Sösemann](https://www.youtube.com/watch?v=7_Ex9WWS_3Q)
|
||||
|
||||
* August 2017 - Webinar about how to use PMD with The Welkin Suite Salesforce IDE - Author [Robert Sösemann](https://github.com/rsoesemann) - [Improving your Apex Code Quality with PMD in The Welkin Suite](https://www.youtube.com/watch?v=Ypyiy5b6huc)
|
||||
* August 2017 - Webinar about how to use PMD with The Welkin Suite Salesforce IDE - Author
|
||||
[Robert Sösemann](https://github.com/rsoesemann) - [Improving your Apex Code Quality with PMD in The Welkin Suite](https://www.youtube.com/watch?v=Ypyiy5b6huc)
|
||||
|
||||
* November 2016 - Recording of [Robert Sösemann](https://github.com/rsoesemann)'s Session at Salesforce Dreamforce Conference about enforcing Clean Code in the Salesforce world using PMD and other tools [Clean Apex Code with Automatic Code Metrics](https://www.youtube.com/watch?v=bW7m6y6bEug)
|
||||
* November 2016 - Recording of [Robert Sösemann](https://github.com/rsoesemann)'s Session at Salesforce Dreamforce
|
||||
Conference about enforcing Clean Code in the Salesforce world using PMD and other tools
|
||||
[Clean Apex Code with Automatic Code Metrics](https://www.youtube.com/watch?v=bW7m6y6bEug)
|
||||
|
||||
|
||||
### PMD in general and other Language Modules
|
||||
|
||||
* February 2021 - Artem Krosheninnikov's talk about Quality Assurance Automation: [Artem Krosheninnikov, Wrike - How static analysis can help in QAA processes](https://www.youtube.com/watch?v=L42zH5ne074)
|
||||
* February 2021 - Artem Krosheninnikov's talk about Quality Assurance Automation:
|
||||
[Artem Krosheninnikov, Wrike - How static analysis can help in QAA processes](
|
||||
https://www.youtube.com/watch?v=L42zH5ne074)
|
||||
|
||||
* May 2019 - [Code quality assurance with PMD – An extensible static code analyser for Java and other languages](https://www.datarespons.com/code-quality-assurance-with-pmd/)
|
||||
* December 2020 - Jeroen Borgers' talk about finding performance bugs with PMD:
|
||||
[J-Fall Virtual 2020: Jeroen Borgers - Fixing your performance and concurrency bugs before they bite you](
|
||||
https://www.youtube.com/watch?v=Z_sT38KTRNk)
|
||||
|
||||
* May 2019 - [Code quality assurance with PMD – An extensible static code analyser for Java and other languages](
|
||||
https://www.datarespons.com/code-quality-assurance-with-pmd/)
|
||||
|
||||
* February 2012 - Romain Pelisse's lightning talk at FOSDEM 2012 about "PMD5: What can it do for you?".
|
||||
[Video recording is available](http://video.fosdem.org/2012/lightningtalks/PMD5.webm).
|
||||
|
27
docs/pages/pmd/userdocs/3rdpartyrulesets.md
Normal file
27
docs/pages/pmd/userdocs/3rdpartyrulesets.md
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
title: 3rd party rulesets
|
||||
tags: [rule_references, userdocs]
|
||||
summary: Lists rulesets and rules from the community
|
||||
permalink: pmd_userdocs_3rdpartyrulesets.html
|
||||
last_updated: September 2022
|
||||
---
|
||||
|
||||
## For Java
|
||||
|
||||
* **jPinpoint rules:** PMD rule set for performance aware Java and Kotlin coding.
|
||||
* <https://github.com/jborgers/PMD-jPinpoint-rules>
|
||||
* **arch4u-pmd** is a library with pmd rules that bring new regulations related to known problems in REST API, logging,
|
||||
monitoring, etc., including reconfigured default pmd rules to decrease false-positive violations during usage of
|
||||
well-known frameworks like Spring, Quarkus, etc.
|
||||
* <https://github.com/dgroup/arch4u-pmd>
|
||||
* Sample ruleset from **maxdocs**, a multi markup wiki engine.
|
||||
* <https://github.com/bohni/maxdocs/blob/master/src/main/config/pmd/pmd-ruleset.xml>
|
||||
* Sample ruleset from **geotools**, an open source Java library that provides tools for geospatial data.
|
||||
* <https://github.com/geotools/geotools/blob/main/build/qa/pmd-ruleset.xml>
|
||||
* <https://github.com/geotools/geotools/blob/main/build/qa/pmd-junit-ruleset.xml>
|
||||
|
||||
|
||||
## For Apex
|
||||
* **unhappy-soup**, a repository with problematic Salesforce code to showcase PMD, the SFDX Scanner CLI
|
||||
* <https://github.com/rsoesemann/unhappy-soup/blob/master/ruleset.xml>
|
||||
|
@ -122,7 +122,7 @@ Novice as much as advanced readers may want to [read on on Refactoring Guru](htt
|
||||
{% include custom/cli_option_row.html options="--ignore-literal-sequences"
|
||||
description="Ignore sequences of literals (common e.g. in list initializers)"
|
||||
default="false"
|
||||
languages="C#, C++"
|
||||
languages="C#, C++, Lua"
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--ignore-usings"
|
||||
description="Ignore `using` directives in C# when comparing text"
|
||||
|
@ -5,6 +5,98 @@ permalink: pmd_release_notes_old.html
|
||||
|
||||
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
|
||||
|
||||
|
||||
## 30-September-2022 - 6.50.0
|
||||
|
||||
The PMD team is pleased to announce PMD 6.50.0.
|
||||
|
||||
This is a minor release.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
* [New and noteworthy](#new-and-noteworthy)
|
||||
* [Lua now supports additionally Luau](#lua-now-supports-additionally-luau)
|
||||
* [Modified rules](#modified-rules)
|
||||
* [Fixed Issues](#fixed-issues)
|
||||
* [API Changes](#api-changes)
|
||||
* [CPD CLI](#cpd-cli)
|
||||
* [Financial Contributions](#financial-contributions)
|
||||
* [External Contributions](#external-contributions)
|
||||
* [Stats](#stats)
|
||||
|
||||
### New and noteworthy
|
||||
|
||||
#### Lua now supports additionally Luau
|
||||
|
||||
This release of PMD adds support for [Luau](https://github.com/Roblox/luau), a gradually typed language derived
|
||||
from Lua. This means, that the Lua language in PMD can now parse both Lua and Luau.
|
||||
|
||||
#### Modified rules
|
||||
|
||||
* The Java rule [`UnusedPrivateField`](https://pmd.github.io/pmd-6.50.0/pmd_rules_java_bestpractices.html#unusedprivatefield) now ignores private fields, if the fields are
|
||||
annotated with any annotation or the enclosing class has any annotation. Annotations often enable a
|
||||
framework (such as dependency injection, mocking or e.g. Lombok) which use the fields by reflection or other
|
||||
means. This usage can't be detected by static code analysis. Previously these frameworks where explicitly allowed
|
||||
by listing their annotations in the property "ignoredAnnotations", but that turned out to be prone of false
|
||||
positive for any not explicitly considered framework. That's why the property "ignoredAnnotations" has been
|
||||
deprecated for this rule.
|
||||
* The Java rule [`CommentDefaultAccessModifier`](https://pmd.github.io/pmd-6.50.0/pmd_rules_java_codestyle.html#commentdefaultaccessmodifier) now by default ignores JUnit5 annotated
|
||||
methods. This behavior can be customized using the property `ignoredAnnotations`.
|
||||
|
||||
### Fixed Issues
|
||||
* cli
|
||||
* [#4118](https://github.com/pmd/pmd/issues/4118): \[cli] run.sh designer reports "integer expression expected"
|
||||
* core
|
||||
* [#4116](https://github.com/pmd/pmd/pull/4116): \[core] Missing --file arg in TreeExport CLI example
|
||||
* doc
|
||||
* [#4072](https://github.com/pmd/pmd/pull/4072): \[doc] Add architecture decision records
|
||||
* [#4109](https://github.com/pmd/pmd/pull/4109): \[doc] Add page for 3rd party rulesets
|
||||
* [#4124](https://github.com/pmd/pmd/pull/4124): \[doc] Fix typos in Java rule docs
|
||||
* java
|
||||
* [#3431](https://github.com/pmd/pmd/issues/3431): \[java] Add sample java project to regression-tester which uses new language constructs
|
||||
* java-bestpractices
|
||||
* [#4033](https://github.com/pmd/pmd/issues/4033): \[java] UnusedPrivateField - false positive with Lombok @ToString.Include
|
||||
* [#4037](https://github.com/pmd/pmd/issues/4037): \[java] UnusedPrivateField - false positive with Spring @SpyBean
|
||||
* java-codestyle
|
||||
* [#3859](https://github.com/pmd/pmd/issues/3859): \[java] CommentDefaultAccessModifier is triggered in JUnit5 test class
|
||||
* [#4085](https://github.com/pmd/pmd/issues/4085): \[java] UnnecessaryFullyQualifiedName false positive when nested and non-nested classes with the same name and in the same package are used together
|
||||
* [#4133](https://github.com/pmd/pmd/issues/4133): \[java] UnnecessaryFullyQualifiedName - FP for inner class pkg.ClassA.Foo implementing pkg.Foo
|
||||
* java-design
|
||||
* [#4090](https://github.com/pmd/pmd/issues/4090): \[java] FinalFieldCouldBeStatic false positive with non-static synchronized block (regression in 6.48, worked with 6.47)
|
||||
* java-errorprone
|
||||
* [#1718](https://github.com/pmd/pmd/issues/1718): \[java] ConstructorCallsOverridableMethod false positive when calling super method
|
||||
* [#2348](https://github.com/pmd/pmd/issues/2348): \[java] ConstructorCallsOverridableMethod occurs when unused overloaded method is defined
|
||||
* [#4099](https://github.com/pmd/pmd/issues/4099): \[java] ConstructorCallsOverridableMethod should consider method calls with var access
|
||||
* scala
|
||||
* [#4138](https://github.com/pmd/pmd/pull/4138): \[scala] Upgrade scala-library to 2.12.7 / 2.13.9 and scalameta to 4.6.0
|
||||
|
||||
### API Changes
|
||||
|
||||
#### CPD CLI
|
||||
|
||||
* CPD now supports the `--ignore-literal-sequences` argument when analyzing Lua code.
|
||||
|
||||
### Financial Contributions
|
||||
|
||||
Many thanks to our sponsors:
|
||||
|
||||
* [Oliver Siegmar](https://github.com/osiegmar) (@osiegmar)
|
||||
|
||||
### External Contributions
|
||||
* [#4066](https://github.com/pmd/pmd/pull/4066): \[lua] Add support for Luau syntax and skipping literal sequences in CPD - [Matt Hargett](https://github.com/matthargett) (@matthargett)
|
||||
* [#4100](https://github.com/pmd/pmd/pull/4100): \[java] Update UnusedPrivateFieldRule - ignore any annotations - [Lynn](https://github.com/LynnBroe) (@LynnBroe)
|
||||
* [#4116](https://github.com/pmd/pmd/pull/4116): \[core] Fix missing --file arg in TreeExport CLI example - [mohan-chinnappan-n](https://github.com/mohan-chinnappan-n) (@mohan-chinnappan-n)
|
||||
* [#4124](https://github.com/pmd/pmd/pull/4124): \[doc] Fix typos in Java rule docs - [Piotrek Żygieło](https://github.com/pzygielo) (@pzygielo)
|
||||
* [#4128](https://github.com/pmd/pmd/pull/4128): \[java] Fix False-positive UnnecessaryFullyQualifiedName when nested and non-nest… #4103 - [Oleg Andreych](https://github.com/OlegAndreych) (@OlegAndreych)
|
||||
* [#4130](https://github.com/pmd/pmd/pull/4130): \[ci] GitHub Workflows security hardening - [Alex](https://github.com/sashashura) (@sashashura)
|
||||
* [#4131](https://github.com/pmd/pmd/pull/4131): \[doc] TooFewBranchesForASwitchStatement - Use "if-else" instead of "if-then" - [Suvashri](https://github.com/Suvashri) (@Suvashri)
|
||||
* [#4137](https://github.com/pmd/pmd/pull/4137): \[java] Fixes 3859: Exclude junit5 test methods from the commentDefaultAccessModifierRule - [Luis Alcantar](https://github.com/lfalcantar) (@lfalcantar)
|
||||
|
||||
### Stats
|
||||
* 100 commits
|
||||
* 26 closed tickets & PRs
|
||||
* Days since last release: 29
|
||||
|
||||
## 31-August-2022 - 6.49.0
|
||||
|
||||
The PMD team is pleased to announce PMD 6.49.0.
|
||||
|
@ -142,7 +142,7 @@ public class TreeExportCli {
|
||||
sb.append(System.lineSeparator())
|
||||
.append(System.lineSeparator());
|
||||
|
||||
sb.append("Example: ast-dump --format xml --language java MyFile.java")
|
||||
sb.append("Example: ast-dump --format xml --language java --file MyFile.java")
|
||||
.append(System.lineSeparator());
|
||||
|
||||
System.err.print(sb);
|
||||
|
@ -4,35 +4,41 @@ set OPTS=
|
||||
set MAIN_CLASS=net.sourceforge.pmd.util.fxdesigner.DesignerStarter
|
||||
|
||||
|
||||
:: sets the jver variable to the java version, eg 901 for 9.0.1+x or 180 for 1.8.0_171-b11
|
||||
:: sets the jver variable to the java version, eg 90 for 9.0.1+x or 80 for 1.8.0_171-b11 or 110 for 11.0.6.1
|
||||
:: sets the jvendor variable to either java (oracle) or openjdk
|
||||
for /f tokens^=1^,3^,4^,5^ delims^=.-_+^"^ %%j in ('java -version 2^>^&1 ^| find "version"') do (
|
||||
set jvendor=%%j
|
||||
if %%l EQU ea (
|
||||
set /A "jver=%%k00"
|
||||
set /A "jver=%%k0"
|
||||
) else (
|
||||
set /A jver=%%k%%l%%m
|
||||
if %%k EQU 1 (
|
||||
:: for java version 1.7.x, 1.8.x, ignore the first 1.
|
||||
set /A "jver=%%l%%m"
|
||||
) else (
|
||||
set /A "jver=%%k%%l"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Set "jreopts="
|
||||
:: oracle java 9 and 10 has javafx included as a module
|
||||
if /I "%jvendor%" EQU "java" (
|
||||
if %jver% GEQ 900 (
|
||||
if %jver% LSS 1100 (
|
||||
if /I %jvendor% == java (
|
||||
if %jver% GEQ 90 (
|
||||
if %jver% LSS 110 (
|
||||
:: enable reflection
|
||||
Set jreopts=--add-opens javafx.controls/javafx.scene.control.skin=ALL-UNNAMED
|
||||
set jreopts=--add-opens javafx.controls/javafx.scene.control.skin=ALL-UNNAMED
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
set "_needjfxlib=0"
|
||||
if /I "%jvendor%" EQU "openjdk" set _needjfxlib=1
|
||||
if /I "%jvendor%" EQU "java" (
|
||||
if %jver% GEQ 1100 set _needjfxlib=1
|
||||
if /I %jvendor% == openjdk set _needjfxlib=1
|
||||
if /I %jvendor% == java (
|
||||
if %jver% GEQ 110 set _needjfxlib=1
|
||||
)
|
||||
if %_needjfxlib% EQU 1 (
|
||||
if %jver% LSS 1000 (
|
||||
if %jver% LSS 100 (
|
||||
echo For openjfx at least java 10 is required.
|
||||
pause
|
||||
exit
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
usage() {
|
||||
echo "Usage:"
|
||||
echo " $(basename $0) <application-name> [-h|-v] ..."
|
||||
echo " $(basename "$0") <application-name> [-h|-v] ..."
|
||||
echo ""
|
||||
echo "application-name: valid options are: $(valid_app_options)"
|
||||
echo "-h print this help"
|
||||
@ -60,9 +60,9 @@ java_heapsize_settings() {
|
||||
|
||||
|
||||
set_lib_dir() {
|
||||
if [ -z ${LIB_DIR} ]; then
|
||||
if [ -z "${LIB_DIR}" ]; then
|
||||
# Allow for symlinks to this script
|
||||
if [ -L $0 ]; then
|
||||
if [ -L "$0" ]; then
|
||||
local script_real_loc=$(readlink "$0")
|
||||
else
|
||||
local script_real_loc=$0
|
||||
@ -104,23 +104,25 @@ check_conf_dir() {
|
||||
}
|
||||
|
||||
function script_exit() {
|
||||
echo $1 >&2
|
||||
echo "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
determine_java_version() {
|
||||
local full_ver=$(java -version 2>&1)
|
||||
# java_ver is eg "18" for java 1.8, "90" for java 9.0, "100" for java 10.0.x
|
||||
readonly java_ver=$(echo $full_ver | sed -n '{
|
||||
# java_ver is eg "80" for java 1.8, "90" for java 9.0, "100" for java 10.0.x
|
||||
readonly java_ver=$(echo "$full_ver" | sed -n '{
|
||||
# replace early access versions, e.g. 11-ea with 11.0.0
|
||||
s/-ea/.0.0/
|
||||
# replace versions such as 10 with 10.0.0
|
||||
s/version "\([0-9]\{1,\}\)"/version "\1.0.0"/
|
||||
# replace old java versions 1.x.* (java 1.7, java 1.8) with x.*
|
||||
s/version "1\.\(.*\)"/version "\1"/
|
||||
# extract the major and minor parts of the version
|
||||
s/^.* version "\(.*\)\.\(.*\)\..*".*$/\1\2/p
|
||||
s/^.* version "\([0-9]\{1,\}\)\.\([0-9]\{1,\}\).*".*$/\1\2/p
|
||||
}')
|
||||
# java_vendor is either java (oracle) or openjdk
|
||||
readonly java_vendor=$(echo $full_ver | sed -n -e 's/^\(.*\) version .*$/\1/p')
|
||||
readonly java_vendor=$(echo "$full_ver" | sed -n -e 's/^\(.*\) version .*$/\1/p')
|
||||
}
|
||||
|
||||
jre_specific_vm_options() {
|
||||
@ -212,7 +214,7 @@ case "${APPNAME}" in
|
||||
readonly CLASSNAME="net.sourceforge.pmd.util.treeexport.TreeExportCli"
|
||||
;;
|
||||
*)
|
||||
echo "${APPNAME} is NOT a valid application name, valid options are:$(valid_app_options)"
|
||||
echo "${APPNAME} is NOT a valid application name, valid options are: $(valid_app_options)"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
103
pmd-dist/src/test/resources/scripts/designertest.bat
Normal file
103
pmd-dist/src/test/resources/scripts/designertest.bat
Normal file
@ -0,0 +1,103 @@
|
||||
@echo off
|
||||
|
||||
:: BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
|
||||
::
|
||||
:: Simple manual test script
|
||||
:: - code is copied from designer.bat to be tested here (so please check, it might be out of sync)
|
||||
:: - mostly the function "determine_java_version" is tested here
|
||||
:: - just run it with "designertest.bat" and look at the output
|
||||
:: - test cases are at the end of this script
|
||||
::
|
||||
|
||||
GOTO :main
|
||||
|
||||
:determine_java_version
|
||||
:: sets the jver variable to the java version, eg 90 for 9.0.1+x or 80 for 1.8.0_171-b11 or 110 for 11.0.6.1
|
||||
:: sets the jvendor variable to either java (oracle) or openjdk
|
||||
for /f tokens^=1^,3^,4^,5^ delims^=.-_+^"^ %%j in (%full_version%) do (
|
||||
set jvendor=%%j
|
||||
if %%l EQU ea (
|
||||
set /A "jver=%%k0"
|
||||
) else (
|
||||
if %%k EQU 1 (
|
||||
:: for java version 1.7.x, 1.8.x, ignore the first 1.
|
||||
set /A "jver=%%l%%m"
|
||||
) else (
|
||||
set /A "jver=%%k%%l"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
set detection=
|
||||
if %jver% GEQ 70 (
|
||||
if %jver% LSS 80 (
|
||||
set detection="detected java 7"
|
||||
)
|
||||
)
|
||||
if [%detection%] == [] (
|
||||
if %jver% GEQ 80 (
|
||||
if %jver% LSS 90 (
|
||||
set detection="detected java 8"
|
||||
)
|
||||
)
|
||||
)
|
||||
if [%detection%] == [] (
|
||||
if %jver% GEQ 90 (
|
||||
if %jver% LSS 110 (
|
||||
if %jvendor% == java (
|
||||
set detection="detected java 9 or 10 from oracle"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
if [%detection%] == [] (
|
||||
if %jvendor% == openjdk (
|
||||
set detection="detected java 11 from oracle or any openjdk"
|
||||
)
|
||||
)
|
||||
if [%detection%] == [] (
|
||||
if %jvendor% == java (
|
||||
if %jver% GEQ 110 (
|
||||
set detection="detected java 11 from oracle or any openjdk"
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
EXIT /B
|
||||
|
||||
|
||||
|
||||
:run_test
|
||||
set full_version=%1
|
||||
set expected_vendor=%2
|
||||
set expected_version=%3
|
||||
set expected_detection=%4
|
||||
|
||||
CALL :determine_java_version
|
||||
|
||||
echo full_version: %full_version%
|
||||
if %jver% == %expected_version% ( echo jver: %jver% [32mOK[0m ) ELSE ( echo jver: %jver% [31mEXPECTED: %expected_version% [0m )
|
||||
if %jvendor% == %expected_vendor% ( echo jvendor: %jvendor% [32mOK[0m ) ELSE ( echo jvendor: %jvendor% [31mEXPECTED: %expected_vendor% [0m )
|
||||
if [%detection%] == [%expected_detection%] ( echo detection: %detection% [32mOK[0m ) ELSE ( echo detection: %detection% [31mEXPECTED: %expected_detection% [0m )
|
||||
echo.
|
||||
|
||||
EXIT /B
|
||||
|
||||
:main
|
||||
|
||||
CALL :run_test "java version ""1.7.0_80""" java 70 "detected java 7"
|
||||
CALL :run_test "openjdk version ""1.7.0_352""" openjdk 70 "detected java 7"
|
||||
CALL :run_test "java version ""1.8.0_271""" java 80 "detected java 8"
|
||||
CALL :run_test "openjdk version ""1.8.0_345""" openjdk 80 "detected java 8"
|
||||
CALL :run_test "java version ""9.0.4""" java 90 "detected java 9 or 10 from oracle"
|
||||
CALL :run_test "openjdk version ""9.0.4""" openjdk 90 "detected java 11 from oracle or any openjdk"
|
||||
CALL :run_test "java version ""10.0.2"" 2018-07-17" java 100 "detected java 9 or 10 from oracle"
|
||||
CALL :run_test "openjdk version ""11.0.6"" 2022-08-12" openjdk 110 "detected java 11 from oracle or any openjdk"
|
||||
CALL :run_test "openjdk version ""11.0.6.1"" 2022-08-12" openjdk 110 "detected java 11 from oracle or any openjdk"
|
||||
CALL :run_test "java version ""11.0.13"" 2021-10-19 LTS" java 110 "detected java 11 from oracle or any openjdk"
|
||||
CALL :run_test "openjdk version ""17.0.4"" 2022-08-12" openjdk 170 "detected java 11 from oracle or any openjdk"
|
||||
CALL :run_test "openjdk version ""17.1.4"" 2022-08-12" openjdk 171 "detected java 11 from oracle or any openjdk"
|
||||
CALL :run_test "openjdk version ""17.0.4.1"" 2022-08-12" openjdk 170 "detected java 11 from oracle or any openjdk"
|
||||
CALL :run_test "openjdk version ""18.0.2.1"" 2022-08-18" openjdk 180 "detected java 11 from oracle or any openjdk"
|
||||
CALL :run_test "openjdk version ""19-ea"" 2022-09-20" openjdk 190 "detected java 11 from oracle or any openjdk"
|
88
pmd-dist/src/test/resources/scripts/runtest.sh
Executable file
88
pmd-dist/src/test/resources/scripts/runtest.sh
Executable file
@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
|
||||
#
|
||||
# Simple manual test script
|
||||
# - code is copied from run.sh to be tested here (so please check, it might be out of sync)
|
||||
# - mostly the function "determine_java_version" is tested here
|
||||
# - just run it with "./runtest.sh" and look at the output
|
||||
# - test cases are at the end of this script
|
||||
#
|
||||
|
||||
export LANG=en_US.UTF-8
|
||||
|
||||
FULL_JAVA_VERSION=""
|
||||
|
||||
get_full_java_version() {
|
||||
#java -version 2>&1
|
||||
#echo "openjdk version \"11.0.6\" 2022-08-12"
|
||||
echo "$FULL_JAVA_VERSION"
|
||||
}
|
||||
|
||||
determine_java_version() {
|
||||
local full_ver=$(get_full_java_version)
|
||||
# java_ver is eg "80" for java 1.8, "90" for java 9.0, "100" for java 10.0.x
|
||||
java_ver=$(echo "$full_ver" | sed -n '{
|
||||
# replace early access versions, e.g. 11-ea with 11.0.0
|
||||
s/-ea/.0.0/
|
||||
# replace versions such as 10 with 10.0.0
|
||||
s/version "\([0-9]\{1,\}\)"/version "\1.0.0"/
|
||||
# replace old java versions 1.x.* (java 1.7, java 1.8) with x.*
|
||||
s/version "1\.\(.*\)"/version "\1"/
|
||||
# extract the major and minor parts of the version
|
||||
s/^.* version "\([0-9]\{1,\}\)\.\([0-9]\{1,\}\).*".*$/\1\2/p
|
||||
}')
|
||||
# java_vendor is either java (oracle) or openjdk
|
||||
java_vendor=$(echo "$full_ver" | sed -n -e 's/^\(.*\) version .*$/\1/p')
|
||||
}
|
||||
|
||||
jre_specific_vm_options() {
|
||||
options=""
|
||||
if [ "$java_ver" -ge 70 ] && [ "$java_ver" -lt 80 ]
|
||||
then
|
||||
options="detected java 7"
|
||||
elif [ "$java_ver" -ge 80 ] && [ "$java_ver" -lt 90 ]
|
||||
then
|
||||
options="detected java 8"
|
||||
elif [ "$java_ver" -ge 90 ] && [ "$java_ver" -lt 110 ] && [ "$java_vendor" = "java" ]
|
||||
then
|
||||
options="detected java 9 or 10 from oracle"
|
||||
elif [ "$java_vendor" = "openjdk" ] || ( [ "$java_vendor" = "java" ] && [ "$java_ver" -ge 110 ] )
|
||||
then
|
||||
options="detected java 11 from oracle or any openjdk"
|
||||
fi
|
||||
echo $options
|
||||
}
|
||||
|
||||
run_test() {
|
||||
FULL_JAVA_VERSION="$1"
|
||||
EXPECTED_VENDOR="$2"
|
||||
EXPECTED_VER="$3"
|
||||
EXPECTED="$4"
|
||||
echo "Testing: '${FULL_JAVA_VERSION}'"
|
||||
determine_java_version
|
||||
java_opts="$(jre_specific_vm_options)"
|
||||
echo -n "java_ver: $java_ver "
|
||||
if [ "$EXPECTED_VER" = "$java_ver" ]; then echo -e "\e[32mOK\e[0m"; else echo -e "\e[31mFAILED\e[0m"; fi
|
||||
echo -n "java_vendor: $java_vendor "
|
||||
if [ "$EXPECTED_VENDOR" = "$java_vendor" ]; then echo -e "\e[32mOK\e[0m"; else echo -e "\e[31mFAILED\e[0m"; fi
|
||||
echo -n "java_opts: $java_opts "
|
||||
if [ "$EXPECTED" = "$java_opts" ]; then echo -e "\e[32mOK\e[0m"; else echo -e "\e[31mFAILED\e[0m - expected: ${EXPECTED}"; fi
|
||||
echo
|
||||
}
|
||||
|
||||
run_test "java version \"1.7.0_80\"" "java" "70" "detected java 7"
|
||||
run_test "openjdk version \"1.7.0_352\"" "openjdk" "70" "detected java 7"
|
||||
run_test "java version \"1.8.0_271\"" "java" "80" "detected java 8"
|
||||
run_test "openjdk version \"1.8.0_345\"" "openjdk" "80" "detected java 8"
|
||||
run_test "java version \"9.0.4\"" "java" "90" "detected java 9 or 10 from oracle"
|
||||
run_test "openjdk version \"9.0.4\"" "openjdk" "90" "detected java 11 from oracle or any openjdk"
|
||||
run_test "java version \"10.0.2\" 2018-07-17" "java" "100" "detected java 9 or 10 from oracle"
|
||||
run_test "openjdk version \"11.0.6\" 2022-08-12" "openjdk" "110" "detected java 11 from oracle or any openjdk"
|
||||
run_test "openjdk version \"11.0.6.1\" 2022-08-12" "openjdk" "110" "detected java 11 from oracle or any openjdk"
|
||||
run_test "java version \"11.0.13\" 2021-10-19 LTS" "java" "110" "detected java 11 from oracle or any openjdk"
|
||||
run_test "openjdk version \"17.0.4\" 2022-08-12" "openjdk" "170" "detected java 11 from oracle or any openjdk"
|
||||
run_test "openjdk version \"17.1.4\" 2022-08-12" "openjdk" "171" "detected java 11 from oracle or any openjdk"
|
||||
run_test "openjdk version \"17.0.4.1\" 2022-08-12" "openjdk" "170" "detected java 11 from oracle or any openjdk"
|
||||
run_test "openjdk version \"18.0.2.1\" 2022-08-18" "openjdk" "180" "detected java 11 from oracle or any openjdk"
|
||||
run_test "openjdk version \"19-ea\" 2022-09-20" "openjdk" "190" "detected java 11 from oracle or any openjdk"
|
@ -31,7 +31,7 @@
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.14.3</version>
|
||||
<version>1.15.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -4,51 +4,21 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.rule.bestpractices;
|
||||
|
||||
import static net.sourceforge.pmd.util.CollectionUtil.setOf;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
|
||||
import net.sourceforge.pmd.lang.java.ast.AccessNode.Visibility;
|
||||
import net.sourceforge.pmd.lang.java.ast.Annotatable;
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaNode;
|
||||
import net.sourceforge.pmd.lang.java.ast.internal.JavaAstUtils;
|
||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
|
||||
import net.sourceforge.pmd.lang.java.rule.internal.JavaPropertyUtil;
|
||||
import net.sourceforge.pmd.properties.PropertyDescriptor;
|
||||
import net.sourceforge.pmd.properties.PropertyFactory;
|
||||
|
||||
public class UnusedPrivateFieldRule extends AbstractJavaRulechainRule {
|
||||
|
||||
private static final Set<String> INVALIDATING_CLASS_ANNOT = setOf(
|
||||
"lombok.Builder",
|
||||
"lombok.EqualsAndHashCode",
|
||||
"lombok.Getter",
|
||||
"lombok.Setter",
|
||||
"lombok.Data",
|
||||
"lombok.Value"
|
||||
);
|
||||
|
||||
private static final PropertyDescriptor<List<String>> IGNORED_FIELD_ANNOTATIONS =
|
||||
JavaPropertyUtil.ignoredAnnotationsDescriptor(
|
||||
"lombok.Setter",
|
||||
"lombok.Getter",
|
||||
"java.lang.Deprecated",
|
||||
"lombok.experimental.Delegate",
|
||||
"javafx.fxml.FXML",
|
||||
"javax.persistence.Id",
|
||||
"javax.persistence.EmbeddedId",
|
||||
"javax.persistence.Version",
|
||||
"jakarta.persistence.Id",
|
||||
"jakarta.persistence.EmbeddedId",
|
||||
"jakarta.persistence.Version",
|
||||
"org.mockito.Mock",
|
||||
"org.mockito.Spy",
|
||||
"org.springframework.boot.test.mock.mockito.MockBean"
|
||||
);
|
||||
|
||||
private static final PropertyDescriptor<List<String>> IGNORED_FIELD_NAMES =
|
||||
PropertyFactory.stringListProperty("ignoredFieldNames")
|
||||
.defaultValues("serialVersionUID", "serialPersistentFields")
|
||||
@ -57,7 +27,6 @@ public class UnusedPrivateFieldRule extends AbstractJavaRulechainRule {
|
||||
|
||||
public UnusedPrivateFieldRule() {
|
||||
super(ASTAnyTypeDeclaration.class);
|
||||
definePropertyDescriptor(IGNORED_FIELD_ANNOTATIONS);
|
||||
definePropertyDescriptor(IGNORED_FIELD_NAMES);
|
||||
}
|
||||
|
||||
@ -65,7 +34,7 @@ public class UnusedPrivateFieldRule extends AbstractJavaRulechainRule {
|
||||
public Object visitJavaNode(JavaNode node, Object data) {
|
||||
if (node instanceof ASTAnyTypeDeclaration) {
|
||||
ASTAnyTypeDeclaration type = (ASTAnyTypeDeclaration) node;
|
||||
if (JavaAstUtils.hasAnyAnnotation(type, INVALIDATING_CLASS_ANNOT)) {
|
||||
if (hasAnyAnnotation(type)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -85,10 +54,14 @@ public class UnusedPrivateFieldRule extends AbstractJavaRulechainRule {
|
||||
private boolean isIgnored(ASTFieldDeclaration field) {
|
||||
return field.getVisibility() != Visibility.V_PRIVATE
|
||||
|| isOK(field)
|
||||
|| JavaAstUtils.hasAnyAnnotation(field, getProperty(IGNORED_FIELD_ANNOTATIONS));
|
||||
|| hasAnyAnnotation(field);
|
||||
}
|
||||
|
||||
private boolean isOK(ASTFieldDeclaration field) {
|
||||
return field.getVarIds().any(it -> getProperty(IGNORED_FIELD_NAMES).contains(it.getName()));
|
||||
}
|
||||
|
||||
private static boolean hasAnyAnnotation(Annotatable node) {
|
||||
return !node.getDeclaredAnnotations().isEmpty();
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,16 @@ public class CommentDefaultAccessModifierRule extends AbstractJavaRulechainRule
|
||||
private static final PropertyDescriptor<List<String>> IGNORED_ANNOTS =
|
||||
JavaPropertyUtil.ignoredAnnotationsDescriptor(
|
||||
"com.google.common.annotations.VisibleForTesting",
|
||||
"android.support.annotation.VisibleForTesting"
|
||||
"android.support.annotation.VisibleForTesting",
|
||||
"org.junit.jupiter.api.Test",
|
||||
"org.junit.jupiter.api.ParameterizedTest",
|
||||
"org.junit.jupiter.api.RepeatedTest",
|
||||
"org.junit.jupiter.api.TestFactory",
|
||||
"org.junit.jupiter.api.TestTemplate",
|
||||
"org.junit.jupiter.api.BeforeEach",
|
||||
"org.junit.jupiter.api.BeforeAll",
|
||||
"org.junit.jupiter.api.AfterEach",
|
||||
"org.junit.jupiter.api.AfterAll"
|
||||
);
|
||||
|
||||
private static final PropertyDescriptor<Pattern> REGEX_DESCRIPTOR =
|
||||
|
@ -5,9 +5,13 @@
|
||||
package net.sourceforge.pmd.lang.java.rule.errorprone;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.pcollections.PVector;
|
||||
import org.pcollections.TreePVector;
|
||||
|
||||
@ -40,13 +44,15 @@ import net.sourceforge.pmd.lang.java.types.OverloadSelectionResult;
|
||||
public final class ConstructorCallsOverridableMethodRule extends AbstractJavaRulechainRule {
|
||||
|
||||
private static final String MESSAGE = "Overridable method called during object construction: {0} ";
|
||||
private static final String MESSAGE_TRANSITIVE = "This method may call an overridable method during object construction: {0}";
|
||||
private static final String MESSAGE_TRANSITIVE = "This method may call an overridable method during object construction: {0} (call stack: [{1}])";
|
||||
|
||||
|
||||
// Maps methods to the method that makes them unsafe
|
||||
// Safe methods are mapped to null
|
||||
// The value is used for better messages
|
||||
private final Map<JMethodSymbol, JMethodSymbol> safeMethods = new HashMap<>();
|
||||
// Maps methods to the method call stack that makes them unsafe
|
||||
// Safe methods are mapped to an empty stack
|
||||
// The method call stack (value of the map) is used for better messages
|
||||
private final Map<JMethodSymbol, Deque<JMethodSymbol>> safeMethods = new HashMap<>();
|
||||
|
||||
private static final Deque<JMethodSymbol> EMPTY_STACK = new LinkedList<>();
|
||||
|
||||
public ConstructorCallsOverridableMethodRule() {
|
||||
super(ASTConstructorDeclaration.class);
|
||||
@ -64,47 +70,53 @@ public final class ConstructorCallsOverridableMethodRule extends AbstractJavaRul
|
||||
return null; // then cannot be overridden
|
||||
}
|
||||
for (ASTMethodCall call : node.getBody().descendants(ASTMethodCall.class)) {
|
||||
JMethodSymbol unsafetyReason = getUnsafetyReason(call, TreePVector.empty());
|
||||
if (unsafetyReason != null) {
|
||||
Deque<JMethodSymbol> unsafetyReason = getUnsafetyReason(call, TreePVector.empty());
|
||||
if (!unsafetyReason.isEmpty()) {
|
||||
JMethodSig overload = call.getOverloadSelectionInfo().getMethodType();
|
||||
JMethodSig unsafeMethod = call.getTypeSystem().sigOf(unsafetyReason);
|
||||
JMethodSig unsafeMethod = call.getTypeSystem().sigOf(unsafetyReason.getLast());
|
||||
String message = unsafeMethod.equals(overload) ? MESSAGE : MESSAGE_TRANSITIVE;
|
||||
addViolationWithMessage(data, call, message, new Object[] { PrettyPrintingUtil.prettyPrintOverload(unsafetyReason) });
|
||||
String lastMethod = PrettyPrintingUtil.prettyPrintOverload(unsafetyReason.getLast());
|
||||
String stack = unsafetyReason.stream().map(PrettyPrintingUtil::prettyPrintOverload).collect(Collectors.joining(", "));
|
||||
asCtx(data).addViolationWithMessage(call, message, lastMethod, stack);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private JMethodSymbol getUnsafetyReason(ASTMethodCall call, PVector<ASTMethodDeclaration> recursionGuard) {
|
||||
@NonNull
|
||||
private Deque<JMethodSymbol> getUnsafetyReason(ASTMethodCall call, PVector<ASTMethodDeclaration> recursionGuard) {
|
||||
if (!isCallOnThisInstance(call)) {
|
||||
return null;
|
||||
return EMPTY_STACK;
|
||||
}
|
||||
|
||||
OverloadSelectionResult overload = call.getOverloadSelectionInfo();
|
||||
if (overload.isFailed()) {
|
||||
return null;
|
||||
return EMPTY_STACK;
|
||||
}
|
||||
|
||||
JMethodSymbol method = (JMethodSymbol) overload.getMethodType().getSymbol();
|
||||
if (isOverridable(method)) {
|
||||
return method; // the method itself
|
||||
Deque<JMethodSymbol> stack = new LinkedList<>();
|
||||
stack.addFirst(method); // the method itself
|
||||
return stack;
|
||||
} else {
|
||||
return getUnsafetyReason(method, recursionGuard);
|
||||
}
|
||||
}
|
||||
|
||||
private JMethodSymbol getUnsafetyReason(JMethodSymbol method, PVector<ASTMethodDeclaration> recursionGuard) {
|
||||
@NonNull
|
||||
private Deque<JMethodSymbol> getUnsafetyReason(JMethodSymbol method, PVector<ASTMethodDeclaration> recursionGuard) {
|
||||
if (method.isStatic()) {
|
||||
return null; // no access to this instance anyway
|
||||
return EMPTY_STACK; // no access to this instance anyway
|
||||
}
|
||||
// we need to prove that all calls on this instance are safe
|
||||
|
||||
ASTMethodDeclaration declaration = method.tryGetNode();
|
||||
if (declaration == null) {
|
||||
return null; // no idea
|
||||
return EMPTY_STACK; // no idea
|
||||
} else if (recursionGuard.contains(declaration)) {
|
||||
// being visited, assume body is safe
|
||||
return null;
|
||||
return EMPTY_STACK;
|
||||
}
|
||||
|
||||
// note we can't use computeIfAbsent because of comodification
|
||||
@ -117,18 +129,19 @@ public final class ConstructorCallsOverridableMethodRule extends AbstractJavaRul
|
||||
for (ASTMethodCall call : NodeStream.of(declaration.getBody())
|
||||
.descendants(ASTMethodCall.class)
|
||||
.filter(ConstructorCallsOverridableMethodRule::isCallOnThisInstance)) {
|
||||
JMethodSymbol unsafetyReason = getUnsafetyReason(call, deeperRecursion);
|
||||
if (unsafetyReason != null) {
|
||||
Deque<JMethodSymbol> unsafetyReason = getUnsafetyReason(call, deeperRecursion);
|
||||
if (!unsafetyReason.isEmpty()) {
|
||||
// this method call is unsafe for some reason,
|
||||
// body is unsafe for the same reason
|
||||
safeMethods.put(method, unsafetyReason);
|
||||
return unsafetyReason;
|
||||
safeMethods.putIfAbsent(method, new LinkedList<>(unsafetyReason));
|
||||
safeMethods.get(method).addFirst(method);
|
||||
return safeMethods.get(method);
|
||||
}
|
||||
}
|
||||
|
||||
// body is safe
|
||||
safeMethods.put(method, null);
|
||||
return null;
|
||||
safeMethods.remove(method);
|
||||
return EMPTY_STACK;
|
||||
}
|
||||
|
||||
private static boolean isCallOnThisInstance(ASTMethodCall call) {
|
||||
|
@ -19,7 +19,7 @@ Rules which enforce generally accepted best practices.
|
||||
The abstract class does not contain any abstract methods. An abstract class suggests
|
||||
an incomplete implementation, which is to be completed by subclasses implementing the
|
||||
abstract methods. If the class is intended to be used as a base class only (not to be instantiated
|
||||
directly) a protected constructor can be provided prevent direct instantiation.
|
||||
directly) a protected constructor can be provided to prevent direct instantiation.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
@ -1606,6 +1606,12 @@ public class Foo {
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_bestpractices.html#unusedprivatefield">
|
||||
<description>
|
||||
Detects when a private field is declared and/or assigned a value, but not used.
|
||||
|
||||
Since PMD 6.50.0 private fields are ignored, if the fields are annotated with any annotation or the
|
||||
enclosing class has any annotation. Annotations often enable a framework (such as dependency injection, mocking
|
||||
or e.g. Lombok) which use the fields by reflection or other means. This usage can't be detected by static code analysis.
|
||||
Previously these frameworks where explicitly allowed by listing their annotations in the property
|
||||
"ignoredAnnotations", but that turned out to be prone of false positive for any not explicitly considered framework.
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<example>
|
||||
|
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