forked from phoedos/pmd
Compare commits
86 Commits
pmd_releas
...
pmd_releas
Author | SHA1 | Date | |
---|---|---|---|
|
90b051bfff | ||
|
bc5b6b9801 | ||
|
1a3fb8a10f | ||
|
15f9ca6d3f | ||
|
f9398de22f | ||
|
6d6d4c5769 | ||
|
3bb93c5ef6 | ||
|
4382a32fb1 | ||
|
4d49fd5fe2 | ||
|
6458f95c4d | ||
|
8a6bb312e1 | ||
|
d6e2911b81 | ||
|
c08917773c | ||
|
be362aca8b | ||
|
fd3c366822 | ||
|
400f6c6776 | ||
|
1a6d60aead | ||
|
7c6e699de8 | ||
|
4c752c650a | ||
|
e0bc09ed8e | ||
|
d7d70d503e | ||
|
4377ca0ef9 | ||
|
ef3b1a8fa1 | ||
|
414b5c9a89 | ||
|
8fd326ca0a | ||
|
a69a612ff3 | ||
|
0cec8ade81 | ||
|
9affb15a56 | ||
|
a61b532ace | ||
|
bd6c72e0f5 | ||
|
64ef8957bc | ||
|
b256726ab0 | ||
|
3dd4eda7ea | ||
|
1138b96b81 | ||
|
83d56dab28 | ||
|
1f520a9f6f | ||
|
c00d84aa9a | ||
|
ee713c201f | ||
|
2f824576c9 | ||
|
d9c563f6d7 | ||
|
c9ff96a751 | ||
|
e6d2b5815f | ||
|
46e70a0d8f | ||
|
c38e9d40e6 | ||
|
65af1c0675 | ||
|
7d11a02052 | ||
|
5aa23354d4 | ||
|
17d0473eb2 | ||
|
af51d2d331 | ||
|
2636fde5d9 | ||
|
e22a434527 | ||
|
b2adc915bb | ||
|
e9e51ddfdb | ||
|
5a22ef104b | ||
|
742871afcc | ||
|
8da900b0c3 | ||
|
35685a994c | ||
|
d07b0caa58 | ||
|
5770785847 | ||
|
7e15f1781c | ||
|
4516f39686 | ||
|
f23d68e432 | ||
|
0a92718a4e | ||
|
389d2e855e | ||
|
f97347eb86 | ||
|
c961c74458 | ||
|
7796535a24 | ||
|
52e3bb1eed | ||
|
482268def8 | ||
|
55c005a39e | ||
|
e64d485384 | ||
|
064c1d7aef | ||
|
54dc756207 | ||
|
b9d3685b10 | ||
|
efaf34df44 | ||
|
e72d79d2b9 | ||
|
172c7bec58 | ||
|
e3a94a1b04 | ||
|
3734d293e8 | ||
|
8153ce9a7a | ||
|
8acb7dc781 | ||
|
f76c5eec1a | ||
|
46edb0d432 | ||
|
6969f1b3cc | ||
|
69541a0252 | ||
|
821f7a849b |
6445
.all-contributorsrc
Normal file
6445
.all-contributorsrc
Normal file
File diff suppressed because it is too large
Load Diff
10
.ci/build.sh
10
.ci/build.sh
@ -87,15 +87,15 @@ function build() {
|
||||
if pmd_ci_maven_isSnapshotBuild; then
|
||||
if [ "${PMD_CI_MAVEN_PROJECT_VERSION}" != "7.0.0-SNAPSHOT" ]; then
|
||||
pmd_ci_log_group_start "Executing PMD dogfood test with ${PMD_CI_MAVEN_PROJECT_VERSION}"
|
||||
./mvnw versions:set -DnewVersion=${PMD_CI_MAVEN_PROJECT_VERSION}-dogfood -DgenerateBackupPoms=false
|
||||
./mvnw versions:set -DnewVersion="${PMD_CI_MAVEN_PROJECT_VERSION}-dogfood" -DgenerateBackupPoms=false
|
||||
sed -i 's/<version>[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}.*<\/version>\( *<!-- pmd.dogfood.version -->\)/<version>'"${PMD_CI_MAVEN_PROJECT_VERSION}"'<\/version>\1/' pom.xml
|
||||
./mvnw verify --show-version --errors --batch-mode --no-transfer-progress "${PMD_MAVEN_EXTRA_OPTS[@]}" \
|
||||
-DskipTests \
|
||||
-Dmaven.javadoc.skip=true \
|
||||
-Dmaven.source.skip=true \
|
||||
-Dcheckstyle.skip=true \
|
||||
-Ppmd-dogfood \
|
||||
-Dpmd.dogfood.version=${PMD_CI_MAVEN_PROJECT_VERSION}
|
||||
./mvnw versions:set -DnewVersion=${PMD_CI_MAVEN_PROJECT_VERSION} -DgenerateBackupPoms=false
|
||||
-Dcheckstyle.skip=true
|
||||
./mvnw versions:set -DnewVersion="${PMD_CI_MAVEN_PROJECT_VERSION}" -DgenerateBackupPoms=false
|
||||
git checkout -- pom.xml
|
||||
pmd_ci_log_group_end
|
||||
else
|
||||
# current maven-pmd-plugin is not compatible with PMD 7 yet.
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -16,5 +16,8 @@ pmd-core/dependency-reduced-pom.xml
|
||||
vendor
|
||||
.DS_Store
|
||||
|
||||
# node modules for https://allcontributors.org/docs/en/cli/installation
|
||||
node_modules
|
||||
|
||||
# rule docs are generated
|
||||
docs/pages/pmd/rules
|
||||
|
2
.mvn/wrapper/maven-wrapper.properties
vendored
2
.mvn/wrapper/maven-wrapper.properties
vendored
@ -1,2 +1,2 @@
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.2/apache-maven-3.8.2-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
||||
|
@ -57,4 +57,20 @@ See [pmd-checkstyle-config.xml](https://github.com/pmd/build-tools/blob/master/s
|
||||
[the eclipse configuration files](https://github.com/pmd/build-tools/tree/master/eclipse) that can
|
||||
be imported into a fresh workspace.
|
||||
|
||||
## Add yourself as contributor
|
||||
|
||||
We use [All Contributors](https://allcontributors.org/en).
|
||||
|
||||
To add yourself to the table of contributors, follow the
|
||||
[bot usage instructions](https://allcontributors.org/docs/en/bot/usage) ;).
|
||||
|
||||
Or use the CLI:
|
||||
|
||||
1. Install the CLI: `npm i` (in PMD's top level directory)
|
||||
2. Add yourself: `npx all-contributors add <username> <contribution>`
|
||||
|
||||
Where `username` is your GitHub username and `contribution` is a `,`-separated list
|
||||
of contributions. See [Emoji Key](https://allcontributors.org/docs/en/emoji-key) for a list
|
||||
of valid types. Common types are: "code", "doc", "bug", "blog", "talk", "test", "tutorial".
|
||||
|
||||
See also [cli documentation](https://allcontributors.org/docs/en/cli/usage)
|
||||
|
53
README.md
53
README.md
@ -1,4 +1,4 @@
|
||||
# PMD
|
||||
# PMD - source code analyzer
|
||||
|
||||
[![Join the chat at https://gitter.im/pmd/pmd](https://badges.gitter.im/pmd/pmd.svg)](https://gitter.im/pmd/pmd?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Build Status](https://github.com/pmd/pmd/workflows/build/badge.svg?branch=master)](https://github.com/pmd/pmd/actions)
|
||||
@ -7,18 +7,42 @@
|
||||
[![Coverage Status](https://coveralls.io/repos/github/pmd/pmd/badge.svg)](https://coveralls.io/github/pmd/pmd)
|
||||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/a674ee8642ed44c6ba7633626ee95967)](https://www.codacy.com/app/pmd/pmd?utm_source=github.com&utm_medium=referral&utm_content=pmd/pmd&utm_campaign=Badge_Grade)
|
||||
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](code_of_conduct.md)
|
||||
|
||||
## About
|
||||
[![Documentation (latest)](https://img.shields.io/badge/docs-latest-green)](https://pmd.github.io/latest/)
|
||||
|
||||
**PMD** is a source code analyzer. It finds common programming flaws like unused variables, empty catch blocks,
|
||||
unnecessary object creation, and so forth. It supports Java, JavaScript, Salesforce.com Apex and Visualforce,
|
||||
unnecessary object creation, and so forth. It supports many languages. It can be extended with custom rules.
|
||||
It uses JavaCC and Antlr to parse source files into abstract syntax trees (AST) and runs rules against them to find violations.
|
||||
Rules can be written in Java or using a XPath query.
|
||||
|
||||
It supports Java, JavaScript, Salesforce.com Apex and Visualforce,
|
||||
Modelica, PLSQL, Apache Velocity, XML, XSL, Scala.
|
||||
|
||||
Additionally it includes **CPD**, the copy-paste-detector. CPD finds duplicated code in
|
||||
C/C++, C#, Dart, Fortran, Go, Groovy, Java, JavaScript, JSP, Kotlin, Lua, Matlab, Modelica,
|
||||
Objective-C, Perl, PHP, PLSQL, Python, Ruby, Salesforce.com Apex, Scala, Swift, Visualforce and XML.
|
||||
|
||||
## Support
|
||||
In the future we hope to add support for data/control flow analysis and automatic (quick) fixes where
|
||||
it makes sense.
|
||||
|
||||
## 🚀 Installation and Usage
|
||||
|
||||
Download the latest binary zip from the [releases](https://github.com/pmd/pmd/releases/latest)
|
||||
and extract it somewhere.
|
||||
|
||||
Execute `bin/run.sh pmd` or `bin\pmd.bat`.
|
||||
|
||||
See also [Getting Started](https://pmd.github.io/latest/pmd_userdocs_installation.html)
|
||||
|
||||
**Demo:**
|
||||
|
||||
This shows how PMD can detect for loops, that can be replaced by for-each loops.
|
||||
|
||||
![Demo](docs/images/userdocs/pmd-demo.gif)
|
||||
|
||||
There are plugins for Maven and Gradle as well as for various IDEs.
|
||||
See [Tools / Integrations](https://pmd.github.io/latest/pmd_userdocs_tools.html)
|
||||
|
||||
## ℹ️ How to get support?
|
||||
|
||||
* How do I? -- Ask a question on [StackOverflow](https://stackoverflow.com/questions/tagged/pmd)
|
||||
or on [discussions](https://github.com/pmd/pmd/discussions).
|
||||
@ -29,7 +53,9 @@ Objective-C, Perl, PHP, PLSQL, Python, Ruby, Salesforce.com Apex, Scala, Swift,
|
||||
* I have a quick question -- ask on our [Gitter chat](https://gitter.im/pmd/pmd).
|
||||
* Where's your documentation? -- <https://pmd.github.io/latest/>
|
||||
|
||||
## Source
|
||||
## 🤝 Contributing
|
||||
|
||||
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
|
||||
|
||||
Our latest source of PMD can be found on [GitHub](https://github.com/pmd/pmd). Fork us!
|
||||
|
||||
@ -40,6 +66,17 @@ The rule designer is developed over at [pmd/pmd-designer](https://github.com/pmd
|
||||
Please see [its README](https://github.com/pmd/pmd-designer#contributing) for
|
||||
developer documentation.
|
||||
|
||||
## Website
|
||||
## 💵 Financial Contributors
|
||||
|
||||
More information can be found on our [Website](https://pmd.github.io).
|
||||
Become a financial contributor and help us sustain our community. [Contribute](https://opencollective.com/pmd/contribute)
|
||||
|
||||
## ✨ Contributors
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification.
|
||||
Contributions of any kind welcome!
|
||||
|
||||
See [credits](docs/pages/pmd/projectdocs/credits.md) for the complete list.
|
||||
|
||||
## 📝 License
|
||||
|
||||
[BSD Style](LICENSE)
|
||||
|
@ -1,9 +1,9 @@
|
||||
repository: pmd/pmd
|
||||
|
||||
pmd:
|
||||
version: 6.37.0
|
||||
previous_version: 6.36.0
|
||||
date: 31-July-2021
|
||||
version: 6.39.0
|
||||
previous_version: 6.38.0
|
||||
date: 25-September-2021
|
||||
release_type: minor
|
||||
|
||||
# release types: major, minor, bugfix
|
||||
|
@ -385,6 +385,9 @@ entries:
|
||||
- title: Major contributions
|
||||
output: web, pdf
|
||||
subfolderitems:
|
||||
- title: Rule Guidelines
|
||||
url: /pmd_devdocs_major_rule_guidelines.html
|
||||
output: web, pdf
|
||||
- title: Adding a new language
|
||||
url: /pmd_devdocs_major_adding_new_language.html
|
||||
output: web, pdf
|
||||
|
@ -10,6 +10,22 @@ aliases:
|
||||
- &needs_typenode "The context node must be a {% jdoc jast::TypeNode %}"
|
||||
|
||||
langs:
|
||||
- name: "Any language"
|
||||
ns: "pmd"
|
||||
funs:
|
||||
- name: fileName
|
||||
returnType: "xs:string"
|
||||
shortDescription: "Returns the current filename"
|
||||
description: "Returns the current simple filename without path but including the extension.
|
||||
This can be used to write rules that check filename naming conventions.
|
||||
|
||||
<p>This function is available since PMD 6.38.0.</p>"
|
||||
notes: "The function can be called on any node."
|
||||
examples:
|
||||
- code: "//b[pmd:fileName() = 'Foo.xml']"
|
||||
outcome: "Matches any `<b>` tags in files called `Foo.xml`."
|
||||
|
||||
|
||||
- name: "Java"
|
||||
ns: "pmd-java"
|
||||
funs:
|
||||
|
@ -1177,3 +1177,8 @@ h4.panel-title {
|
||||
padding-top: 0px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.post-content .all-contributors-list img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
BIN
docs/images/userdocs/pmd-demo.gif
Normal file
BIN
docs/images/userdocs/pmd-demo.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 953 KiB |
@ -22,7 +22,7 @@ author: Jeff Jensen <jjensen@apache.org>, Andreas Dangel <andreas.dangel@adangel
|
||||
{% endunless %}
|
||||
|
||||
|
||||
## Overview
|
||||
## 💡 Overview
|
||||
|
||||
<!-- You can link to an individual panel, the id is determined from the title of the panel -->
|
||||
<!-- See custom/shuffle_panel.html for the details -->
|
||||
@ -48,17 +48,23 @@ things, PMD can be run:
|
||||
**CPD**, the **copy-paste detector**, is also distributed with PMD. You can also use it
|
||||
in a variety of ways, which are [documented here](pmd_userdocs_cpd.html).
|
||||
|
||||
## Download
|
||||
## 💾 Download
|
||||
|
||||
The latest release of PMD can be downloaded from our [Github releases page](https://github.com/pmd/pmd/releases/latest).
|
||||
|
||||
|
||||
## Documentation
|
||||
## 📖 Documentation
|
||||
|
||||
The rest of this page exposes the contents of the documentation site thematically,
|
||||
which you can further scope down using the blue filter buttons. To navigate the site,
|
||||
you may also use the search bar in the top right, or the sidebar on the left.
|
||||
|
||||
## ✨ Contributors
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification.
|
||||
Contributions of any kind welcome!
|
||||
|
||||
See [credits](pmd_projectdocs_credits.html) for the complete list.
|
||||
|
||||
<br/>
|
||||
|
||||
|
@ -125,6 +125,14 @@ 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.39.0
|
||||
|
||||
No changes.
|
||||
|
||||
#### 6.38.0
|
||||
|
||||
No changes.
|
||||
|
||||
#### 6.37.0
|
||||
|
||||
##### PMD CLI
|
||||
|
@ -0,0 +1,77 @@
|
||||
---
|
||||
title: Guidelines for standard rules
|
||||
short_title: Rule guidelines
|
||||
tags: [devdocs, extending]
|
||||
summary: "Guidelines for rules that are included in the standard distribution"
|
||||
last_updated: August, 2021
|
||||
sidebar: pmd_sidebar
|
||||
permalink: pmd_devdocs_major_rule_guidelines.html
|
||||
---
|
||||
|
||||
{% include note.html content="
|
||||
These guidelines are new and most rules don't follow these guidelines yet.
|
||||
The goal is, that eventually all rules are updated.
|
||||
" %}
|
||||
|
||||
## Why do we need these guidelines?
|
||||
|
||||
* To prevent low quality contributions
|
||||
* To reduce time reviewing rules
|
||||
|
||||
They just apply to rules included in the standard distribution.
|
||||
|
||||
## Requirements for standard rules
|
||||
|
||||
To be included in stock PMD, a rule needs
|
||||
|
||||
* Broad applicability. It may be specific to a framework, but then, this framework should be widely used
|
||||
* Solid documentation. See below
|
||||
* If it's a performance rule: solid benchmarks. No micro-optimization rules
|
||||
* No overlap with other rules
|
||||
|
||||
## Dos/Don'ts (rule rules)
|
||||
|
||||
* Rule naming
|
||||
* **Don't** put the implementation of the rule in the name, because it will be awkward
|
||||
if the scope of the rule changes
|
||||
* Eg. *SwitchStmtShouldHaveDefault* -> since enums are a thing they don't necessarily
|
||||
need to have a default anymore, they should be exhaustive. So the rule name lies now...
|
||||
* Eg. *MissingBreakInSwitch* -> it's obvious that this is supposed to find fall-through
|
||||
switches. Counting breaks is not a clever way to do it, but since it's in the name
|
||||
we can't change it without renaming the rule.
|
||||
* **Do** use rule names that name the underlying problem that violations exhibit
|
||||
* Eg. instead of *SwitchStmtShouldHaveDefault*, use *NonExhaustiveSwitchStatement* -> this
|
||||
is the problem, the description of the rule will clarify why it is a problem and how
|
||||
to fix it (add a default, or add branches, or something else in the future)
|
||||
* Eg. instead of *MissingBreakInSwitch*, use *SwitchCaseFallsThrough*
|
||||
* **Don't** create several rules for instances of the same problem
|
||||
* *EmptyIfStmt* and *EmptyWhileStmt* are actually the same problem, namely,
|
||||
that there's useless syntax in the tree.
|
||||
* **Don't** limit the rule name to strictly what the rule can do today
|
||||
* Eg. *UnusedPrivateField* is a bad name. The problem is that there is an unused field,
|
||||
not that it is private as well. If we had the ability to find unused package-private
|
||||
fields, we would report them too. So if one day we get that ability,
|
||||
using a name like *UnusedField* would allow us to keep the name.
|
||||
* Rule messages
|
||||
* **Do** write rule messages that neutrally point out a problem or construct that should
|
||||
be reviewed ("Unnecessary parentheses")
|
||||
* **Don't** write rule messages that give an order ("Avoid unnecessary parentheses")
|
||||
especially without explaining why, like here
|
||||
* **Don't** write rule messages that are tautological ("Unnecessary parentheses should be removed").
|
||||
The answer to this would be an annoyed "yes I know, so what?".
|
||||
* **Do** use Markdown in rule descriptions and break lines at a reasonable 80 chars
|
||||
* **Do** thoroughly comment rule examples. It must be obvious where to look
|
||||
* **Do** comment your xpath expressions too
|
||||
|
||||
## Rule description template
|
||||
|
||||
* What the rule reports (1 summary line)
|
||||
* Why the rule exists and where it might be useful (including, since which language version, etc)
|
||||
* Blank line
|
||||
* Explain all assumptions that the rule makes and keywords used in the previous paragraph.
|
||||
("overridden methods are ignored", "for the purposes of this rule, a 'visible' field is
|
||||
non-private").
|
||||
* Describe known limitations if any
|
||||
* Blank line
|
||||
* For each property, explain how it modifies the assumptions and why you would want to use it.
|
||||
**If you can't explain why it's there then it shouldn’t be there!**
|
File diff suppressed because it is too large
Load Diff
@ -14,154 +14,37 @@ This is a {{ site.pmd.release_type }} release.
|
||||
|
||||
### New and noteworthy
|
||||
|
||||
#### Java 17 Support
|
||||
#### All Contributors
|
||||
|
||||
This release of PMD brings support for Java 17. PMD supports [JEP 409: Sealed Classes](https://openjdk.java.net/jeps/409)
|
||||
which has been promoted to be a standard language feature of Java 17.
|
||||
PMD follows the [All Contributors](https://allcontributors.org/) specification.
|
||||
Contributions of any kind welcome!
|
||||
|
||||
PMD also supports [JEP 406: Pattern Matching for switch (Preview)](https://openjdk.java.net/jeps/406) as a preview
|
||||
language feature. In order to analyze a project with PMD that uses these language features, you'll need to enable
|
||||
it via the environment variable `PMD_JAVA_OPTS` and select the new language version `17-preview`:
|
||||
|
||||
export PMD_JAVA_OPTS=--enable-preview
|
||||
./run.sh pmd -language java -version 17-preview ...
|
||||
|
||||
Note: Support for Java 15 preview language features have been removed. The version "15-preview" is no longer available.
|
||||
|
||||
#### Updated PMD Designer
|
||||
|
||||
This PMD release ships a new version of the pmd-designer.
|
||||
For the changes, see [PMD Designer Changelog](https://github.com/pmd/pmd-designer/releases/tag/6.37.0).
|
||||
|
||||
#### New rules
|
||||
|
||||
This release ships with 3 new Java rules.
|
||||
|
||||
* {% rule java/bestpractices/PrimitiveWrapperInstantiation %} reports usages of primitive wrapper
|
||||
constructors. They are deprecated since Java 9 and should not be used.
|
||||
|
||||
```xml
|
||||
<rule ref="category/java/bestpractices.xml/PrimitiveWrapperInstantiation" />
|
||||
```
|
||||
|
||||
The rule is part of the quickstart.xml ruleset.
|
||||
|
||||
* {% rule java/bestpractices/SimplifiableTestAssertion %} suggests rewriting
|
||||
some test assertions to be more readable.
|
||||
|
||||
```xml
|
||||
<rule ref="category/java/bestpractices.xml/SimplifiableTestAssertion" />
|
||||
```
|
||||
|
||||
The rule is part of the quickstart.xml ruleset.
|
||||
|
||||
* {% rule java/errorprone/ReturnEmptyCollectionRatherThanNull %} suggests returning empty collections / arrays
|
||||
instead of null.
|
||||
|
||||
```xml
|
||||
<rule ref="category/java/errorprone.xml/ReturnEmptyCollectionRatherThanNull" />
|
||||
```
|
||||
|
||||
The rule is part of the quickstart.xml ruleset.
|
||||
|
||||
#### Renamed rules
|
||||
|
||||
* The Java rule {% rule java/errorprone/MissingBreakInSwitch %} has been renamed to
|
||||
{% rule java/errorprone/ImplicitSwitchFallThrough %} (category error prone) to better reflect the rule's
|
||||
purpose: The rule finds implicit fall-through cases in switch statements, which are most
|
||||
likely unexpected. The old rule name described only one way how to avoid a fall-through,
|
||||
namely using `break` but `continue`, `throw` and `return` avoid a fall-through
|
||||
as well. This enables us to improve this rule in the future.
|
||||
|
||||
#### Deprecated rules
|
||||
|
||||
* The following Java rules are deprecated and removed from the quickstart ruleset,
|
||||
as the new rule {% rule java/bestpractices/SimplifiableTestAssertion %} merges
|
||||
their functionality:
|
||||
* {% rule java/bestpractices/UseAssertEqualsInsteadOfAssertTrue %}
|
||||
* {% rule java/bestpractices/UseAssertNullInsteadOfAssertTrue %}
|
||||
* {% rule java/bestpractices/UseAssertSameInsteadOfAssertTrue %}
|
||||
* {% rule java/bestpractices/UseAssertTrueInsteadOfAssertEquals %}
|
||||
* {% rule java/design/SimplifyBooleanAssertion %}
|
||||
|
||||
* The Java rule {% rule java/errorprone/ReturnEmptyArrayRatherThanNull %} is deprecated and removed from
|
||||
the quickstart ruleset, as the new rule {% rule java/errorprone/ReturnEmptyCollectionRatherThanNull %}
|
||||
supersedes it.
|
||||
|
||||
* The following Java rules are deprecated and removed from the quickstart ruleset,
|
||||
as the new rule {% rule java/bestpractices/PrimitiveWrapperInstantiation %} merges
|
||||
their functionality:
|
||||
* {% rule java/performance/BooleanInstantiation %}
|
||||
* {% rule java/performance/ByteInstantiation %}
|
||||
* {% rule java/performance/IntegerInstantiation %}
|
||||
* {% rule java/performance/LongInstantiation %}
|
||||
* {% rule java/performance/ShortInstantiation %}
|
||||
|
||||
* The Java rule {% rule java/performance/UnnecessaryWrapperObjectCreation %} is deprecated
|
||||
with no planned replacement before PMD 7. In it's current state, the rule is not useful
|
||||
as it finds only contrived cases of creating a primitive wrapper and unboxing it explicitly
|
||||
in the same expression. In PMD 7 this and more cases will be covered by a
|
||||
new rule `UnnecessaryBoxing`.
|
||||
See [credits](https://pmd.github.io/latest/pmd_projectdocs_credits.html) for our complete contributors list.
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* apex
|
||||
* [#3201](https://github.com/pmd/pmd/issues/3201): \[apex] ApexCRUDViolation doesn't report Database class DMLs, inline no-arg object instantiations and inline list initialization
|
||||
* [#3329](https://github.com/pmd/pmd/issues/3329): \[apex] ApexCRUDViolation doesn't report SOQL for loops
|
||||
* core
|
||||
* [#1603](https://github.com/pmd/pmd/issues/1603): \[core] Language version comparison
|
||||
* [#2133](https://github.com/pmd/pmd/issues/2133): \[xml] Allow to check Salesforce XML Metadata using XPath rules
|
||||
* [#3377](https://github.com/pmd/pmd/issues/3377): \[core] NPE when specifying report file in current directory in PMD CLI
|
||||
* [#3387](https://github.com/pmd/pmd/issues/3387): \[core] CPD should avoid unnecessary copies when running with --skip-lexical-errors
|
||||
* java-bestpractices
|
||||
* [#2908](https://github.com/pmd/pmd/issues/2908): \[java] Merge Junit assertion simplification rules
|
||||
* [#3235](https://github.com/pmd/pmd/issues/3235): \[java] UseTryWithResources false positive when closeable is provided as a method argument or class field
|
||||
* [#3499](https://github.com/pmd/pmd/pull/3499): \[core] Fix XPath rulechain with combined node tests
|
||||
* java-errorprone
|
||||
* [#3361](https://github.com/pmd/pmd/issues/3361): \[java] Rename rule MissingBreakInSwitch to ImplicitSwitchFallThrough
|
||||
* [#3382](https://github.com/pmd/pmd/pull/3382): \[java] New rule ReturnEmptyCollectionRatherThanNull
|
||||
* java-performance
|
||||
* [#3420](https://github.com/pmd/pmd/issues/3420): \[java] NPE in `InefficientStringBuffering` with Records
|
||||
* [#3493](https://github.com/pmd/pmd/pull/3493): \[java] AvoidAccessibilityAlteration: add tests and fix rule
|
||||
* javascript
|
||||
* [#3516](https://github.com/pmd/pmd/pull/3516): \[javascript] NPE while creating rule violation when specifying explicit line numbers
|
||||
* plsql
|
||||
* [#3487](https://github.com/pmd/pmd/issues/3487): \[plsql] Parsing exception OPEN ref_cursor_name FOR statement
|
||||
* [#3515](https://github.com/pmd/pmd/issues/3515): \[plsql] Parsing exception SELECT...INTO on Associative Arrays Types
|
||||
|
||||
### API Changes
|
||||
|
||||
#### PMD CLI
|
||||
|
||||
* PMD has a new CLI option `-force-language`. With that a language can be forced to be used for all input files,
|
||||
irrespective of filenames. When using this option, the automatic language selection by extension is disabled
|
||||
and all files are tried to be parsed with the given language. Parsing errors are ignored and unparsable files
|
||||
are skipped.
|
||||
|
||||
This option allows to use the xml language for files, that don't use xml as extension.
|
||||
See also the examples on [PMD CLI reference](pmd_userdocs_cli_reference.html#analyze-other-xml-formats).
|
||||
|
||||
#### Experimental APIs
|
||||
|
||||
* The AST types and APIs around Sealed Classes are not experimental anymore:
|
||||
* {% jdoc !!java::lang.java.ast.ASTClassOrInterfaceDeclaration#isSealed() %},
|
||||
{% jdoc !!java::lang.java.ast.ASTClassOrInterfaceDeclaration#isNonSealed() %},
|
||||
{% jdoc !!java::lang.java.ast.ASTClassOrInterfaceDeclaration#getPermittedSubclasses() %}
|
||||
* {% jdoc java::lang.java.ast.ASTPermitsList %}
|
||||
|
||||
#### Internal API
|
||||
|
||||
Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
|
||||
You can identify them with the `@InternalApi` annotation. You'll also get a deprecation warning.
|
||||
|
||||
* The inner class {% jdoc !!core::cpd.TokenEntry.State %} is considered to be internal API.
|
||||
It will probably be moved away with PMD 7.
|
||||
No changes.
|
||||
|
||||
### External Contributions
|
||||
|
||||
* [#3367](https://github.com/pmd/pmd/pull/3367): \[apex] Check SOQL CRUD on for loops - [Jonathan Wiesel](https://github.com/jonathanwiesel)
|
||||
* [#3373](https://github.com/pmd/pmd/pull/3373): \[apex] Add ApexCRUDViolation support for database class, inline no-arg object construction DML and inline list initialization DML - [Jonathan Wiesel](https://github.com/jonathanwiesel)
|
||||
* [#3385](https://github.com/pmd/pmd/pull/3385): \[core] CPD: Optimize --skip-lexical-errors option - [Woongsik Choi](https://github.com/woongsikchoi)
|
||||
* [#3388](https://github.com/pmd/pmd/pull/3388): \[doc] Add Code Inspector in the list of tools - [Julien Delange](https://github.com/juli1)
|
||||
* [#3417](https://github.com/pmd/pmd/pull/3417): \[core] Support forcing a specific language from the command-line - [Aidan Harding](https://github.com/aidan-harding)
|
||||
* [#3516](https://github.com/pmd/pmd/pull/3516): \[javascript] NPE while creating rule violation when specifying explicit line numbers - [Kevin Guerra](https://github.com/kevingnet)
|
||||
|
||||
### Stats
|
||||
* 82 commits
|
||||
* 29 closed tickets & PRs
|
||||
* Days since last release: 35
|
||||
* 37 commits
|
||||
* 10 closed tickets & PRs
|
||||
* Days since last release: 27
|
||||
|
||||
{% endtocmaker %}
|
||||
|
||||
|
@ -5,6 +5,211 @@ permalink: pmd_release_notes_old.html
|
||||
|
||||
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
|
||||
|
||||
## 28-August-2021 - 6.38.0
|
||||
|
||||
The PMD team is pleased to announce PMD 6.38.0.
|
||||
|
||||
This is a minor release.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
* [Fixed Issues](#fixed-issues)
|
||||
* [External Contributions](#external-contributions)
|
||||
* [Stats](#stats)
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* apex
|
||||
* [#3462](https://github.com/pmd/pmd/issues/3462): \[apex] SOQL performed in a for-each loop doesn't trigger ApexCRUDViolationRule
|
||||
* [#3484](https://github.com/pmd/pmd/issues/3484): \[apex] ApexCRUDViolationRule maintains state across files
|
||||
* core
|
||||
* [#3446](https://github.com/pmd/pmd/issues/3446): \[core] Allow XPath rules to access the current file name
|
||||
* java-bestpractices
|
||||
* [#3403](https://github.com/pmd/pmd/issues/3403): \[java] MethodNamingConventions junit5TestPattern does not detect parameterized tests
|
||||
|
||||
### External Contributions
|
||||
|
||||
* [#3445](https://github.com/pmd/pmd/pull/3445): \[java] Fix #3403 about MethodNamingConventions and JUnit5 parameterized tests - [Cyril Sicard](https://github.com/CyrilSicard)
|
||||
* [#3470](https://github.com/pmd/pmd/pull/3470): \[apex] Fix ApexCRUDViolationRule - add super call - [Josh Feingold](https://github.com/jfeingold35)
|
||||
|
||||
### Stats
|
||||
* 32 commits
|
||||
* 8 closed tickets & PRs
|
||||
* Days since last release: 27
|
||||
|
||||
## 28-August-2021 - 6.38.0-SNAPSHOT
|
||||
|
||||
The PMD team is pleased to announce PMD 6.38.0-SNAPSHOT.
|
||||
|
||||
This is a minor release.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
* [New and noteworthy](#new-and-noteworthy)
|
||||
* [Java 17 Support](#java-17-support)
|
||||
* [Updated PMD Designer](#updated-pmd-designer)
|
||||
* [New rules](#new-rules)
|
||||
* [Renamed rules](#renamed-rules)
|
||||
* [Deprecated rules](#deprecated-rules)
|
||||
* [Fixed Issues](#fixed-issues)
|
||||
* [API Changes](#api-changes)
|
||||
* [PMD CLI](#pmd-cli)
|
||||
* [Experimental APIs](#experimental-apis)
|
||||
* [Internal API](#internal-api)
|
||||
* [External Contributions](#external-contributions)
|
||||
* [Stats](#stats)
|
||||
|
||||
### New and noteworthy
|
||||
|
||||
#### Java 17 Support
|
||||
|
||||
This release of PMD brings support for Java 17. PMD supports [JEP 409: Sealed Classes](https://openjdk.java.net/jeps/409)
|
||||
which has been promoted to be a standard language feature of Java 17.
|
||||
|
||||
PMD also supports [JEP 406: Pattern Matching for switch (Preview)](https://openjdk.java.net/jeps/406) as a preview
|
||||
language feature. In order to analyze a project with PMD that uses these language features, you'll need to enable
|
||||
it via the environment variable `PMD_JAVA_OPTS` and select the new language version `17-preview`:
|
||||
|
||||
export PMD_JAVA_OPTS=--enable-preview
|
||||
./run.sh pmd -language java -version 17-preview ...
|
||||
|
||||
Note: Support for Java 15 preview language features have been removed. The version "15-preview" is no longer available.
|
||||
|
||||
#### Updated PMD Designer
|
||||
|
||||
This PMD release ships a new version of the pmd-designer.
|
||||
For the changes, see [PMD Designer Changelog](https://github.com/pmd/pmd-designer/releases/tag/6.37.0).
|
||||
|
||||
#### New rules
|
||||
|
||||
This release ships with 3 new Java rules.
|
||||
|
||||
* [`PrimitiveWrapperInstantiation`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_bestpractices.html#primitivewrapperinstantiation) reports usages of primitive wrapper
|
||||
constructors. They are deprecated since Java 9 and should not be used.
|
||||
|
||||
```xml
|
||||
<rule ref="category/java/bestpractices.xml/PrimitiveWrapperInstantiation" />
|
||||
```
|
||||
|
||||
The rule is part of the quickstart.xml ruleset.
|
||||
|
||||
* [`SimplifiableTestAssertion`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_bestpractices.html#simplifiabletestassertion) suggests rewriting
|
||||
some test assertions to be more readable.
|
||||
|
||||
```xml
|
||||
<rule ref="category/java/bestpractices.xml/SimplifiableTestAssertion" />
|
||||
```
|
||||
|
||||
The rule is part of the quickstart.xml ruleset.
|
||||
|
||||
* [`ReturnEmptyCollectionRatherThanNull`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_errorprone.html#returnemptycollectionratherthannull) suggests returning empty collections / arrays
|
||||
instead of null.
|
||||
|
||||
```xml
|
||||
<rule ref="category/java/errorprone.xml/ReturnEmptyCollectionRatherThanNull" />
|
||||
```
|
||||
|
||||
The rule is part of the quickstart.xml ruleset.
|
||||
|
||||
#### Renamed rules
|
||||
|
||||
* The Java rule [`MissingBreakInSwitch`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_errorprone.html#missingbreakinswitch) has been renamed to
|
||||
[`ImplicitSwitchFallThrough`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_errorprone.html#implicitswitchfallthrough) (category error prone) to better reflect the rule's
|
||||
purpose: The rule finds implicit fall-through cases in switch statements, which are most
|
||||
likely unexpected. The old rule name described only one way how to avoid a fall-through,
|
||||
namely using `break` but `continue`, `throw` and `return` avoid a fall-through
|
||||
as well. This enables us to improve this rule in the future.
|
||||
|
||||
#### Deprecated rules
|
||||
|
||||
* The following Java rules are deprecated and removed from the quickstart ruleset,
|
||||
as the new rule [`SimplifiableTestAssertion`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_bestpractices.html#simplifiabletestassertion) merges
|
||||
their functionality:
|
||||
* [`UseAssertEqualsInsteadOfAssertTrue`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_bestpractices.html#useassertequalsinsteadofasserttrue)
|
||||
* [`UseAssertNullInsteadOfAssertTrue`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_bestpractices.html#useassertnullinsteadofasserttrue)
|
||||
* [`UseAssertSameInsteadOfAssertTrue`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_bestpractices.html#useassertsameinsteadofasserttrue)
|
||||
* [`UseAssertTrueInsteadOfAssertEquals`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_bestpractices.html#useasserttrueinsteadofassertequals)
|
||||
* [`SimplifyBooleanAssertion`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_design.html#simplifybooleanassertion)
|
||||
|
||||
* The Java rule [`ReturnEmptyArrayRatherThanNull`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_errorprone.html#returnemptyarrayratherthannull) is deprecated and removed from
|
||||
the quickstart ruleset, as the new rule [`ReturnEmptyCollectionRatherThanNull`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_errorprone.html#returnemptycollectionratherthannull)
|
||||
supersedes it.
|
||||
|
||||
* The following Java rules are deprecated and removed from the quickstart ruleset,
|
||||
as the new rule [`PrimitiveWrapperInstantiation`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_bestpractices.html#primitivewrapperinstantiation) merges
|
||||
their functionality:
|
||||
* [`BooleanInstantiation`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_performance.html#booleaninstantiation)
|
||||
* [`ByteInstantiation`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_performance.html#byteinstantiation)
|
||||
* [`IntegerInstantiation`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_performance.html#integerinstantiation)
|
||||
* [`LongInstantiation`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_performance.html#longinstantiation)
|
||||
* [`ShortInstantiation`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_performance.html#shortinstantiation)
|
||||
|
||||
* The Java rule [`UnnecessaryWrapperObjectCreation`](https://pmd.github.io/pmd-6.38.0-SNAPSHOT/pmd_rules_java_performance.html#unnecessarywrapperobjectcreation) is deprecated
|
||||
with no planned replacement before PMD 7. In it's current state, the rule is not useful
|
||||
as it finds only contrived cases of creating a primitive wrapper and unboxing it explicitly
|
||||
in the same expression. In PMD 7 this and more cases will be covered by a
|
||||
new rule `UnnecessaryBoxing`.
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* apex
|
||||
* [#3201](https://github.com/pmd/pmd/issues/3201): \[apex] ApexCRUDViolation doesn't report Database class DMLs, inline no-arg object instantiations and inline list initialization
|
||||
* [#3329](https://github.com/pmd/pmd/issues/3329): \[apex] ApexCRUDViolation doesn't report SOQL for loops
|
||||
* core
|
||||
* [#1603](https://github.com/pmd/pmd/issues/1603): \[core] Language version comparison
|
||||
* [#2133](https://github.com/pmd/pmd/issues/2133): \[xml] Allow to check Salesforce XML Metadata using XPath rules
|
||||
* [#3377](https://github.com/pmd/pmd/issues/3377): \[core] NPE when specifying report file in current directory in PMD CLI
|
||||
* [#3387](https://github.com/pmd/pmd/issues/3387): \[core] CPD should avoid unnecessary copies when running with --skip-lexical-errors
|
||||
* java-bestpractices
|
||||
* [#2908](https://github.com/pmd/pmd/issues/2908): \[java] Merge Junit assertion simplification rules
|
||||
* [#3235](https://github.com/pmd/pmd/issues/3235): \[java] UseTryWithResources false positive when closeable is provided as a method argument or class field
|
||||
* java-errorprone
|
||||
* [#3361](https://github.com/pmd/pmd/issues/3361): \[java] Rename rule MissingBreakInSwitch to ImplicitSwitchFallThrough
|
||||
* [#3382](https://github.com/pmd/pmd/pull/3382): \[java] New rule ReturnEmptyCollectionRatherThanNull
|
||||
* java-performance
|
||||
* [#3420](https://github.com/pmd/pmd/issues/3420): \[java] NPE in `InefficientStringBuffering` with Records
|
||||
|
||||
### API Changes
|
||||
|
||||
#### PMD CLI
|
||||
|
||||
* PMD has a new CLI option `-force-language`. With that a language can be forced to be used for all input files,
|
||||
irrespective of filenames. When using this option, the automatic language selection by extension is disabled
|
||||
and all files are tried to be parsed with the given language. Parsing errors are ignored and unparsable files
|
||||
are skipped.
|
||||
|
||||
This option allows to use the xml language for files, that don't use xml as extension.
|
||||
See also the examples on [PMD CLI reference](pmd_userdocs_cli_reference.html#analyze-other-xml-formats).
|
||||
|
||||
#### Experimental APIs
|
||||
|
||||
* The AST types and APIs around Sealed Classes are not experimental anymore:
|
||||
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.38.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceDeclaration.html#isSealed()"><code>ASTClassOrInterfaceDeclaration#isSealed</code></a>,
|
||||
<a href="https://docs.pmd-code.org/apidocs/pmd-java/6.38.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceDeclaration.html#isNonSealed()"><code>ASTClassOrInterfaceDeclaration#isNonSealed</code></a>,
|
||||
<a href="https://docs.pmd-code.org/apidocs/pmd-java/6.38.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceDeclaration.html#getPermittedSubclasses()"><code>ASTClassOrInterfaceDeclaration#getPermittedSubclasses</code></a>
|
||||
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.38.0-SNAPSHOT/net/sourceforge/pmd/lang/java/ast/ASTPermitsList.html#"><code>ASTPermitsList</code></a>
|
||||
|
||||
#### Internal API
|
||||
|
||||
Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
|
||||
You can identify them with the `@InternalApi` annotation. You'll also get a deprecation warning.
|
||||
|
||||
* The inner class <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.38.0-SNAPSHOT/net/sourceforge/pmd/cpd/TokenEntry.State.html#"><code>net.sourceforge.pmd.cpd.TokenEntry.State</code></a> is considered to be internal API.
|
||||
It will probably be moved away with PMD 7.
|
||||
|
||||
### External Contributions
|
||||
|
||||
* [#3367](https://github.com/pmd/pmd/pull/3367): \[apex] Check SOQL CRUD on for loops - [Jonathan Wiesel](https://github.com/jonathanwiesel)
|
||||
* [#3373](https://github.com/pmd/pmd/pull/3373): \[apex] Add ApexCRUDViolation support for database class, inline no-arg object construction DML and inline list initialization DML - [Jonathan Wiesel](https://github.com/jonathanwiesel)
|
||||
* [#3385](https://github.com/pmd/pmd/pull/3385): \[core] CPD: Optimize --skip-lexical-errors option - [Woongsik Choi](https://github.com/woongsikchoi)
|
||||
* [#3388](https://github.com/pmd/pmd/pull/3388): \[doc] Add Code Inspector in the list of tools - [Julien Delange](https://github.com/juli1)
|
||||
* [#3417](https://github.com/pmd/pmd/pull/3417): \[core] Support forcing a specific language from the command-line - [Aidan Harding](https://github.com/aidan-harding)
|
||||
|
||||
### Stats
|
||||
* 82 commits
|
||||
* 29 closed tickets & PRs
|
||||
* Days since last release: 35
|
||||
|
||||
## 26-June-2021 - 6.36.0
|
||||
|
||||
The PMD team is pleased to announce PMD 6.36.0.
|
||||
|
1160
package-lock.json
generated
Normal file
1160
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
5
package.json
Normal file
5
package.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"all-contributors-cli": "^6.20.0"
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>6.37.0</version>
|
||||
<version>6.39.0</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
<artifactId>pmd</artifactId>
|
||||
<version>6.37.0</version>
|
||||
<version>6.39.0</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -4,9 +4,10 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.ast;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
import apex.jorje.data.Identifier;
|
||||
@ -72,29 +73,21 @@ public class ASTLiteralExpression extends AbstractApexNode<LiteralExpression> {
|
||||
public String getName() {
|
||||
if (getParent() instanceof ASTNewKeyValueObjectExpression) {
|
||||
ASTNewKeyValueObjectExpression parent = (ASTNewKeyValueObjectExpression) getParent();
|
||||
try {
|
||||
Field exprField = NameValueParameter.class.getDeclaredField("expression");
|
||||
exprField.setAccessible(true);
|
||||
Optional<NameValueParameter> parameter = parent.node.getParameters().stream().filter(p -> {
|
||||
try {
|
||||
return this.node.equals(exprField.get(p));
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
return false;
|
||||
}
|
||||
}).findFirst();
|
||||
Optional<NameValueParameter> parameter = parent.node.getParameters().stream().filter(p -> {
|
||||
try {
|
||||
return this.node.equals(FieldUtils.readDeclaredField(p, "expression", true));
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
return false;
|
||||
}
|
||||
}).findFirst();
|
||||
|
||||
Field nameField = NameValueParameter.class.getDeclaredField("name");
|
||||
nameField.setAccessible(true);
|
||||
return parameter.map(p -> {
|
||||
try {
|
||||
return (Identifier) nameField.get(p);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}).map(Identifier::getValue).orElse(null);
|
||||
} catch (NoSuchFieldException | SecurityException e1) {
|
||||
return null;
|
||||
}
|
||||
return parameter.map(p -> {
|
||||
try {
|
||||
return (Identifier) FieldUtils.readDeclaredField(p, "name", true);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}).map(Identifier::getValue).orElse(null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.ast;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
|
||||
import apex.jorje.semantic.ast.statement.TypeWhenBlock;
|
||||
|
||||
@ -22,9 +22,7 @@ public final class ASTTypeWhenBlock extends AbstractApexNode<TypeWhenBlock> {
|
||||
public String getName() {
|
||||
// unfortunately the name is not exposed...
|
||||
try {
|
||||
Field nameField = TypeWhenBlock.class.getDeclaredField("name");
|
||||
nameField.setAccessible(true);
|
||||
return String.valueOf(nameField.get(node));
|
||||
return String.valueOf(FieldUtils.readDeclaredField(node, "name", true));
|
||||
} catch (SecurityException | ReflectiveOperationException e) {
|
||||
return null;
|
||||
}
|
||||
|
@ -5,11 +5,11 @@
|
||||
package net.sourceforge.pmd.lang.apex.ast;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.apache.commons.lang3.reflect.MethodUtils;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
@ -139,11 +139,8 @@ public class CompilerService {
|
||||
"compilerContext", true);
|
||||
|
||||
for (CodeUnit unit : allUnits) {
|
||||
Method getOperation = CompilerStage.ADDITIONAL_VALIDATE.getDeclaringClass()
|
||||
.getDeclaredMethod("getOperation");
|
||||
getOperation.setAccessible(true);
|
||||
CompilerOperation operation = (CompilerOperation) getOperation
|
||||
.invoke(CompilerStage.ADDITIONAL_VALIDATE);
|
||||
CompilerOperation operation = (CompilerOperation)
|
||||
MethodUtils.invokeMethod(CompilerStage.ADDITIONAL_VALIDATE, true, "getOperation");
|
||||
operation.invoke(compilerContext, unit);
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||
|
@ -155,6 +155,12 @@ public abstract class AbstractApexRule extends AbstractRule
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// The following APIs are identical to those in ApexParserVisitorAdapter.
|
||||
// Due to Java single inheritance, it is preferred to extend from the more
|
||||
// complex Rule base class instead of from relatively simple Visitor.
|
||||
//
|
||||
// CPD-OFF
|
||||
|
||||
@Override
|
||||
public Object visit(ApexNode<?> node, Object data) {
|
||||
@ -648,4 +654,6 @@ public abstract class AbstractApexRule extends AbstractRule
|
||||
public Object visit(ASTEmptyReferenceExpression node, Object data) {
|
||||
return visit((ApexNode<?>) node, data);
|
||||
}
|
||||
|
||||
// CPD-ON
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ public class AvoidDmlStatementsInLoopsRule extends AbstractAvoidNodeInLoopsRule
|
||||
setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false);
|
||||
}
|
||||
|
||||
// CPD-OFF - the same visits are in the replacement rule OperationWithLimitsInLoopRule
|
||||
@Override
|
||||
public Object visit(ASTDmlDeleteStatement node, Object data) {
|
||||
return checkForViolation(node, data);
|
||||
@ -53,4 +54,5 @@ public class AvoidDmlStatementsInLoopsRule extends AbstractAvoidNodeInLoopsRule
|
||||
public Object visit(ASTDmlUpsertStatement node, Object data) {
|
||||
return checkForViolation(node, data);
|
||||
}
|
||||
// CPD-ON
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.sourceforge.pmd.RuleContext;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTAssignmentExpression;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTBlockStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTDmlDeleteStatement;
|
||||
@ -85,10 +86,10 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
|
||||
|
||||
private static final Pattern WITH_SECURITY_ENFORCED = Pattern.compile("(?is).*[^']\\s*WITH\\s+SECURITY_ENFORCED\\s*[^']*");
|
||||
|
||||
private final Map<String, String> varToTypeMapping = new HashMap<>();
|
||||
private final ListMultimap<String, String> typeToDMLOperationMapping = ArrayListMultimap.create();
|
||||
private final Map<String, String> checkedTypeToDMLOperationViaESAPI = new HashMap<>();
|
||||
private final Map<String, ASTMethod> classMethods = new WeakHashMap<>();
|
||||
private Map<String, String> varToTypeMapping;
|
||||
private ListMultimap<String, String> typeToDMLOperationMapping;
|
||||
private Map<String, String> checkedTypeToDMLOperationViaESAPI;
|
||||
private Map<String, ASTMethod> classMethods;
|
||||
private String className;
|
||||
|
||||
public ApexCRUDViolationRule() {
|
||||
@ -97,6 +98,19 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
|
||||
setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(RuleContext ctx) {
|
||||
// At the start of each rule execution, these member variables need to be fresh. So they're initialized in the
|
||||
// .start() method instead of the constructor, since .start() is called before every execution.
|
||||
varToTypeMapping = new HashMap<>();
|
||||
typeToDMLOperationMapping = ArrayListMultimap.create();
|
||||
checkedTypeToDMLOperationViaESAPI = new HashMap<>();
|
||||
classMethods = new WeakHashMap<>();
|
||||
className = null;
|
||||
super.start(ctx);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object visit(ASTUserClass node, Object data) {
|
||||
if (Helper.isTestMethodOrClass(node) || Helper.isSystemLevelClass(node)) {
|
||||
@ -246,7 +260,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
|
||||
checkForAccessibility(soql, data);
|
||||
}
|
||||
|
||||
return data;
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
private void addVariableToMapping(final String variableName, final String type) {
|
||||
@ -539,7 +553,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
|
||||
}
|
||||
|
||||
|
||||
private void validateCRUDCheckPresent(final ApexNode<?> node, final Object data, final String crudMethod,
|
||||
private boolean validateCRUDCheckPresent(final ApexNode<?> node, final Object data, final String crudMethod,
|
||||
final String typeCheck) {
|
||||
boolean missingKey = !typeToDMLOperationMapping.containsKey(typeCheck);
|
||||
boolean isImproperDMLCheck = !isProperESAPICheckForDML(typeCheck, crudMethod);
|
||||
@ -548,6 +562,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
|
||||
//if condition returns true, add violation, otherwise return.
|
||||
if (isImproperDMLCheck && noSecurityEnforced) {
|
||||
addViolation(data, node);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
boolean properChecksHappened = false;
|
||||
@ -566,8 +581,10 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
|
||||
|
||||
if (!properChecksHappened) {
|
||||
addViolation(data, node);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkForAccessibility(final ASTSoqlExpression node, Object data) {
|
||||
@ -591,7 +608,7 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
|
||||
if (wrappingMethod != null) {
|
||||
returnType = getReturnType(wrappingMethod);
|
||||
}
|
||||
|
||||
boolean violationAdded = false;
|
||||
final ASTVariableDeclaration variableDecl = node.getFirstParentOfType(ASTVariableDeclaration.class);
|
||||
if (variableDecl != null) {
|
||||
String type = variableDecl.getType();
|
||||
@ -600,15 +617,20 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
|
||||
.append(":").append(type);
|
||||
|
||||
if (typesFromSOQL.isEmpty()) {
|
||||
validateCRUDCheckPresent(node, data, ANY, typeCheck.toString());
|
||||
violationAdded = validateCRUDCheckPresent(node, data, ANY, typeCheck.toString());
|
||||
} else {
|
||||
for (String typeFromSOQL : typesFromSOQL) {
|
||||
validateCRUDCheckPresent(node, data, ANY, typeFromSOQL);
|
||||
violationAdded |= validateCRUDCheckPresent(node, data, ANY, typeFromSOQL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If the node's already in violation, we don't need to keep checking.
|
||||
if (violationAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ASTAssignmentExpression assignment = node.getFirstParentOfType(ASTAssignmentExpression.class);
|
||||
if (assignment != null) {
|
||||
final ASTVariableExpression variable = assignment.getFirstChildOfType(ASTVariableExpression.class);
|
||||
@ -617,10 +639,10 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
|
||||
if (varToTypeMapping.containsKey(variableWithClass)) {
|
||||
String type = varToTypeMapping.get(variableWithClass);
|
||||
if (typesFromSOQL.isEmpty()) {
|
||||
validateCRUDCheckPresent(node, data, ANY, type);
|
||||
violationAdded = validateCRUDCheckPresent(node, data, ANY, type);
|
||||
} else {
|
||||
for (String typeFromSOQL : typesFromSOQL) {
|
||||
validateCRUDCheckPresent(node, data, ANY, typeFromSOQL);
|
||||
violationAdded |= validateCRUDCheckPresent(node, data, ANY, typeFromSOQL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -628,17 +650,27 @@ public class ApexCRUDViolationRule extends AbstractApexRule {
|
||||
|
||||
}
|
||||
|
||||
// If the node's already in violation, we don't need to keep checking.
|
||||
if (violationAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ASTReturnStatement returnStatement = node.getFirstParentOfType(ASTReturnStatement.class);
|
||||
if (returnStatement != null) {
|
||||
if (typesFromSOQL.isEmpty()) {
|
||||
validateCRUDCheckPresent(node, data, ANY, returnType);
|
||||
violationAdded = validateCRUDCheckPresent(node, data, ANY, returnType);
|
||||
} else {
|
||||
for (String typeFromSOQL : typesFromSOQL) {
|
||||
validateCRUDCheckPresent(node, data, ANY, typeFromSOQL);
|
||||
violationAdded |= validateCRUDCheckPresent(node, data, ANY, typeFromSOQL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the node's already in violation, we don't need to keep checking.
|
||||
if (violationAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ASTForEachStatement forEachStatement = node.getFirstParentOfType(ASTForEachStatement.class);
|
||||
if (forEachStatement != null) {
|
||||
if (typesFromSOQL.isEmpty()) {
|
||||
|
@ -4,15 +4,8 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.rule.security;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTDmlDeleteStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTDmlInsertStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTDmlMergeStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTDmlUndeleteStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTDmlUpdateStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTDmlUpsertStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTField;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclaration;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression;
|
||||
@ -62,17 +55,7 @@ public final class Helper {
|
||||
* @return true if found DML operations in node descendants
|
||||
*/
|
||||
static boolean foundAnyDML(final ApexNode<?> node) {
|
||||
|
||||
final List<ASTDmlUpsertStatement> dmlUpsertStatement = node.findDescendantsOfType(ASTDmlUpsertStatement.class);
|
||||
final List<ASTDmlUpdateStatement> dmlUpdateStatement = node.findDescendantsOfType(ASTDmlUpdateStatement.class);
|
||||
final List<ASTDmlUndeleteStatement> dmlUndeleteStatement = node
|
||||
.findDescendantsOfType(ASTDmlUndeleteStatement.class);
|
||||
final List<ASTDmlMergeStatement> dmlMergeStatement = node.findDescendantsOfType(ASTDmlMergeStatement.class);
|
||||
final List<ASTDmlInsertStatement> dmlInsertStatement = node.findDescendantsOfType(ASTDmlInsertStatement.class);
|
||||
final List<ASTDmlDeleteStatement> dmlDeleteStatement = node.findDescendantsOfType(ASTDmlDeleteStatement.class);
|
||||
|
||||
return !dmlUpsertStatement.isEmpty() || !dmlUpdateStatement.isEmpty() || !dmlUndeleteStatement.isEmpty()
|
||||
|| !dmlMergeStatement.isEmpty() || !dmlInsertStatement.isEmpty() || !dmlDeleteStatement.isEmpty();
|
||||
return net.sourceforge.pmd.lang.apex.rule.internal.Helper.foundAnyDML(node);
|
||||
}
|
||||
|
||||
static boolean isMethodName(final ASTMethodCallExpression methodNode, final String className,
|
||||
@ -89,25 +72,7 @@ public final class Helper {
|
||||
}
|
||||
|
||||
static boolean isMethodCallChain(final ASTMethodCallExpression methodNode, final String... methodNames) {
|
||||
String methodName = methodNames[methodNames.length - 1];
|
||||
if (Helper.isMethodName(methodNode, methodName)) {
|
||||
final ASTReferenceExpression reference = methodNode.getFirstChildOfType(ASTReferenceExpression.class);
|
||||
if (reference != null) {
|
||||
final ASTMethodCallExpression nestedMethod = reference
|
||||
.getFirstChildOfType(ASTMethodCallExpression.class);
|
||||
if (nestedMethod != null) {
|
||||
String[] newMethodNames = Arrays.copyOf(methodNames, methodNames.length - 1);
|
||||
return isMethodCallChain(nestedMethod, newMethodNames);
|
||||
} else {
|
||||
String[] newClassName = Arrays.copyOf(methodNames, methodNames.length - 1);
|
||||
if (newClassName.length == 1) {
|
||||
return Helper.isMethodName(methodNode, newClassName[0], methodName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return net.sourceforge.pmd.lang.apex.rule.internal.Helper.isMethodCallChain(methodNode, methodNames);
|
||||
}
|
||||
|
||||
static String getFQVariableName(final ASTVariableExpression variable) {
|
||||
|
@ -20,6 +20,7 @@ import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.ast.xpath.internal.FileNameXPathFunction;
|
||||
|
||||
import apex.jorje.semantic.ast.compilation.Compilation;
|
||||
|
||||
@ -40,6 +41,15 @@ public class ApexParserTest extends ApexParserTestBase {
|
||||
assertEquals(4, methods.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileName() {
|
||||
String code = "class Outer { class Inner {}}";
|
||||
|
||||
ASTUserClass rootNode = (ASTUserClass) parse(code, "src/filename.cls");
|
||||
|
||||
assertEquals("filename.cls", rootNode.getUserMap().get(FileNameXPathFunction.FILE_NAME_KEY));
|
||||
}
|
||||
|
||||
private String testCodeForLineNumbers =
|
||||
"public class SimpleClass {\n" // line 1
|
||||
+ " public void method1() {\n" // line 2
|
||||
|
@ -15,6 +15,10 @@ public class ApexParserTestBase {
|
||||
return apex.parse(code);
|
||||
}
|
||||
|
||||
protected ApexNode<? extends Compilation> parse(String code, String fileName) {
|
||||
return apex.parse(code, null, fileName);
|
||||
}
|
||||
|
||||
protected ApexNode<Compilation> parseResource(String code) {
|
||||
return apex.parseResource(code);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user