forked from phoedos/pmd
Compare commits
182 Commits
dependabot
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
4f766035a4 | ||
|
9da17877ac | ||
|
3e9e128aa7 | ||
|
918684c154 | ||
|
e63edf358e | ||
|
0d11f151bd | ||
|
28b4139cd4 | ||
|
d61f691559 | ||
|
12f7f98803 | ||
|
2e4f16d516 | ||
|
46ef55c9a9 | ||
|
79c0ce0415 | ||
|
8fdfd369b0 | ||
|
80b8bc47df | ||
|
a9b6c946b4 | ||
|
2910ab0403 | ||
|
5a0220da2e | ||
|
bc4a49deac | ||
|
a40c30c8c1 | ||
|
44c15aae6d | ||
|
85aeebbab0 | ||
|
a5925eb5ea | ||
|
c456396931 | ||
|
1ee0f53608 | ||
|
e60f460e02 | ||
|
ee1ab976bc | ||
|
15cab177d2 | ||
|
b6f45ed618 | ||
|
1ceae38880 | ||
|
f7de8d3e7e | ||
|
59864a7c6c | ||
|
a6746fcffa | ||
|
aad8e93a2f | ||
|
3bb943e0e5 | ||
|
3356dd949d | ||
|
b264fa14e1 | ||
|
c1aa4e0381 | ||
|
a72ac5845b | ||
|
4e1f4be009 | ||
|
c73e5cb8b1 | ||
|
5931b6601c | ||
|
9d15c900db | ||
|
69a24126f7 | ||
|
ef3a4cc15e | ||
|
4ef8fb21a9 | ||
|
f803aa36dc | ||
|
0cf8f2c18b | ||
|
178f9541e2 | ||
|
79026f98c9 | ||
|
0e0f347f51 | ||
|
0d606a7122 | ||
|
d60b234a47 | ||
|
b050ce353e | ||
|
32f55e22e3 | ||
|
206ed8bbd3 | ||
|
e1d4f27e19 | ||
|
093683bc59 | ||
|
509452577d | ||
|
991bc2c41d | ||
|
8c58a0b3f5 | ||
|
01b8ca765b | ||
|
3fdbf7d6cb | ||
|
bb729e02f4 | ||
|
bf388d7fd0 | ||
|
61eb116833 | ||
|
634a525286 | ||
|
2df68ed168 | ||
|
04dfb782f0 | ||
|
a79d3e6557 | ||
|
bb2782241e | ||
|
2340168421 | ||
|
e5a1236981 | ||
|
ed5e862aa3 | ||
|
529693c916 | ||
|
1a9e721fb6 | ||
|
4e4ca6bb70 | ||
|
3659a2cb7d | ||
|
07de5559bc | ||
|
b05b8240a7 | ||
|
ee7d6fed3e | ||
|
fe88498ee8 | ||
|
944e1e8f7a | ||
|
ca208d2241 | ||
|
9dcb697f13 | ||
|
733ac4bba0 | ||
|
1ee6494429 | ||
|
a1996554d8 | ||
|
e15c05721e | ||
|
f0daed5874 | ||
|
36dfcf8211 | ||
|
83d8ca0169 | ||
|
be3c34fe1a | ||
|
52fb6c814b | ||
|
93929deef6 | ||
|
3ed370f61d | ||
|
5eaefd2841 | ||
|
a709be1dcb | ||
|
c079d8c544 | ||
|
7bfa581511 | ||
|
6ae7404941 | ||
|
94095df872 | ||
|
7119424d96 | ||
|
69a92de52d | ||
|
73dbc7a67f | ||
|
c81cd1d520 | ||
|
4473aa6667 | ||
|
97d68e331c | ||
|
16eafc89c2 | ||
|
d68d6c57ef | ||
|
9c098b2531 | ||
|
3f697aff35 | ||
|
74ec6f45ee | ||
|
c179834288 | ||
|
7739f2b840 | ||
|
919e73f6b0 | ||
|
e2d59c0e64 | ||
|
8f2d47dfb7 | ||
|
e6097d6090 | ||
|
5e83246469 | ||
|
62c2858f70 | ||
|
0d8878d58e | ||
|
4b23718aac | ||
|
3a501a0f6b | ||
|
36654ed52e | ||
|
45b1217485 | ||
|
662759755d | ||
|
d9d6b57f2a | ||
|
6c35c73919 | ||
|
e37f82b62d | ||
|
6f5af6e585 | ||
|
66d879f707 | ||
|
93f6279ea7 | ||
|
156f293ef3 | ||
|
40ed4590be | ||
|
7358289bbe | ||
|
a180258033 | ||
|
63675eaa18 | ||
|
49f2c15b83 | ||
|
15520211b5 | ||
|
c4b8f18a36 | ||
|
c95817a75d | ||
|
09b0864eff | ||
|
1517a18956 | ||
|
61b1c372cd | ||
|
97fe389dcc | ||
|
7df70ea7c1 | ||
|
7ad4e0f0fc | ||
|
c47f5a6062 | ||
|
6d55f6f053 | ||
|
5df7dccfb6 | ||
|
f4941433ce | ||
|
665504decc | ||
|
ef0db9a166 | ||
|
fd8fcd67d6 | ||
|
dafdc964a5 | ||
|
81429a4628 | ||
|
fb94e2493c | ||
|
a0d4b38b53 | ||
|
f317e8bee5 | ||
|
7ae3155325 | ||
|
c595fea83f | ||
|
07840cace2 | ||
|
ff1b9b2cdd | ||
|
377670f267 | ||
|
5ecc29245b | ||
|
079eb238b9 | ||
|
b3157825d8 | ||
|
6f081e111a | ||
|
59403fc9e1 | ||
|
13cc79af62 | ||
|
1f31f771ad | ||
|
d9db4dbcab | ||
|
855e5175d4 | ||
|
b87944a565 | ||
|
90f436fd28 | ||
|
375fb72f3c | ||
|
49deb8d4a0 | ||
|
312d8e46ae | ||
|
e5ff5532d4 | ||
|
0c858b0a7b | ||
|
9337e5a7a2 | ||
|
33c737718c |
@ -7453,7 +7453,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/16755668?v=4",
|
||||
"profile": "https://github.com/emouty",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -7516,6 +7517,7 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/18402464?v=4",
|
||||
"profile": "https://github.com/mitchspano",
|
||||
"contributions": [
|
||||
"code",
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
@ -7820,6 +7822,15 @@
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "thesunlover",
|
||||
"name": "Iskren Stanislavov",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6734600?v=4",
|
||||
"profile": "https://interop.io/",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "gudzpoz",
|
||||
"name": "gudzpoz",
|
||||
@ -7846,6 +7857,42 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jdupak",
|
||||
"name": "Jakub Dupak",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/22683640?v=4",
|
||||
"profile": "https://github.com/jdupak",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "chenguangqi",
|
||||
"name": "天热吃西瓜",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6231010?v=4",
|
||||
"profile": "http://chenguangqi.github.io/",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "wahajenius",
|
||||
"name": "Willem A. Hajenius",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7836322?v=4",
|
||||
"profile": "https://github.com/wahajenius",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "VitaliiIevtushenko",
|
||||
"name": "Vitalii Yevtushenko",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11145125?v=4",
|
||||
"profile": "https://github.com/VitaliiIevtushenko",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
28
Gemfile.lock
28
Gemfile.lock
@ -3,6 +3,7 @@ GEM
|
||||
specs:
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
base64 (0.2.0)
|
||||
bigdecimal (3.1.8)
|
||||
claide (1.1.0)
|
||||
claide-plugins (0.9.2)
|
||||
@ -13,7 +14,8 @@ GEM
|
||||
concurrent-ruby (1.3.4)
|
||||
cork (0.3.0)
|
||||
colored2 (~> 3.1)
|
||||
danger (9.5.0)
|
||||
danger (9.5.1)
|
||||
base64 (~> 0.2)
|
||||
claide (~> 1.0)
|
||||
claide-plugins (>= 0.9.2)
|
||||
colored2 (~> 3.1)
|
||||
@ -24,12 +26,14 @@ GEM
|
||||
kramdown (~> 2.3)
|
||||
kramdown-parser-gfm (~> 1.0)
|
||||
octokit (>= 4.0)
|
||||
pstore (~> 0.1)
|
||||
terminal-table (>= 1, < 4)
|
||||
differ (0.1.2)
|
||||
et-orbi (1.2.11)
|
||||
tzinfo
|
||||
faraday (2.11.0)
|
||||
faraday (2.12.0)
|
||||
faraday-net_http (>= 2.0, < 3.4)
|
||||
json
|
||||
logger
|
||||
faraday-http-cache (2.5.1)
|
||||
faraday (>= 0.8)
|
||||
@ -41,19 +45,20 @@ GEM
|
||||
git (1.19.1)
|
||||
addressable (~> 2.8)
|
||||
rchardet (~> 1.8)
|
||||
json (2.7.5)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (5.5.1)
|
||||
logger (1.6.0)
|
||||
logger (1.6.1)
|
||||
logger-colors (1.0.0)
|
||||
nap (1.1.0)
|
||||
net-http (0.4.1)
|
||||
uri
|
||||
nokogiri (1.16.7-x86_64-linux)
|
||||
racc (~> 1.4)
|
||||
octokit (9.1.0)
|
||||
octokit (9.2.0)
|
||||
faraday (>= 1, < 3)
|
||||
sawyer (~> 0.9)
|
||||
open4 (1.3.4)
|
||||
@ -64,26 +69,25 @@ GEM
|
||||
nokogiri (~> 1.13)
|
||||
rufus-scheduler (~> 3.8)
|
||||
slop (~> 4.9)
|
||||
pstore (0.1.3)
|
||||
public_suffix (6.0.1)
|
||||
raabro (1.4.0)
|
||||
racc (1.8.1)
|
||||
rchardet (1.8.0)
|
||||
rexml (3.3.6)
|
||||
strscan
|
||||
rouge (4.4.0)
|
||||
rufus-scheduler (3.9.1)
|
||||
fugit (~> 1.1, >= 1.1.6)
|
||||
rexml (3.3.9)
|
||||
rouge (4.5.1)
|
||||
rufus-scheduler (3.9.2)
|
||||
fugit (~> 1.1, >= 1.11.1)
|
||||
safe_yaml (1.0.5)
|
||||
sawyer (0.9.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (>= 0.17.3, < 3)
|
||||
slop (4.10.1)
|
||||
strscan (3.1.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (2.5.0)
|
||||
unicode-display_width (2.6.0)
|
||||
uri (0.13.1)
|
||||
|
||||
PLATFORMS
|
||||
@ -98,4 +102,4 @@ DEPENDENCIES
|
||||
safe_yaml
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.3
|
||||
2.5.22
|
||||
|
@ -172,8 +172,8 @@ public class ${lexer-name}'/>
|
||||
</delete>
|
||||
</target>
|
||||
|
||||
<target name="pmd-language" depends="check-up-to-date, annotate-classes, pmd-language-processing, update-stamp-file"/>
|
||||
<target name="pmd-language-processing" description="Adapt Antlr sources for PMD languages" depends="rename-parser"
|
||||
<target name="pmd-language" depends="check-up-to-date, rename-parser, annotate-classes, pmd-language-processing, update-stamp-file"/>
|
||||
<target name="pmd-language-processing" description="Adapt Antlr sources for PMD languages"
|
||||
unless="processing-not-required">
|
||||
|
||||
<!-- Adapt parser. -->
|
||||
|
@ -1,8 +1,9 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (7.2.1)
|
||||
activesupport (7.2.2)
|
||||
base64
|
||||
benchmark (>= 0.3)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||
connection_pool (>= 2.2.5)
|
||||
@ -15,6 +16,7 @@ GEM
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
base64 (0.2.0)
|
||||
benchmark (0.3.0)
|
||||
bigdecimal (3.1.8)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
@ -34,9 +36,10 @@ GEM
|
||||
ethon (0.16.0)
|
||||
ffi (>= 1.15.0)
|
||||
eventmachine (1.2.7)
|
||||
execjs (2.9.1)
|
||||
faraday (2.11.0)
|
||||
execjs (2.10.0)
|
||||
faraday (2.12.0)
|
||||
faraday-net_http (>= 2.0, < 3.4)
|
||||
json
|
||||
logger
|
||||
faraday-net_http (3.3.0)
|
||||
net-http
|
||||
@ -99,7 +102,7 @@ GEM
|
||||
activesupport (>= 2)
|
||||
nokogiri (>= 1.4)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.14.5)
|
||||
i18n (1.14.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (3.10.0)
|
||||
addressable (~> 2.4)
|
||||
@ -211,6 +214,7 @@ GEM
|
||||
gemoji (>= 3, < 5)
|
||||
html-pipeline (~> 2.2)
|
||||
jekyll (>= 3.0, < 5.0)
|
||||
json (2.7.5)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
@ -219,7 +223,7 @@ GEM
|
||||
listen (3.9.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
logger (1.6.0)
|
||||
logger (1.6.1)
|
||||
mercenary (0.3.6)
|
||||
minima (2.5.1)
|
||||
jekyll (>= 3.5, < 5.0)
|
||||
@ -240,8 +244,7 @@ GEM
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.11.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.3.6)
|
||||
strscan
|
||||
rexml (3.3.9)
|
||||
rouge (3.30.0)
|
||||
rubyzip (2.3.2)
|
||||
safe_yaml (1.0.5)
|
||||
@ -255,7 +258,6 @@ GEM
|
||||
faraday (>= 0.17.3, < 3)
|
||||
securerandom (0.3.1)
|
||||
simpleidn (0.2.3)
|
||||
strscan (3.1.0)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
typhoeus (1.4.1)
|
||||
@ -264,7 +266,7 @@ GEM
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (1.8.0)
|
||||
uri (0.13.1)
|
||||
webrick (1.8.2)
|
||||
webrick (1.9.0)
|
||||
|
||||
PLATFORMS
|
||||
x86_64-linux
|
||||
@ -276,4 +278,4 @@ DEPENDENCIES
|
||||
webrick
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.3
|
||||
2.5.22
|
||||
|
@ -1,9 +1,9 @@
|
||||
repository: pmd/pmd
|
||||
|
||||
pmd:
|
||||
version: 7.7.0-SNAPSHOT
|
||||
previous_version: 7.6.0
|
||||
date: 2024-10-25
|
||||
version: 7.8.0-SNAPSHOT
|
||||
previous_version: 7.7.0
|
||||
date: 2024-11-29
|
||||
# release types: major, minor, bugfix
|
||||
release_type: minor
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -163,7 +163,7 @@ exactly identical.
|
||||
{% include custom/cli_option_row.html options="--ignore-literals"
|
||||
description="Ignore literal values such as numbers and strings when comparing text.
|
||||
By default, literals are not ignored."
|
||||
languages="Java"
|
||||
languages="Java, C++"
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--ignore-literal-sequences"
|
||||
description="Ignore sequences of literals such as list initializers.
|
||||
@ -173,7 +173,7 @@ exactly identical.
|
||||
{% include custom/cli_option_row.html options="--ignore-identifiers"
|
||||
description="Ignore names of classes, methods, variables, constants, etc. when comparing text.
|
||||
By default, identifier names are not ignored."
|
||||
languages="Java"
|
||||
languages="Java, C++"
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--ignore-annotations"
|
||||
description="Ignore language annotations (Java) or attributes (C#) when comparing text.
|
||||
|
@ -14,48 +14,70 @@ This is a {{ site.pmd.release_type }} release.
|
||||
|
||||
### 🚀 New and noteworthy
|
||||
|
||||
### 🌟 Rule Changes
|
||||
### 🌟 New and changed rules
|
||||
|
||||
#### Renamed Rules
|
||||
* Several rules for unit testing have been renamed to better reflect their actual scope. Lots of them were called
|
||||
after JUnit / JUnit 4, even when they applied to JUnit 5 and / or TestNG.
|
||||
* {% rule java/bestpractices/UnitTestAssertionsShouldIncludeMessage %} (Java Best Practices) has been renamed from `JUnitAssertionsShouldIncludeMessage`.
|
||||
* {% rule java/bestpractices/UnitTestContainsTooManyAsserts %} (Java Best Practices) has been renamed from `JUnitTestContainsTooManyAsserts`.
|
||||
* {% rule java/bestpractices/UnitTestShouldIncludeAssert %} (Java Best Practices) has been renamed from `JUnitTestsShouldIncludeAssert`.
|
||||
* {% rule java/bestpractices/UnitTestShouldUseAfterAnnotation %} (Java Best Practices) has been renamed from `JUnit4TestShouldUseAfterAnnotation`.
|
||||
* {% rule java/bestpractices/UnitTestShouldUseBeforeAnnotation %} (Java Best Practices) has been renamed from `JUnit4TestShouldUseBeforeAnnotation`.
|
||||
* {% rule java/bestpractices/UnitTestShouldUseTestAnnotation %} (Java Best Practices) has been renamed from `JUnit4TestShouldUseTestAnnotation`.
|
||||
|
||||
The old rule names still work but are deprecated.
|
||||
#### New Rules
|
||||
* The new Apex rule {% rule apex/bestpractices/QueueableWithoutFinalizer %} detects when the Queueable interface
|
||||
is used but a Finalizer is not attached. Without attaching a Finalizer, there is no way of designing error
|
||||
recovery actions should the Queueable action fail.
|
||||
|
||||
### 🐛 Fixed Issues
|
||||
* ant
|
||||
* [#1860](https://github.com/pmd/pmd/issues/1860): \[ant] Reflective access warnings on java > 9 and java < 17
|
||||
* apex
|
||||
* [#5302](https://github.com/pmd/pmd/issues/5302): \[apex] New Rule: Queueable Should Attach Finalizer
|
||||
* [#5333](https://github.com/pmd/pmd/issues/5333): \[apex] Token recognition errors for string containing unicode escape sequence
|
||||
* html
|
||||
* [#5322](https://github.com/pmd/pmd/issues/5322): \[html] CPD throws exception on when HTML file is missing closing tag
|
||||
* java
|
||||
* [#4532](https://github.com/pmd/pmd/issues/4532): \[java] Rule misnomer for JUnit* rules
|
||||
* [#5261](https://github.com/pmd/pmd/issues/5261): \[java] Record patterns with empty deconstructor lists lead to NPE
|
||||
* [#5293](https://github.com/pmd/pmd/issues/5293): \[java] Deadlock when executing PMD in multiple threads
|
||||
* [#5324](https://github.com/pmd/pmd/issues/5324): \[java] Issue with type inference of nested lambdas
|
||||
* [#5329](https://github.com/pmd/pmd/issues/5329): \[java] Type inference issue with unknown method ref in call chain
|
||||
* java-bestpractices
|
||||
* [#5083](https://github.com/pmd/pmd/issues/5083): \[java] UnusedPrivateMethod false positive when method reference has no target type
|
||||
* [#5097](https://github.com/pmd/pmd/issues/5097): \[java] UnusedPrivateMethod FP with raw type missing from the classpath
|
||||
* [#5318](https://github.com/pmd/pmd/issues/5318): \[java] PreserveStackTraceRule: false-positive on Pattern Matching with instanceof
|
||||
* java-codestyle
|
||||
* [#5253](https://github.com/pmd/pmd/issues/5253): \[java] BooleanGetMethodName: False-negatives with `Boolean` wrapper
|
||||
* java-errorprone
|
||||
* [#5067](https://github.com/pmd/pmd/issues/5067): \[java] CloseResource: False positive for FileSystems.getDefault()
|
||||
* [#5263](https://github.com/pmd/pmd/issues/5263): \[java] UnnecessaryFullyQualifiedName: false-positive in an enum that uses its own static variables
|
||||
* java-performance
|
||||
* [#5287](https://github.com/pmd/pmd/issues/5287): \[java] TooFewBranchesForSwitch false-positive with switch using list of case constants
|
||||
* [#5314](https://github.com/pmd/pmd/issues/5314): \[java] InsufficientStringBufferDeclarationRule: Lack of handling for char type parameters
|
||||
|
||||
### 🚨 API Changes
|
||||
* java-bestpractices
|
||||
* The old rule name `JUnit4TestShouldUseAfterAnnotation` has been deprecated. Use the new name {% rule java/bestpractices/UnitTestShouldUseAfterAnnotation %} instead.
|
||||
* The old rule name `JUnit4TestShouldUseBeforeAnnotation` has been deprecated. Use the new name {% rule java/bestpractices/UnitTestShouldUseBeforeAnnotation %} instead.
|
||||
* The old rule name `JUnit4TestShouldUseTestAnnotation` has been deprecated. Use the new name {% rule java/bestpractices/UnitTestShouldUseTestAnnotation %} instead.
|
||||
* The old rule name `JUnitAssertionsShouldIncludeMessage` has been deprecated. Use the new name {% rule java/bestpractices/UnitTestAssertionsShouldIncludeMessage %} instead.
|
||||
* The old rule name `JUnitTestContainsTooManyAsserts` has been deprecated. Use the new name {% rule java/bestpractices/UnitTestContainsTooManyAsserts %} instead.
|
||||
* The old rule name `JUnitTestsShouldIncludeAssert` has been deprecated. Use the new name {% rule java/bestpractices/UnitTestShouldIncludeAssert %} instead.
|
||||
|
||||
#### Deprecations
|
||||
* pmd-gherkin
|
||||
* {%jdoc gherkin::lang.gherkin.ast.GherkinBaseListener %} is deprecated for removal. This class was never intended
|
||||
to be generated. It will be removed with no replacement.
|
||||
* {%jdoc gherkin::lang.gherkin.ast.GherkinBaseVisitor %} is deprecated for removal. This class was never intended
|
||||
to be generated. It will be removed with no replacement.
|
||||
* {%jdoc gherkin::lang.gherkin.ast.GherkinListener %} is deprecated for removal. This class was never intended
|
||||
to be generated. It will be removed with no replacement.
|
||||
* {%jdoc gherkin::lang.gherkin.ast.GherkinParser %} is deprecated for removal. This class was never intended
|
||||
to be generated. It will be removed with no replacement.
|
||||
* {%jdoc gherkin::lang.gherkin.ast.GherkinVisitor %} is deprecated for removal. This class was never intended
|
||||
to be generated. It will be removed with no replacement.
|
||||
* pmd-julia
|
||||
* {%jdoc julia::lang.julia.ast.JuliaBaseListener %} is deprecated for removal. This class was never intended to
|
||||
be generated. It will be removed with no replacement.
|
||||
* {%jdoc julia::lang.julia.ast.JuliaBaseVisitor %} is deprecated for removal. This class was never intended to
|
||||
be generated. It will be removed with no replacement.
|
||||
* {%jdoc julia::lang.julia.ast.JuliaListener %} is deprecated for removal. This class was never intended to
|
||||
be generated. It will be removed with no replacement.
|
||||
* {%jdoc julia::lang.julia.ast.JuliaParser %} is deprecated for removal. This class was never intended to
|
||||
be generated. It will be removed with no replacement.
|
||||
* {%jdoc julia::lang.julia.ast.JuliaVisitor %} is deprecated for removal. This class was never intended to
|
||||
be generated. It will be removed with no replacement.
|
||||
* pmd-kotlin
|
||||
* {%jdoc kotlin::lang.kotlin.ast.UnicodeClasses %} is deprecated for removal. This class was never intended to
|
||||
be generated. It will be removed with no replacement.
|
||||
* pmd-xml
|
||||
* {%jdoc xml::lang.xml.antlr4.XMLLexer %} is deprecated for removal. Use {%jdoc !!xml::lang.xml.ast.XMLLexer %}
|
||||
instead (note different package `ast` instead of `antlr4`).
|
||||
|
||||
### ✨ Merged pull requests
|
||||
* [#4965](https://github.com/pmd/pmd/pull/4965): Fix #4532: \[java] Rename JUnit rules with overly restrictive names - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
|
||||
* [#5225](https://github.com/pmd/pmd/pull/5225): Fix #5067: \[java] CloseResource: False positive for FileSystems.getDefault() - [Lukas Gräf](https://github.com/lukasgraef) (@lukasgraef)
|
||||
* [#5241](https://github.com/pmd/pmd/pull/5241): Ignore javacc code in coverage report - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
|
||||
* [#5258](https://github.com/pmd/pmd/pull/5258): Ignore generated antlr classes in coverage reports - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
|
||||
* [#5264](https://github.com/pmd/pmd/pull/5264): Fix #5261: \[java] Fix NPE with empty pattern list - [Clément Fournier](https://github.com/oowekyala) (@oowekyala)
|
||||
* [#5269](https://github.com/pmd/pmd/pull/5269): Fix #5253: \[java] Support Boolean wrapper class for BooleanGetMethodName rule - [Aryant Tripathi](https://github.com/Aryant-Tripathi) (@Aryant-Tripathi)
|
||||
* [#5275](https://github.com/pmd/pmd/pull/5275): Use plugin-classpath to simplify javacc-wrapper.xml - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5278](https://github.com/pmd/pmd/pull/5278): \[java] CouplingBetweenObjects: improve violation message - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
### ✨ External Contributions
|
||||
* [#5284](https://github.com/pmd/pmd/pull/5284): \[apex] Use case-insensitive input stream to avoid choking on Unicode escape sequences - [Willem A. Hajenius](https://github.com/wahajenius) (@wahajenius)
|
||||
* [#5303](https://github.com/pmd/pmd/pull/5303): \[apex] New Rule: Queueable Should Attach Finalizer - [Mitch Spano](https://github.com/mitchspano) (@mitchspano)
|
||||
|
||||
{% endtocmaker %}
|
||||
|
||||
|
@ -5,6 +5,132 @@ permalink: pmd_release_notes_old.html
|
||||
|
||||
Previous versions of PMD can be downloaded here: [Releases - pmd/pmd (GitHub)](https://github.com/pmd/pmd/releases)
|
||||
|
||||
## 25-October-2024 - 7.7.0
|
||||
|
||||
The PMD team is pleased to announce PMD 7.7.0.
|
||||
|
||||
This is a minor release.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
* [🚀 New and noteworthy](#new-and-noteworthy)
|
||||
* [CPD can now ignore literals and identifiers in C++ code](#cpd-can-now-ignore-literals-and-identifiers-in-c-code)
|
||||
* [🌟 Rule Changes](#rule-changes)
|
||||
* [Changed Rules](#changed-rules)
|
||||
* [Renamed Rules](#renamed-rules)
|
||||
* [🐛 Fixed Issues](#fixed-issues)
|
||||
* [🚨 API Changes](#api-changes)
|
||||
* [✨ Merged pull requests](#merged-pull-requests)
|
||||
* [📦 Dependency updates](#dependency-updates)
|
||||
* [📈 Stats](#stats)
|
||||
|
||||
### 🚀 New and noteworthy
|
||||
|
||||
#### CPD can now ignore literals and identifiers in C++ code
|
||||
|
||||
When searching for duplicated code in C++ differences in literals or identifiers can be
|
||||
ignored now (like in Java). This can be enabled via the command line options `--ignore-literal`
|
||||
and `--ignore-identifiers`.
|
||||
See [PR #5040](https://github.com/pmd/pmd/pull/5040) for details.
|
||||
|
||||
### 🌟 Rule Changes
|
||||
|
||||
#### Changed Rules
|
||||
* [`SwitchStmtsShouldHaveDefault`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#switchstmtsshouldhavedefault) (Java Best Practices) doesn't report empty switch statements anymore.
|
||||
To detect these, use [`EmptyControlStatement`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_codestyle.html#emptycontrolstatement).
|
||||
* [`UnitTestShouldUseAfterAnnotation`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestshoulduseafterannotation) (Java Best Practices) now also considers JUnit 5 and TestNG tests.
|
||||
* [`UnitTestShouldUseBeforeAnnotation`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestshouldusebeforeannotation) (Java Best Practices) now also considers JUnit 5 and TestNG tests.
|
||||
* [`TooFewBranchesForSwitch`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_performance.html#toofewbranchesforswitch) (Java Performance) doesn't report empty switches anymore.
|
||||
To detect these, use [`EmptyControlStatement`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_codestyle.html#emptycontrolstatement).
|
||||
|
||||
#### Renamed Rules
|
||||
* Several rules for unit testing have been renamed to better reflect their actual scope. Lots of them were called
|
||||
after JUnit / JUnit 4, even when they applied to JUnit 5 and / or TestNG.
|
||||
* [`UnitTestAssertionsShouldIncludeMessage`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestassertionsshouldincludemessage) (Java Best Practices) has been renamed from `JUnitAssertionsShouldIncludeMessage`.
|
||||
* [`UnitTestContainsTooManyAsserts`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestcontainstoomanyasserts) (Java Best Practices) has been renamed from `JUnitTestContainsTooManyAsserts`.
|
||||
* [`UnitTestShouldIncludeAssert`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestshouldincludeassert) (Java Best Practices) has been renamed from `JUnitTestsShouldIncludeAssert`.
|
||||
* [`UnitTestShouldUseAfterAnnotation`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestshoulduseafterannotation) (Java Best Practices) has been renamed from `JUnit4TestShouldUseAfterAnnotation`.
|
||||
* [`UnitTestShouldUseBeforeAnnotation`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestshouldusebeforeannotation) (Java Best Practices) has been renamed from `JUnit4TestShouldUseBeforeAnnotation`.
|
||||
* [`UnitTestShouldUseTestAnnotation`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestshouldusetestannotation) (Java Best Practices) has been renamed from `JUnit4TestShouldUseTestAnnotation`.
|
||||
* Several rules about switch statements and switch expression have been renamed, as they apply both to Switch Statements
|
||||
and to Switch Expressions:
|
||||
* [`DefaultLabelNotLastInSwitch`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#defaultlabelnotlastinswitch) (Java Best Practices) has been renamed from `DefaultLabelNotLastInSwitchStmt`.
|
||||
* [`NonCaseLabelInSwitch`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_errorprone.html#noncaselabelinswitch) (Java Error Prone) has been renamed from `NonCaseLabelInSwitchStatement`.
|
||||
* [`TooFewBranchesForSwitch`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_performance.html#toofewbranchesforswitch) (Java Performance) has been renamed from `TooFewBranchesForASwitchStatement`.
|
||||
* [`NonExhaustiveSwitch`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#nonexhaustiveswitch) (Java Best Practices) has been renamed from `SwitchStmtsShouldHaveDefault`.
|
||||
|
||||
The old rule names still work but are deprecated.
|
||||
|
||||
### 🐛 Fixed Issues
|
||||
* apex-performance
|
||||
* [#5270](https://github.com/pmd/pmd/issues/5270): \[apex] AvoidNonRestrictiveQueries when LIMIT is followed by bind expression
|
||||
* java
|
||||
* [#4532](https://github.com/pmd/pmd/issues/4532): \[java] Rule misnomer for JUnit* rules
|
||||
* [#5261](https://github.com/pmd/pmd/issues/5261): \[java] Record patterns with empty deconstructor lists lead to NPE
|
||||
* java-bestpractices
|
||||
* [#4286](https://github.com/pmd/pmd/issues/4286): \[java] Rename rule SwitchStmtsShouldHaveDefault to NonExhaustiveSwitch
|
||||
* [#4813](https://github.com/pmd/pmd/issues/4813): \[java] SwitchStmtsShouldHaveDefault false positive with pattern matching
|
||||
* java-codestyle
|
||||
* [#5253](https://github.com/pmd/pmd/issues/5253): \[java] BooleanGetMethodName: False-negatives with `Boolean` wrapper
|
||||
* java-design
|
||||
* [#5030](https://github.com/pmd/pmd/issues/5030): \[java] SwitchDensity false positive with pattern matching
|
||||
* java-errorprone
|
||||
* [#3362](https://github.com/pmd/pmd/issues/3362): \[java] ImplicitSwitchFallThrough should consider switch expressions
|
||||
* [#5067](https://github.com/pmd/pmd/issues/5067): \[java] CloseResource: False positive for FileSystems.getDefault()
|
||||
* [#5244](https://github.com/pmd/pmd/issues/5244): \[java] UselessOperationOnImmutable should detect java.time types
|
||||
* [#5257](https://github.com/pmd/pmd/issues/5257): \[java] NonCaseLabelInSwitch should consider switch expressions
|
||||
* java-performance
|
||||
* [#5249](https://github.com/pmd/pmd/issues/5249): \[java] TooFewBranchesForASwitchStatement false positive for Pattern Matching
|
||||
* [#5250](https://github.com/pmd/pmd/issues/5250): \[java] TooFewBranchesForASwitchStatement should consider Switch Expressions
|
||||
|
||||
### 🚨 API Changes
|
||||
* java-bestpractices
|
||||
* The old rule name `JUnit4TestShouldUseAfterAnnotation` has been deprecated. Use the new name [`UnitTestShouldUseAfterAnnotation`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestshoulduseafterannotation) instead.
|
||||
* The old rule name `JUnit4TestShouldUseBeforeAnnotation` has been deprecated. Use the new name [`UnitTestShouldUseBeforeAnnotation`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestshouldusebeforeannotation) instead.
|
||||
* The old rule name `JUnit4TestShouldUseTestAnnotation` has been deprecated. Use the new name [`UnitTestShouldUseTestAnnotation`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestshouldusetestannotation) instead.
|
||||
* The old rule name `JUnitAssertionsShouldIncludeMessage` has been deprecated. Use the new name [`UnitTestAssertionsShouldIncludeMessage`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestassertionsshouldincludemessage) instead.
|
||||
* The old rule name `JUnitTestContainsTooManyAsserts` has been deprecated. Use the new name [`UnitTestContainsTooManyAsserts`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestcontainstoomanyasserts) instead.
|
||||
* The old rule name `JUnitTestsShouldIncludeAssert` has been deprecated. Use the new name [`UnitTestShouldIncludeAssert`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#unittestshouldincludeassert) instead.
|
||||
* The old rule name `DefaultLabelNotLastInSwitchStmt` has been deprecated. Use the new name [`DefaultLabelNotLastInSwitch`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#defaultlabelnotlastinswitch) instead.
|
||||
* The old rule name `SwitchStmtsShouldHaveDefault` has been deprecated. USe the new name [`NonExhaustiveSwitch`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_bestpractices.html#nonexhaustiveswitch) instead.
|
||||
* java-errorprone
|
||||
* The old rule name `NonCaseLabelInSwitchStatement` has been deprecated. Use the new name [`NonCaseLabelInSwitch`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_errorprone.html#noncaselabelinswitch) instead.
|
||||
* java-performance
|
||||
* The old rule name `TooFewBranchesForASwitchStatement` has been deprecated. Use the new name [`TooFewBranchesForSwitch`](https://docs.pmd-code.org/pmd-doc-7.7.0/pmd_rules_java_performance.html#toofewbranchesforswitch) instead.
|
||||
|
||||
### ✨ Merged pull requests
|
||||
* [#4965](https://github.com/pmd/pmd/pull/4965): Fix #4532: \[java] Rename JUnit rules with overly restrictive names - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
|
||||
* [#5040](https://github.com/pmd/pmd/pull/5040): \[cpp] Ignore literals and ignore identifiers capability to C++ CPD - [Jakub Dupak](https://github.com/jdupak) (@jdupak)
|
||||
* [#5225](https://github.com/pmd/pmd/pull/5225): Fix #5067: \[java] CloseResource: False positive for FileSystems.getDefault() - [Lukas Gräf](https://github.com/lukasgraef) (@lukasgraef)
|
||||
* [#5241](https://github.com/pmd/pmd/pull/5241): Ignore javacc code in coverage report - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
|
||||
* [#5245](https://github.com/pmd/pmd/pull/5245): \[java] Improve UnitTestShouldUse{After,Before}Annotation rules to support JUnit5 and TestNG - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5247](https://github.com/pmd/pmd/pull/5247): Fix #5030: \[java] SwitchDensity false positive with pattern matching - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5248](https://github.com/pmd/pmd/pull/5248): Fix #3362: \[java] ImplicitSwitchFallThrough should consider switch expressions - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5251](https://github.com/pmd/pmd/pull/5251): Fix #5249 and #5250: \[java] TooFewBranchesForSwitch ignore pattern matching and support switch expressions - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5252](https://github.com/pmd/pmd/pull/5252): Fix #4813: \[java] SwitchStmtsShouldHaveDefault false positive with pattern matching - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5255](https://github.com/pmd/pmd/pull/5255): \[java] Rename rule DefaultLabelNotLastInSwitch - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5256](https://github.com/pmd/pmd/pull/5256): Fix #5257: \[java] NonCaseLabelInSwitch - support switch expressions - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5258](https://github.com/pmd/pmd/pull/5258): Ignore generated antlr classes in coverage reports - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
|
||||
* [#5264](https://github.com/pmd/pmd/pull/5264): Fix #5261: \[java] Fix NPE with empty pattern list - [Clément Fournier](https://github.com/oowekyala) (@oowekyala)
|
||||
* [#5267](https://github.com/pmd/pmd/pull/5267): \[java] Rename rule SwitchStmtsShouldHaveDefault to NonExhaustiveSwitch - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5269](https://github.com/pmd/pmd/pull/5269): Fix #5253: \[java] Support Boolean wrapper class for BooleanGetMethodName rule - [Aryant Tripathi](https://github.com/Aryant-Tripathi) (@Aryant-Tripathi)
|
||||
* [#5273](https://github.com/pmd/pmd/pull/5273): Fix #5270: \[apex] AvoidNonRestrictiveQueries: Fix regex for detecting LIMIT clause - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5275](https://github.com/pmd/pmd/pull/5275): Use plugin-classpath to simplify javacc-wrapper.xml - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5278](https://github.com/pmd/pmd/pull/5278): \[java] CouplingBetweenObjects: improve violation message - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
* [#5279](https://github.com/pmd/pmd/pull/5279): Fix #5244: \[java] UselessOperationOnImmutable: consider java.time.* types - [Andreas Dangel](https://github.com/adangel) (@adangel)
|
||||
|
||||
### 📦 Dependency updates
|
||||
* [#5234](https://github.com/pmd/pmd/issues/5234): Bump com.google.protobuf:protobuf-java from 3.25.3 to 4.28.2
|
||||
* [#5274](https://github.com/pmd/pmd/issues/5274): Bump org.junit from 5.8.2 to 5.11.2
|
||||
* [#5276](https://github.com/pmd/pmd/issues/5276): Bump org.checkerframework:checker-qual from 2.11.1 to 3.48.1
|
||||
* [#5280](https://github.com/pmd/pmd/issues/5280): Bump danger from 9.5.0 to 9.5.1 in the all-gems group across 1 directory
|
||||
* [#5281](https://github.com/pmd/pmd/issues/5281): Bump org.scala-lang:scala-reflect from 2.13.13 to 2.13.15
|
||||
|
||||
### 📈 Stats
|
||||
* 98 commits
|
||||
* 32 closed tickets & PRs
|
||||
* Days since last release: 27
|
||||
|
||||
## 27-September-2024 - 7.6.0
|
||||
|
||||
The PMD team is pleased to announce PMD 7.6.0.
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<artifactId>pmd</artifactId>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<version>7.7.0-SNAPSHOT</version>
|
||||
<version>7.8.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -11,6 +11,7 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.Charset;
|
||||
@ -21,8 +22,6 @@ import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.apache.commons.lang3.reflect.MethodUtils;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.Project;
|
||||
import org.apache.tools.ant.types.Parameter;
|
||||
@ -200,10 +199,12 @@ public class Formatter {
|
||||
if (console != null) {
|
||||
// Since Java 22, this returns a console even for redirected streams.
|
||||
// In that case, we need to check Console.isTerminal()
|
||||
// https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/io/Console.html#isTerminal()
|
||||
// See: JLine As The Default Console Provider (JDK-8308591)
|
||||
try {
|
||||
Boolean isTerminal = (Boolean) MethodUtils.invokeMethod(console, "isTerminal");
|
||||
if (!isTerminal) {
|
||||
Method method = Console.class.getMethod("isTerminal");
|
||||
Object isTerminal = method.invoke(console);
|
||||
if (isTerminal instanceof Boolean && !(Boolean) isTerminal) {
|
||||
// stop here, we don't have an interactive console.
|
||||
return null;
|
||||
}
|
||||
@ -211,39 +212,58 @@ public class Formatter {
|
||||
// fall-through - we use a Java Runtime < 22.
|
||||
}
|
||||
|
||||
// Maybe this is Java17+? Then there will be a public method charset()
|
||||
// https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/Console.html#charset()
|
||||
try {
|
||||
Object res = FieldUtils.readDeclaredField(console, "cs", true);
|
||||
if (res instanceof Charset) {
|
||||
return ((Charset) res).name();
|
||||
Method method = Console.class.getMethod("charset");
|
||||
Object charset = method.invoke(console);
|
||||
if (charset instanceof Charset) {
|
||||
return ((Charset) charset).name();
|
||||
}
|
||||
} catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException ignored) {
|
||||
// fall-through
|
||||
}
|
||||
|
||||
{
|
||||
// try to use the system property "sun.jnu.encoding", which is the platform encoding.
|
||||
// this property is not specified and might not always be available, but it is for
|
||||
// openjdk 11: https://github.com/openjdk/jdk11u/blob/cee8535a9d3de8558b4b5028d68e397e508bef71/src/java.base/share/native/libjava/System.c#L384
|
||||
// if it exists, we use it - this avoids illegal reflective access below.
|
||||
String jnuEncoding = System.getProperty("sun.jnu.encoding");
|
||||
if (jnuEncoding != null) {
|
||||
return jnuEncoding;
|
||||
}
|
||||
}
|
||||
|
||||
// the following parts are accessing private/protected fields via reflection
|
||||
// this should work with Java 8 and 11. With Java 11, you'll see warnings abouts
|
||||
// illegal reflective access, see #1860. However, the access still works.
|
||||
|
||||
// Fall-Back 1: private field "cs" in java.io.Console
|
||||
try {
|
||||
Field field = Console.class.getDeclaredField("cs");
|
||||
field.setAccessible(true);
|
||||
Object csField = field.get(console);
|
||||
if (csField instanceof Charset) {
|
||||
return ((Charset) csField).name();
|
||||
}
|
||||
} catch (IllegalArgumentException | ReflectiveOperationException ignored) {
|
||||
// fall-through
|
||||
}
|
||||
|
||||
// Maybe this is Java17+? Then there will be
|
||||
// https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/Console.html#charset()
|
||||
// instead of the field "cs".
|
||||
// Fall-Back 2: private native method "encoding()" in java.io.Console
|
||||
try {
|
||||
Method charsetMethod = Console.class.getDeclaredMethod("charset");
|
||||
Charset charset = (Charset) charsetMethod.invoke(console);
|
||||
return charset.name();
|
||||
} catch (IllegalArgumentException | ReflectiveOperationException ignored) {
|
||||
Method method = Console.class.getDeclaredMethod("encoding");
|
||||
method.setAccessible(true);
|
||||
Object encoding = method.invoke(console);
|
||||
if (encoding instanceof String) {
|
||||
return (String) encoding;
|
||||
}
|
||||
} catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException ignored) {
|
||||
// fall-through
|
||||
}
|
||||
return getNativeConsoleEncoding();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getNativeConsoleEncoding() {
|
||||
try {
|
||||
Object res = MethodUtils.invokeStaticMethod(Console.class, "encoding");
|
||||
if (res instanceof String) {
|
||||
return (String) res;
|
||||
}
|
||||
} catch (IllegalArgumentException | ReflectiveOperationException ignored) {
|
||||
// fall-through
|
||||
}
|
||||
// we couldn't determine the correct platform console encoding
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>7.7.0-SNAPSHOT</version>
|
||||
<version>7.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -14,14 +14,19 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.RandomAccess;
|
||||
|
||||
import org.antlr.v4.runtime.BaseErrorListener;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.RecognitionException;
|
||||
import org.antlr.v4.runtime.Recognizer;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.ast.LexException;
|
||||
import net.sourceforge.pmd.lang.document.TextDocument;
|
||||
import net.sourceforge.pmd.lang.document.TextRegion;
|
||||
|
||||
import io.github.apexdevtools.apexparser.ApexLexer;
|
||||
import io.github.apexdevtools.apexparser.CaseInsensitiveInputStream;
|
||||
|
||||
@InternalApi
|
||||
final class ApexCommentBuilder {
|
||||
@ -103,7 +108,15 @@ final class ApexCommentBuilder {
|
||||
}
|
||||
|
||||
private static CommentInformation extractInformationFromComments(TextDocument sourceCode, String suppressMarker) {
|
||||
ApexLexer lexer = new ApexLexer(CharStreams.fromString(sourceCode.getText().toString()));
|
||||
String source = sourceCode.getText().toString();
|
||||
ApexLexer lexer = new ApexLexer(new CaseInsensitiveInputStream(CharStreams.fromString(source)));
|
||||
lexer.removeErrorListeners();
|
||||
lexer.addErrorListener(new BaseErrorListener() {
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
|
||||
throw new LexException(line, charPositionInLine, sourceCode.getFileId(), msg, e);
|
||||
}
|
||||
});
|
||||
|
||||
List<Token> allCommentTokens = new ArrayList<>();
|
||||
Map<Integer, String> suppressMap = new HashMap<>();
|
||||
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.rule.bestpractices;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTParameter;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTUserClass;
|
||||
import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule;
|
||||
import net.sourceforge.pmd.lang.rule.RuleTargetSelector;
|
||||
|
||||
/**
|
||||
* Scans classes which implement the `Queueable` interface. If the `public void
|
||||
* execute(QueueableContext context)` method does not call the
|
||||
* `System.attachFinalizer(Finalizer f)` method, then a violation will be added
|
||||
* to the `execute` method.
|
||||
*
|
||||
* @author mitchspano
|
||||
*/
|
||||
public class QueueableWithoutFinalizerRule extends AbstractApexRule {
|
||||
|
||||
private static final String EXECUTE = "execute";
|
||||
private static final String QUEUEABLE = "queueable";
|
||||
private static final String QUEUEABLE_CONTEXT = "queueablecontext";
|
||||
private static final String SYSTEM_ATTACH_FINALIZER = "system.attachfinalizer";
|
||||
|
||||
@Override
|
||||
protected @NonNull RuleTargetSelector buildTargetSelector() {
|
||||
return RuleTargetSelector.forTypes(ASTUserClass.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the class implements the `Queueable` interface and the
|
||||
* `execute(QueueableContext context)` does not call the
|
||||
* `System.attachFinalizer(Finalizer f)` method, then add a violation.
|
||||
*/
|
||||
@Override
|
||||
public Object visit(ASTUserClass theClass, Object data) {
|
||||
if (!implementsTheQueueableInterface(theClass)) {
|
||||
return data;
|
||||
}
|
||||
for (ASTMethod theMethod : theClass.descendants(ASTMethod.class).toList()) {
|
||||
if (isTheExecuteMethodOfTheQueueableInterface(theMethod)
|
||||
&& !callsTheSystemAttachFinalizerMethod(theMethod)) {
|
||||
asCtx(data).addViolation(theMethod);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Determines if the class implements the Queueable interface. */
|
||||
private boolean implementsTheQueueableInterface(ASTUserClass theClass) {
|
||||
for (String interfaceName : theClass.getInterfaceNames()) {
|
||||
if (QUEUEABLE.equalsIgnoreCase(interfaceName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the method is the `execute(QueueableContext context)`
|
||||
* method. Parameter count is checked to account for method overloading.
|
||||
*/
|
||||
private boolean isTheExecuteMethodOfTheQueueableInterface(ASTMethod theMethod) {
|
||||
if (!EXECUTE.equalsIgnoreCase(theMethod.getCanonicalName())) {
|
||||
return false;
|
||||
}
|
||||
List<ASTParameter> parameters = theMethod.descendants(ASTParameter.class).toList();
|
||||
return parameters.size() == 1 && QUEUEABLE_CONTEXT.equalsIgnoreCase(parameters.get(0).getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the method calls the `System.attachFinalizer(Finalizer f)`
|
||||
* method.
|
||||
*/
|
||||
private boolean callsTheSystemAttachFinalizerMethod(ASTMethod theMethod) {
|
||||
for (ASTMethodCallExpression methodCallExpression : theMethod.descendants(ASTMethodCallExpression.class)
|
||||
.toList()) {
|
||||
if (SYSTEM_ATTACH_FINALIZER.equalsIgnoreCase(methodCallExpression.getFullMethodName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ import net.sourceforge.pmd.lang.rule.RuleTargetSelector;
|
||||
import net.sourceforge.pmd.reporting.RuleContext;
|
||||
|
||||
public class AvoidNonRestrictiveQueriesRule extends AbstractApexRule {
|
||||
private static final Pattern RESTRICTIVE_PATTERN = Pattern.compile("(where\\s+)|(limit\\s+)", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern RESTRICTIVE_PATTERN = Pattern.compile("\\b(where|limit)\\b", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern SELECT_OR_FIND_PATTERN = Pattern.compile("(select\\s+|find\\s+)", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern SUB_QUERY_PATTERN = Pattern.compile("(?i)\\(\\s*select\\s+[^)]+\\)");
|
||||
|
||||
|
@ -285,4 +285,56 @@ Detects when a local variable is declared and/or assigned but not used.
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule name="QueueableWithoutFinalizer"
|
||||
since="7.8.0"
|
||||
language="apex"
|
||||
message="This Queueable doesn't attach a Finalizer"
|
||||
class="net.sourceforge.pmd.lang.apex.rule.bestpractices.QueueableWithoutFinalizerRule"
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_bestpractices.html#queueablewithoutfinalizer">
|
||||
<description>
|
||||
Detects when the Queueable interface is used but a Finalizer is not attached.
|
||||
It is best practice to call the `System.attachFinalizer(Finalizer f)` method within the `execute` method of a class which implements the `Queueable` interface.
|
||||
Without attaching a Finalizer, there is no way of designing error recovery actions should the Queueable action fail.
|
||||
</description>
|
||||
<priority>5</priority>
|
||||
<example>
|
||||
<![CDATA[
|
||||
// Incorrect code, does not attach a finalizer.
|
||||
public class UserUpdater implements Queueable {
|
||||
public List<User> usersToUpdate;
|
||||
|
||||
public UserUpdater(List<User> usersToUpdate) {
|
||||
this.usersToUpdate = usersToUpdate;
|
||||
}
|
||||
|
||||
public void execute(QueueableContext context) { // no Finalizer is attached
|
||||
update usersToUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
// Proper code, attaches a finalizer.
|
||||
public class UserUpdater implements Queueable, Finalizer {
|
||||
public List<User> usersToUpdate;
|
||||
|
||||
public UserUpdater(List<User> usersToUpdate) {
|
||||
this.usersToUpdate = usersToUpdate;
|
||||
}
|
||||
|
||||
public void execute(QueueableContext context) {
|
||||
System.attachFinalizer(this);
|
||||
update usersToUpdate;
|
||||
}
|
||||
|
||||
public void execute(FinalizerContext ctx) {
|
||||
if (ctx.getResult() == ParentJobResult.SUCCESS) {
|
||||
// Handle success
|
||||
} else {
|
||||
// Handle failure
|
||||
}
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
</ruleset>
|
||||
|
@ -209,6 +209,7 @@
|
||||
<priority>3</priority>
|
||||
</rule>
|
||||
<!-- <rule ref="category/apex/bestpractices.xml/UnusedLocalVariable"/> -->
|
||||
<!-- <rule ref="category/apex/bestpractices.xml/QueueableWithoutFinalizer"/> -->
|
||||
<!-- <rule ref="category/apex/errorprone.xml/OverrideBothEqualsAndHashcode" /> -->
|
||||
<!-- <rule ref="category/apex/errorprone.xml/InaccessibleAuraEnabledGetter" /> -->
|
||||
|
||||
|
@ -66,4 +66,12 @@ class ApexCommentTest extends ApexParserTestBase {
|
||||
ASTFormalComment comment = file.descendants(ASTUserClass.class).children(ASTFormalComment.class).first();
|
||||
assertEquals(FORMAL_COMMENT_CONTENT, comment.getImage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void fileWithUnicodeEscapes() {
|
||||
ASTApexFile file = apex.parse(FORMAL_COMMENT_CONTENT + "\n"
|
||||
+ "class MyClass { String s = 'Fran\\u00E7ois'; }");
|
||||
ASTFormalComment comment = file.descendants(ASTUserClass.class).children(ASTFormalComment.class).first();
|
||||
assertEquals(FORMAL_COMMENT_CONTENT, comment.getImage());
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,18 @@ package net.sourceforge.pmd.lang.apex.ast;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import org.antlr.v4.runtime.BaseErrorListener;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.RecognitionException;
|
||||
import org.antlr.v4.runtime.Recognizer;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import io.github.apexdevtools.apexparser.ApexLexer;
|
||||
import io.github.apexdevtools.apexparser.ApexParser;
|
||||
import io.github.apexdevtools.apexparser.CaseInsensitiveInputStream;
|
||||
|
||||
/**
|
||||
* This is an exploration test for {@link ApexLexer}.
|
||||
@ -49,4 +53,36 @@ class ApexLexerTest {
|
||||
ApexParser.CompilationUnitContext compilationUnit = parser.compilationUnit();
|
||||
assertNotNull(compilationUnit);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLexerUnicodeEscapes() {
|
||||
String s = "'Fran\\u00E7ois'";
|
||||
// note: with apex-parser 4.3.1, no errors are reported anymore
|
||||
assertEquals(2, getLexingErrors(CharStreams.fromString(s)));
|
||||
assertEquals(0, getLexingErrors(new CaseInsensitiveInputStream(CharStreams.fromString(s))));
|
||||
}
|
||||
|
||||
private int getLexingErrors(CharStream stream) {
|
||||
ApexLexer lexer = new ApexLexer(stream);
|
||||
ErrorListener errorListener = new ErrorListener();
|
||||
lexer.removeErrorListeners(); // Avoid distracting "token recognition error" stderr output
|
||||
lexer.addErrorListener(errorListener);
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
tokens.fill();
|
||||
return errorListener.getErrorCount();
|
||||
}
|
||||
|
||||
private static class ErrorListener extends BaseErrorListener {
|
||||
private int errorCount = 0;
|
||||
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line,
|
||||
int charPositionInLine, String msg, RecognitionException e) {
|
||||
++errorCount;
|
||||
}
|
||||
|
||||
public int getErrorCount() {
|
||||
return errorCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.rule.bestpractices;
|
||||
|
||||
import net.sourceforge.pmd.test.PmdRuleTst;
|
||||
|
||||
class QueueableWithoutFinalizerTest extends PmdRuleTst {
|
||||
// no additional unit tests
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test-data
|
||||
xmlns="http://pmd.sourceforge.net/rule-tests"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
|
||||
|
||||
<test-code>
|
||||
<description>[apex] Queueable Without Finalizer - positive test case #5302</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>8</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
public class UserUpdater implements Queueable {
|
||||
public List<User> usersToUpdate;
|
||||
|
||||
public UserUpdater(List<User> usersToUpdate) {
|
||||
this.usersToUpdate = usersToUpdate;
|
||||
}
|
||||
|
||||
public void execute(QueueableContext context) {
|
||||
update usersToUpdate;
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description>[apex] Queueable Without Finalizer - negative test case #5302</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class UserUpdater implements Queueable, Finalizer {
|
||||
public List<User> usersToUpdate;
|
||||
|
||||
public UserUpdater(List<User> usersToUpdate) {
|
||||
this.usersToUpdate = usersToUpdate;
|
||||
}
|
||||
|
||||
public void execute(QueueableContext context) {
|
||||
System.attachFinalizer(this);
|
||||
update usersToUpdate;
|
||||
}
|
||||
|
||||
public void execute(FinalizerContext ctx) {
|
||||
if (ctx.getResult() == ParentJobResult.SUCCESS) {
|
||||
// Handle success
|
||||
} else {
|
||||
// Handle failure
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
</test-data>
|
@ -260,6 +260,36 @@ public class Something {
|
||||
.isEmpty();
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>[apex] AvoidNonRestrictiveQueries when LIMIT is followed by bind expression #5270</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public with sharing class DemoController {
|
||||
public static final Integer LIMIT_ACCOUNTS = 2;
|
||||
@AuraEnabled
|
||||
public static List<Account> getTwoAccounts() {
|
||||
List<Account> result = [
|
||||
SELECT Id, Name FROM Account WITH SECURITY_ENFORCED
|
||||
LIMIT:LIMIT_ACCOUNTS // note: no spaces... - false positive here
|
||||
];
|
||||
List<Account> result2 = [
|
||||
SELECT Id, Name FROM Account WITH SECURITY_ENFORCED
|
||||
LIMIT :LIMIT_ACCOUNTS
|
||||
];
|
||||
List<Account> result3 = [
|
||||
SELECT Id, Name FROM Account WITH SECURITY_ENFORCED
|
||||
LIMIT : LIMIT_ACCOUNTS
|
||||
];
|
||||
|
||||
// sosl:
|
||||
List<List<SObject>> searchList = [FIND 'map*' IN ALL FIELDS RETURNING Account (Id, Name), Contact, Opportunity, Lead LIMIT:LIMIT_ACCOUNTS];
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
</test-data>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>7.7.0-SNAPSHOT</version>
|
||||
<version>7.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>7.7.0-SNAPSHOT</version>
|
||||
<version>7.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>7.7.0-SNAPSHOT</version>
|
||||
<version>7.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -48,7 +48,7 @@ class AbstractNodeTest {
|
||||
return childIndexes;
|
||||
}
|
||||
|
||||
static Object childrenAndGrandChildrenIndexes() {
|
||||
static Object[] childrenAndGrandChildrenIndexes() {
|
||||
final Integer[] childrenIndexes = childrenIndexes();
|
||||
final Integer[] grandChildrenIndexes = grandChildrenIndexes();
|
||||
final Object[] indexes = new Object[childrenIndexes.length * grandChildrenIndexes.length];
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>7.7.0-SNAPSHOT</version>
|
||||
<version>7.8.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -47,6 +47,8 @@ public class CppLanguageModule extends CpdOnlyLanguageModuleBase {
|
||||
LanguagePropertyBundle bundle = super.newPropertyBundle();
|
||||
bundle.definePropertyDescriptor(CpdLanguageProperties.CPD_IGNORE_LITERAL_SEQUENCES);
|
||||
bundle.definePropertyDescriptor(CpdLanguageProperties.CPD_IGNORE_LITERAL_AND_IDENTIFIER_SEQUENCES);
|
||||
bundle.definePropertyDescriptor(CpdLanguageProperties.CPD_ANONYMIZE_IDENTIFIERS);
|
||||
bundle.definePropertyDescriptor(CpdLanguageProperties.CPD_ANONYMIZE_LITERALS);
|
||||
bundle.definePropertyDescriptor(CPD_SKIP_BLOCKS);
|
||||
return bundle;
|
||||
}
|
||||
|
@ -9,8 +9,9 @@ import java.util.regex.Pattern;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import net.sourceforge.pmd.cpd.CpdLanguageProperties;
|
||||
import net.sourceforge.pmd.cpd.impl.CpdLexerBase;
|
||||
import net.sourceforge.pmd.cpd.TokenFactory;
|
||||
import net.sourceforge.pmd.cpd.impl.JavaCCTokenFilter;
|
||||
import net.sourceforge.pmd.cpd.impl.JavaccCpdLexer;
|
||||
import net.sourceforge.pmd.lang.LanguagePropertyBundle;
|
||||
import net.sourceforge.pmd.lang.TokenManager;
|
||||
import net.sourceforge.pmd.lang.ast.impl.javacc.CharStream;
|
||||
@ -26,17 +27,21 @@ import net.sourceforge.pmd.lang.document.TextDocument;
|
||||
*
|
||||
* <p>Note: This class has been called CPPTokenizer in PMD 6</p>.
|
||||
*/
|
||||
public class CppCpdLexer extends CpdLexerBase<JavaccToken> {
|
||||
public class CppCpdLexer extends JavaccCpdLexer {
|
||||
|
||||
private boolean skipBlocks;
|
||||
private Pattern skipBlocksStart;
|
||||
private Pattern skipBlocksEnd;
|
||||
private final boolean ignoreIdentifierAndLiteralSeqences;
|
||||
private final boolean ignoreLiteralSequences;
|
||||
private final boolean ignoreLiterals;
|
||||
private final boolean ignoreIdentifiers;
|
||||
|
||||
public CppCpdLexer(LanguagePropertyBundle cppProperties) {
|
||||
ignoreLiteralSequences = cppProperties.getProperty(CpdLanguageProperties.CPD_IGNORE_LITERAL_SEQUENCES);
|
||||
ignoreIdentifierAndLiteralSeqences = cppProperties.getProperty(CpdLanguageProperties.CPD_IGNORE_LITERAL_AND_IDENTIFIER_SEQUENCES);
|
||||
ignoreLiterals = cppProperties.getProperty(CpdLanguageProperties.CPD_ANONYMIZE_LITERALS);
|
||||
ignoreIdentifiers = cppProperties.getProperty(CpdLanguageProperties.CPD_ANONYMIZE_IDENTIFIERS);
|
||||
String skipBlocksPattern = cppProperties.getProperty(CppLanguageModule.CPD_SKIP_BLOCKS);
|
||||
if (StringUtils.isNotBlank(skipBlocksPattern)) {
|
||||
skipBlocks = true;
|
||||
@ -73,6 +78,23 @@ public class CppCpdLexer extends CpdLexerBase<JavaccToken> {
|
||||
return new CppTokenFilter(tokenManager, ignoreLiteralSequences, ignoreIdentifierAndLiteralSeqences);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processToken(TokenFactory tokenEntries, JavaccToken currentToken) {
|
||||
int kind = currentToken.getKind();
|
||||
String image = currentToken.getImage();
|
||||
|
||||
boolean isLiteral = kind == CppTokenKinds.STRING || kind == CppTokenKinds.RSTRING || kind == CppTokenKinds.CHARACTER || kind == CppTokenKinds.DECIMAL_INT_LITERAL || kind == CppTokenKinds.HEXADECIMAL_INT_LITERAL || kind == CppTokenKinds.OCTAL_INT_LITERAL || kind == CppTokenKinds.FLOAT_LITERAL || kind == CppTokenKinds.BINARY_INT_LITERAL || kind == CppTokenKinds.ZERO;
|
||||
if (ignoreLiterals && isLiteral) {
|
||||
image = CppTokenKinds.describe(kind);
|
||||
}
|
||||
|
||||
if (ignoreIdentifiers && (kind == CppTokenKinds.ID)) {
|
||||
image = CppTokenKinds.describe(kind);
|
||||
}
|
||||
|
||||
tokenEntries.recordToken(image, currentToken.getReportLocation());
|
||||
}
|
||||
|
||||
private static class CppTokenFilter extends JavaCCTokenFilter {
|
||||
|
||||
private final boolean ignoreLiteralSequences;
|
||||
|
@ -59,6 +59,16 @@ class CppCpdLexerTest extends CpdTextComparisonTest {
|
||||
doTest("specialComments");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIgnoreLiterals() {
|
||||
doTest("ignoreLiterals", "", ignoreLiterals());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIgnoreIdents() {
|
||||
doTest("ignoreIdents", "", ignoreIdents());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultiLineMacros() {
|
||||
doTest("multilineMacros");
|
||||
@ -142,7 +152,7 @@ class CppCpdLexerTest extends CpdTextComparisonTest {
|
||||
}
|
||||
|
||||
private static LanguagePropertyConfig skipBlocks(String skipPattern) {
|
||||
return properties(true, skipPattern, false, false);
|
||||
return properties(true, skipPattern, false, false, false, false);
|
||||
}
|
||||
|
||||
private static LanguagePropertyConfig skipBlocks() {
|
||||
@ -150,22 +160,31 @@ class CppCpdLexerTest extends CpdTextComparisonTest {
|
||||
}
|
||||
|
||||
private static LanguagePropertyConfig dontSkipBlocks() {
|
||||
return properties(false, null, false, false);
|
||||
return properties(false, null, false, false, false, false);
|
||||
}
|
||||
|
||||
private static LanguagePropertyConfig skipLiteralSequences() {
|
||||
return properties(false, null, true, false);
|
||||
return properties(false, null, true, false, false, false);
|
||||
}
|
||||
|
||||
private static LanguagePropertyConfig skipIdentifierAndLiteralsSequences() {
|
||||
return properties(false, null, true, true);
|
||||
return properties(false, null, true, true, false, false);
|
||||
}
|
||||
|
||||
private static LanguagePropertyConfig skipIdentifierSequences() {
|
||||
return properties(false, null, false, true);
|
||||
return properties(false, null, false, true, false, false);
|
||||
}
|
||||
|
||||
private static LanguagePropertyConfig properties(boolean skipBlocks, String skipPattern, boolean skipLiteralSequences, boolean skipSequences) {
|
||||
private static LanguagePropertyConfig ignoreIdents() {
|
||||
return properties(false, null, false, false, false, true);
|
||||
}
|
||||
|
||||
private static LanguagePropertyConfig ignoreLiterals() {
|
||||
return properties(false, null, false, false, true, false);
|
||||
}
|
||||
|
||||
|
||||
private static LanguagePropertyConfig properties(boolean skipBlocks, String skipPattern, boolean skipLiteralSequences, boolean skipSequences, boolean ignoreLiterals, boolean ignoreIdents) {
|
||||
return properties -> {
|
||||
if (!skipBlocks) {
|
||||
properties.setProperty(CppLanguageModule.CPD_SKIP_BLOCKS, "");
|
||||
@ -174,6 +193,8 @@ class CppCpdLexerTest extends CpdTextComparisonTest {
|
||||
}
|
||||
properties.setProperty(CpdLanguageProperties.CPD_IGNORE_LITERAL_SEQUENCES, skipLiteralSequences);
|
||||
properties.setProperty(CpdLanguageProperties.CPD_IGNORE_LITERAL_AND_IDENTIFIER_SEQUENCES, skipSequences);
|
||||
properties.setProperty(CpdLanguageProperties.CPD_ANONYMIZE_LITERALS, ignoreLiterals);
|
||||
properties.setProperty(CpdLanguageProperties.CPD_ANONYMIZE_IDENTIFIERS, ignoreIdents);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
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