Merge branch 'pmd/7.0.x' into pmd7-junit5-part3
This commit is contained in:
commit
0d2acf6000
@ -7070,6 +7070,24 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "liamsharp",
|
||||
"name": "Liam Sharp",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6429288?v=4",
|
||||
"profile": "https://github.com/liamsharp",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "hassanalamibmx",
|
||||
"name": "Hassan ALAMI",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/67870478?v=4",
|
||||
"profile": "https://github.com/hassanalamibmx",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
@ -265,7 +265,7 @@ function pmd_ci_dogfood() {
|
||||
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
|
||||
if [ "${PMD_CI_MAVEN_PROJECT_VERSION}" = "7.0.0-SNAPSHOT" ]; then
|
||||
sed -i 's/pmd-dogfood-config\.xml/pmd-dogfood-config7.xml/' pom.xml
|
||||
mpmdVersion=(-Denforcer.skip=true -Dpmd.plugin.version=3.18.0-pmd7-SNAPSHOT)
|
||||
mpmdVersion=(-Denforcer.skip=true -Dpmd.plugin.version=3.20.1-pmd-7-SNAPSHOT)
|
||||
fi
|
||||
./mvnw verify --show-version --errors --batch-mode --no-transfer-progress "${PMD_MAVEN_EXTRA_OPTS[@]}" \
|
||||
"${mpmdVersion[@]}" \
|
||||
|
@ -134,6 +134,25 @@ index 6021fa574d..15d29ed699 100644
|
||||
EOF
|
||||
) | patch --strip=1
|
||||
|
||||
# Patch 4: Add https://maven.repository.redhat.com/ga/ as repository in order to resolve
|
||||
# dependency com.ibm.websphere/uow/6.0.2.17
|
||||
# See https://spring.io/blog/2020/10/29/notice-of-permissions-changes-to-repo-spring-io-fall-and-winter-2020
|
||||
(cat <<EOF
|
||||
diff --git a/build.gradle b/build.gradle
|
||||
index 6021fa57..8319ff76 100644
|
||||
--- a/build.gradle
|
||||
+++ b/build.gradle
|
||||
@@ -291,6 +291,7 @@ configure(allprojects) { project ->
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
+ maven { url "https://maven.repository.redhat.com/ga/" }
|
||||
maven { url "https://repo.spring.io/libs-spring-framework-build" }
|
||||
}
|
||||
}
|
||||
EOF
|
||||
) | patch --strip=1
|
||||
|
||||
./gradlew --console=plain --build-cache --no-daemon --max-workers=4 build testClasses -x test -x javadoc -x api -x asciidoctor -x asciidoctorPdf
|
||||
./gradlew --console=plain --build-cache --no-daemon --max-workers=4 createSquishClasspath -q > classpath.txt
|
||||
]]></build-command>
|
||||
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -55,7 +55,7 @@ jobs:
|
||||
run: |
|
||||
echo "LANG=en_US.UTF-8" >> $GITHUB_ENV
|
||||
echo "MAVEN_OPTS=-Dmaven.wagon.httpconnectionManager.ttlSeconds=180 -Dmaven.wagon.http.retryHandler.count=3 -DautoReleaseAfterClose=true -DstagingProgressTimeoutMinutes=30" >> $GITHUB_ENV
|
||||
echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/19/scripts" >> $GITHUB_ENV
|
||||
echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/20/scripts" >> $GITHUB_ENV
|
||||
- name: Check Environment
|
||||
shell: bash
|
||||
run: |
|
||||
|
2
.github/workflows/git-repo-sync.yml
vendored
2
.github/workflows/git-repo-sync.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
echo "LANG=en_US.UTF-8" >> $GITHUB_ENV
|
||||
echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/19/scripts" >> $GITHUB_ENV
|
||||
echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/20/scripts" >> $GITHUB_ENV
|
||||
- name: Sync
|
||||
run: .ci/git-repo-sync.sh
|
||||
shell: bash
|
||||
|
2
.github/workflows/troubleshooting.yml
vendored
2
.github/workflows/troubleshooting.yml
vendored
@ -36,7 +36,7 @@ jobs:
|
||||
run: |
|
||||
echo "LANG=en_US.UTF-8" >> $GITHUB_ENV
|
||||
echo "MAVEN_OPTS=-Dmaven.wagon.httpconnectionManager.ttlSeconds=180 -Dmaven.wagon.http.retryHandler.count=3 -DstagingProgressTimeoutMinutes=30" >> $GITHUB_ENV
|
||||
echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/19/scripts" >> $GITHUB_ENV
|
||||
echo "PMD_CI_SCRIPTS_URL=https://raw.githubusercontent.com/pmd/build-tools/20/scripts" >> $GITHUB_ENV
|
||||
- name: Check Environment
|
||||
shell: bash
|
||||
run: |
|
||||
|
12
Gemfile.lock
12
Gemfile.lock
@ -9,7 +9,7 @@ GEM
|
||||
nap
|
||||
open4 (~> 1.3)
|
||||
colored2 (3.1.2)
|
||||
concurrent-ruby (1.1.10)
|
||||
concurrent-ruby (1.2.0)
|
||||
cork (0.3.0)
|
||||
colored2 (~> 3.1)
|
||||
danger (9.1.0)
|
||||
@ -28,7 +28,7 @@ GEM
|
||||
differ (0.1.2)
|
||||
et-orbi (1.2.7)
|
||||
tzinfo
|
||||
faraday (1.10.2)
|
||||
faraday (1.10.3)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
@ -53,10 +53,10 @@ GEM
|
||||
faraday-patron (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.3)
|
||||
fugit (1.8.0)
|
||||
fugit (1.8.1)
|
||||
et-orbi (~> 1, >= 1.2.7)
|
||||
raabro (~> 1.4)
|
||||
git (1.13.0)
|
||||
git (1.13.1)
|
||||
addressable (~> 2.8)
|
||||
rchardet (~> 1.8)
|
||||
kramdown (2.4.0)
|
||||
@ -69,7 +69,7 @@ GEM
|
||||
multipart-post (2.2.3)
|
||||
nap (1.1.0)
|
||||
no_proxy_fix (0.1.2)
|
||||
nokogiri (1.13.10)
|
||||
nokogiri (1.14.0)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
octokit (5.6.1)
|
||||
@ -114,4 +114,4 @@ DEPENDENCIES
|
||||
safe_yaml
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.4
|
||||
2.4.5
|
||||
|
@ -1,7 +1,7 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (6.0.6)
|
||||
activesupport (6.0.6.1)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
@ -14,8 +14,8 @@ GEM
|
||||
execjs
|
||||
coffee-script-source (1.11.1)
|
||||
colorator (1.1.0)
|
||||
commonmarker (0.23.6)
|
||||
concurrent-ruby (1.1.10)
|
||||
commonmarker (0.23.7)
|
||||
concurrent-ruby (1.2.0)
|
||||
dnsruby (1.61.9)
|
||||
simpleidn (~> 0.1)
|
||||
em-websocket (0.5.3)
|
||||
@ -25,7 +25,7 @@ GEM
|
||||
ffi (>= 1.15.0)
|
||||
eventmachine (1.2.7)
|
||||
execjs (2.8.1)
|
||||
faraday (2.7.2)
|
||||
faraday (2.7.4)
|
||||
faraday-net_http (>= 2.0, < 3.1)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-net_http (3.0.2)
|
||||
@ -263,4 +263,4 @@ DEPENDENCIES
|
||||
webrick
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.4
|
||||
2.4.5
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -122,7 +122,8 @@ The tool comes with a rather extensive help text, simply running with `--help`!
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="-language,-l"
|
||||
option_arg="lang"
|
||||
description="Specify the language PMD should use. Used together with `-version`. See also [Supported Languages](#supported-languages)."
|
||||
description="Specify the language PMD should use. Used together with `-version`. See also [Supported Languages](#supported-languages).
|
||||
<p><span class=\"label label-default\">Deprecated</span> since PMD 6.52.0. Use `--use-version` instead.</p>"
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--minimum-priority"
|
||||
option_arg="priority"
|
||||
@ -147,13 +148,17 @@ The tool comes with a rather extensive help text, simply running with `--help`!
|
||||
description="Specifies a property for the report renderer. The option can be specified several times.
|
||||
<p>Using `--help` will provide a complete list of supported properties for each report format</p>"
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--relativize-paths-with,-z"
|
||||
option_arg="path"
|
||||
description="Path relative to which directories are rendered in the report. This option allows
|
||||
shortening directories in the report; without it, paths are rendered as mentioned in the source directory (option \"--dir\").
|
||||
The option can be repeated, in which case the shortest relative path will be used.
|
||||
If the root path is mentioned (e.g. \"/\" or \"C:\\\"), then the paths will be rendered as absolute."
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--report-file,-r"
|
||||
option_arg="path"
|
||||
description="Path to a file to which report output is written. The file is created if it does not exist. If this option is not specified, the report is rendered to standard output."
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--short-names"
|
||||
description="Prints shortened filenames in the report."
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--show-suppressed"
|
||||
description="Causes the suppressed rule violations to be added to the report."
|
||||
%}
|
||||
|
@ -345,9 +345,16 @@ Was expecting one of:
|
||||
XML with a XSL transformation applied.
|
||||
|
||||
PMD provides one built-in stylesheet, that is used by default, if no other
|
||||
stylesheet with the property "xsltFilename" is specified. It is called [pmd-nicerhtml.xsl](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/resources/pmd-nicerhtml.xsl) and can be used for customization.
|
||||
stylesheet with the property "xsltFilename" is specified. It is called
|
||||
[pmd-nicerhtml.xsl](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/resources/pmd-nicerhtml.xsl)
|
||||
and can be used for customization.
|
||||
|
||||
[Example with pmd-nicerhtml.xsl](report-examples/pmd-report-pmd-nicerhtml.html)
|
||||
There are many other stylesheets available online: <https://github.com/pmd/pmd/tree/master/pmd-core/etc/xslt>.
|
||||
|
||||
Examples:
|
||||
* [Example with pmd-nicerhtml.xsl](report-examples/pmd-report-pmd-nicerhtml.html)
|
||||
* [Example with html-report-v2.xslt](report-examples/html-report-v2.html) - includes charts. It requires javascript enabled and uses
|
||||
[jQuery](https://jquery.com/), [DataTables](https://datatables.net/), and [Vega](https://vega.github.io/vega/) for charting.
|
||||
|
||||
**Properties:**
|
||||
|
||||
|
@ -77,11 +77,6 @@ The examples below won't repeat this taskdef element, as this is always required
|
||||
<td>The rule priority threshold; rules with lower priority than they will not be used</td>
|
||||
<td>No</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>shortFilenames</td>
|
||||
<td>Places truncated filenames in the report. This can reduce your report file size by 15%-20%.</td>
|
||||
<td>No</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>failuresPropertyName</td>
|
||||
<td>A property name to plug the number of rule violations into when the task finishes</td>
|
||||
@ -187,7 +182,7 @@ automatically and the latest language version is used.
|
||||
|
||||
<target name="pmd">
|
||||
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask"/>
|
||||
<pmd shortFilenames="true">
|
||||
<pmd>
|
||||
<ruleset>rulesets/java/quickstart.xml</ruleset>
|
||||
<ruleset>config/my-ruleset.xml</ruleset>
|
||||
<fileset dir="/usr/local/j2sdk1.4.1_01/src/">
|
||||
@ -199,6 +194,11 @@ automatically and the latest language version is used.
|
||||
`fileset` nested element - specify the actual java source files, that PMD should analyze. You can use multiple
|
||||
fileset elements. See [FileSet](https://ant.apache.org/manual/Types/fileset.html) for the syntax and usage.
|
||||
|
||||
`relativizePathsWith` nested element - configures the paths relative to which directories are rendered in the report.
|
||||
This option allows shortening directories in the report; without it, paths are rendered as absolute paths.
|
||||
The option can be repeated, in which case the shortest relative path will be used.
|
||||
It is a [path-like structure](https://ant.apache.org/manual/using.html#path).
|
||||
|
||||
### Language version selection
|
||||
|
||||
PMD selects the language automatically using the file extension. If multiple versions of a language are
|
||||
@ -410,7 +410,7 @@ An HTML report with the "linkPrefix" and "linePrefix" properties:
|
||||
|
||||
<target name="pmd">
|
||||
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask"/>
|
||||
<pmd rulesetfiles="rulesets/java/quickstart.xml" shortFilenames="true">
|
||||
<pmd rulesetfiles="rulesets/java/quickstart.xml">
|
||||
<formatter type="html" toFile="pmd_report.html">
|
||||
<param name="linkPrefix" value="https://maven.apache.org/plugins/maven-pmd-plugin/xref/"/>
|
||||
<param name="linePrefix" value="L"/>
|
||||
@ -418,6 +418,9 @@ An HTML report with the "linkPrefix" and "linePrefix" properties:
|
||||
<fileset dir="/usr/local/j2sdk1.4.1_01/src/">
|
||||
<include name="java/lang/*.java"/>
|
||||
</fileset>
|
||||
<relativizePathsWith>
|
||||
<pathelement location="/usr/local/j2sdk1.4.1_01/src/"/>
|
||||
</relativizePathsWith>
|
||||
</pmd>
|
||||
</target>
|
||||
|
||||
|
@ -19,10 +19,35 @@ This is a {{ site.pmd.release_type }} release.
|
||||
|
||||
### New and noteworthy
|
||||
|
||||
#### New report format html-report-v2.xslt
|
||||
|
||||
Thanks to @mohan-chinnappan-n a new PMD report format has been added which features a data table
|
||||
with charting functions. It uses an XSLT stylesheet to convert PMD's XML format into HTML.
|
||||
|
||||
See [the example report](report-examples/html-report-v2.html).
|
||||
|
||||
### Fixed Issues
|
||||
* apex-bestpractices
|
||||
* [#2669](https://github.com/pmd/pmd/issues/2669): \[apex] UnusedLocalVariable false positive in dynamic SOQL
|
||||
* core
|
||||
* [#4026](https://github.com/pmd/pmd/issues/4026): \[cli] Filenames printed as absolute paths in the report despite parameter `--short-names`
|
||||
* [#4279](https://github.com/pmd/pmd/issues/4279): \[core] Can not set ruleset property value to empty
|
||||
* [#4329](https://github.com/pmd/pmd/pull/4329): \[core] Refactor usage of snakeyaml
|
||||
* [#4340](https://github.com/pmd/pmd/issues/4340): \[core] Allow to filter found matches in CPDReport
|
||||
* java
|
||||
* [#4364](https://github.com/pmd/pmd/issues/4364): \[java] Parsing error with textblock containing quote followed by two backslashes
|
||||
* testing
|
||||
* [#4236](https://github.com/pmd/pmd/issues/4236): \[test] kotest logs look broken
|
||||
|
||||
### API Changes
|
||||
|
||||
#### PMD CLI
|
||||
|
||||
* PMD now supports a new `--relativize-paths-with` flag (or short `-z`), which replaces `--short-names`.
|
||||
It serves the same purpose: Shortening the pathnames in the reports. However, with the new flag it's possible
|
||||
to explicitly define one or more pathnames that should be used as the base when creating relative paths.
|
||||
The old flag `--short-names` is deprecated.
|
||||
|
||||
#### Deprecated APIs
|
||||
|
||||
##### For removal
|
||||
@ -31,12 +56,39 @@ This is a {{ site.pmd.release_type }} release.
|
||||
always `Version.CURRENT`, as the apex compiler integration doesn't use additional information which Apex version
|
||||
actually is used. Therefore, this method can't be used to determine the Apex version of the project
|
||||
that is being analyzed.
|
||||
* {% jdoc !!core::cpd.CPDConfiguration#setEncoding(java.lang.String) %} and
|
||||
{% jdoc !!core::cpd.CPDConfiguration#getEncoding() %}. Use the methods
|
||||
{% jdoc core::AbstractConfiguration#getSourceEncoding() %} and
|
||||
{% jdoc core::AbstractConfiguration#setSourceEncoding(java.lang.String) %} instead. Both are available
|
||||
for `CPDConfiguration` which extends `AbstractConfiguration`.
|
||||
* {% jdoc test::cli.BaseCLITest %} and {% jdoc test::cli.BaseCPDCLITest %} have been deprecated for removal without
|
||||
replacement. CLI tests should be done in pmd-core only (and in PMD7 in pmd-cli). Individual language modules
|
||||
shouldn't need to test the CLI integration logic again. Instead, the individual language modules should test their
|
||||
functionality as unit tests.
|
||||
* {% jdoc core::cpd.CPDConfiguration.LanguageConverter %}
|
||||
|
||||
* {% jdoc !!core::lang.document.FileCollector#addZipFile(java.nio.file.Path) %} has been deprecated. It is replaced
|
||||
by {% jdoc !!core::lang.document.FileCollector#addZipFileWithContent(java.nio.file.Path) %} which directly adds the
|
||||
content of the zip file for analysis.
|
||||
|
||||
* {% jdoc !!core::PMDConfiguration#setReportShortNames(boolean) %} and
|
||||
{% jdoc !!core::PMDConfiguration#isReportShortNames() %} have been deprecated for removal.
|
||||
Use {% jdoc !!core::PMDConfiguration#addRelativizeRoot(java.nio.file.Path) %} instead.
|
||||
|
||||
##### Internal APIs
|
||||
|
||||
* {% jdoc core::renderers.CSVWriter %}
|
||||
* Some fields in {% jdoc test::ant.AbstractAntTestHelper %}
|
||||
|
||||
##### Experimental APIs
|
||||
|
||||
* CPDReport has a new method which limited mutation of a given report:
|
||||
* {%jdoc core::cpd.CPDReport#filterMatches(net.sourceforge.pmd.util.Predicate) %} creates a new CPD report
|
||||
with some matches removed with a given predicate based filter.
|
||||
|
||||
### External Contributions
|
||||
* [#4110](https://github.com/pmd/pmd/pull/4110): \[apex] Feature/unused variable bind false positive with dynamic SOQL - [Thomas Prouvot](https://github.com/tprouvot) (@tprouvot)
|
||||
* [#4125](https://github.com/pmd/pmd/pull/4125): \[core] New report format html-report-v2.xslt to provide html with datatable and chart features - [Mohan Chinnappan](https://github.com/mohan-chinnappan-n) - (@mohan-chinnappan-n)
|
||||
* [#4280](https://github.com/pmd/pmd/pull/4280): \[apex] Deprecate ApexRootNode.getApexVersion - [Aaron Hurst](https://github.com/aaronhurst-google) (@aaronhurst-google)
|
||||
* [#4285](https://github.com/pmd/pmd/pull/4285): \[java] CommentDefaultAccessModifier - add co.elastic.clients.util.VisibleForTesting as default suppressed annotation - [Matthew Luckam](https://github.com/mluckam) (@mluckam)
|
||||
|
||||
|
1209
docs/report-examples/html-report-v2.html
Normal file
1209
docs/report-examples/html-report-v2.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -33,7 +33,6 @@ import net.sourceforge.pmd.cpd.ReportException;
|
||||
import net.sourceforge.pmd.cpd.SimpleRenderer;
|
||||
import net.sourceforge.pmd.cpd.Tokenizer;
|
||||
import net.sourceforge.pmd.cpd.XMLRenderer;
|
||||
import net.sourceforge.pmd.cpd.renderer.CPDRendererAdapter;
|
||||
import net.sourceforge.pmd.cpd.renderer.CPDReportRenderer;
|
||||
|
||||
/**
|
||||
@ -94,7 +93,7 @@ public class CPDTask extends Task {
|
||||
CPDConfiguration config = new CPDConfiguration();
|
||||
config.setMinimumTileSize(minimumTokenCount);
|
||||
config.setLanguage(createLanguage());
|
||||
config.setEncoding(encoding);
|
||||
config.setSourceEncoding(encoding);
|
||||
config.setSkipDuplicates(skipDuplicateFiles);
|
||||
config.setSkipLexicalErrors(skipLexicalErrors);
|
||||
|
||||
@ -190,9 +189,9 @@ public class CPDTask extends Task {
|
||||
|
||||
private CPDReportRenderer createRenderer() {
|
||||
if (TEXT_FORMAT.equals(format)) {
|
||||
return new CPDRendererAdapter(new SimpleRenderer());
|
||||
return new SimpleRenderer();
|
||||
} else if (CSV_FORMAT.equals(format)) {
|
||||
return new CPDRendererAdapter(new CSVRenderer());
|
||||
return new CSVRenderer();
|
||||
}
|
||||
return new XMLRenderer();
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
package net.sourceforge.pmd.ant;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
@ -14,8 +15,10 @@ import org.apache.tools.ant.Task;
|
||||
import org.apache.tools.ant.types.FileSet;
|
||||
import org.apache.tools.ant.types.Path;
|
||||
import org.apache.tools.ant.types.Reference;
|
||||
import org.apache.tools.ant.types.Resource;
|
||||
|
||||
import net.sourceforge.pmd.RulePriority;
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.ant.internal.PMDTaskImpl;
|
||||
|
||||
/**
|
||||
@ -30,7 +33,7 @@ public class PMDTask extends Task {
|
||||
private final List<FileSet> filesets = new ArrayList<>();
|
||||
private boolean failOnError;
|
||||
private boolean failOnRuleViolation;
|
||||
private boolean shortFilenames;
|
||||
private final List<Path> relativizePathsWith = new ArrayList<>();
|
||||
private String suppressMarker;
|
||||
private String rulesetFiles;
|
||||
private boolean noRuleSetCompatibility;
|
||||
@ -94,10 +97,6 @@ public class PMDTask extends Task {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void setShortFilenames(boolean reportShortNames) {
|
||||
this.shortFilenames = reportShortNames;
|
||||
}
|
||||
|
||||
public void setSuppressMarker(String suppressMarker) {
|
||||
this.suppressMarker = suppressMarker;
|
||||
}
|
||||
@ -207,10 +206,6 @@ public class PMDTask extends Task {
|
||||
return failOnRuleViolation;
|
||||
}
|
||||
|
||||
public boolean isShortFilenames() {
|
||||
return shortFilenames;
|
||||
}
|
||||
|
||||
public String getSuppressMarker() {
|
||||
return suppressMarker;
|
||||
}
|
||||
@ -271,4 +266,23 @@ public class PMDTask extends Task {
|
||||
public void setNoCache(boolean noCache) {
|
||||
this.noCache = noCache;
|
||||
}
|
||||
|
||||
public void addRelativizePathsWith(Path relativizePathsWith) {
|
||||
this.relativizePathsWith.add(relativizePathsWith);
|
||||
}
|
||||
|
||||
public List<Path> getRelativizePathsWith() {
|
||||
return relativizePathsWith;
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
public List<java.nio.file.Path> getRelativizeRoots() {
|
||||
List<java.nio.file.Path> paths = new ArrayList<>();
|
||||
for (Path path : getRelativizePathsWith()) {
|
||||
for (Resource resource : path) {
|
||||
paths.add(Paths.get(resource.toString()));
|
||||
}
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ public class PMDTaskImpl {
|
||||
private Project project;
|
||||
|
||||
public PMDTaskImpl(PMDTask task) {
|
||||
configuration.setReportShortNames(task.isShortFilenames());
|
||||
configuration.addRelativizeRoots(task.getRelativizeRoots());
|
||||
if (task.getSuppressMarker() != null) {
|
||||
configuration.setSuppressMarker(task.getSuppressMarker());
|
||||
}
|
||||
@ -103,7 +103,6 @@ public class PMDTaskImpl {
|
||||
project.log("Setting suppress marker to be " + configuration.getSuppressMarker(), Project.MSG_VERBOSE);
|
||||
}
|
||||
|
||||
|
||||
List<String> ruleSetPaths = expandRuleSetPaths(configuration.getRuleSetPaths());
|
||||
// don't let PmdAnalysis.create create rulesets itself.
|
||||
configuration.setRuleSets(Collections.emptyList());
|
||||
@ -116,9 +115,6 @@ public class PMDTaskImpl {
|
||||
|
||||
for (FileSet fileset : filesets) {
|
||||
DirectoryScanner ds = fileset.getDirectoryScanner(project);
|
||||
if (configuration.isReportShortNames()) {
|
||||
pmd.files().relativizeWith(ds.getBasedir().getPath());
|
||||
}
|
||||
for (String srcFile : ds.getIncludedFiles()) {
|
||||
pmd.files().addFile(ds.getBasedir().toPath().resolve(srcFile));
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -69,14 +70,14 @@ class PMDTaskTest extends AbstractAntTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithShortFilenames() throws IOException {
|
||||
executeTarget("testWithShortFilenames");
|
||||
void testRelativizeWith() throws IOException {
|
||||
executeTarget("testRelativizeWith");
|
||||
|
||||
try (InputStream in = Files.newInputStream(Paths.get("target/pmd-ant-test.txt"))) {
|
||||
String actual = IOUtil.readToString(in, StandardCharsets.UTF_8);
|
||||
// remove any trailing newline
|
||||
actual = actual.trim();
|
||||
assertThat(actual, containsString("sample.dummy:1:\tSampleXPathRule:\tTest Rule 2"));
|
||||
actual = actual.replaceAll("\n|\r", "");
|
||||
assertThat(actual, containsString("src" + File.separator + "sample.dummy:1:\tSampleXPathRule:\tTest Rule 2"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,25 +25,31 @@
|
||||
<pmd />
|
||||
</target>
|
||||
|
||||
<target name="testWithShortFilenames">
|
||||
<pmd noCache="true" shortFilenames="true">
|
||||
<target name="testRelativizeWith">
|
||||
<pmd noCache="true">
|
||||
<!-- note: this ruleset is in pmd-core/src/test/resources -->
|
||||
<ruleset>rulesets/dummy/basic.xml</ruleset>
|
||||
<formatter type="text" toFile="${pmd.home}/target/pmd-ant-test.txt" />
|
||||
<fileset dir="${pmd.home}/src/test/resources/net/sourceforge/pmd/ant/src">
|
||||
<fileset dir="${pmd.home}/src/test/resources/net/sourceforge/pmd/ant/">
|
||||
<include name="**/*dummy"/>
|
||||
</fileset>
|
||||
<relativizePathsWith>
|
||||
<pathelement location="${pmd.home}/src/test/resources/net/sourceforge/pmd/ant"/>
|
||||
</relativizePathsWith>
|
||||
</pmd>
|
||||
</target>
|
||||
|
||||
<target name="testXmlFormatter">
|
||||
<pmd noCache="true" shortFilenames="true">
|
||||
<pmd noCache="true">
|
||||
<!-- note: this ruleset is in pmd-core/src/test/resources -->
|
||||
<ruleset>rulesets/dummy/basic.xml</ruleset>
|
||||
<formatter type="xml" toFile="${pmd.home}/target/pmd-ant-xml.xml" />
|
||||
<fileset dir="${pmd.home}/src/test/resources/net/sourceforge/pmd/ant/src">
|
||||
<include name="**/*dummy"/>
|
||||
</fileset>
|
||||
<relativizePathsWith>
|
||||
<pathelement location="${pmd.home}/src/test/resources/net/sourceforge/pmd/ant/src"/>
|
||||
</relativizePathsWith>
|
||||
</pmd>
|
||||
</target>
|
||||
</project>
|
||||
|
@ -104,11 +104,15 @@
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<!-- apex jorje actually depends on 1.7.20 (https://github.com/forcedotcom/salesforcedx-vscode/commit/631b8cfb85cff5e989bfea13bca681b6cedcb003) -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- apex jorje actually depends on 1.17 (https://github.com/forcedotcom/salesforcedx-vscode/commit/631b8cfb85cff5e989bfea13bca681b6cedcb003)
|
||||
however, it is not really needed, so we don't add it here as a dependency,
|
||||
so that it doesn't end up in pmd-dist
|
||||
-->
|
||||
<!--<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<!-- apex jorje actually depends on 1.17 (https://github.com/forcedotcom/salesforcedx-vscode/commit/631b8cfb85cff5e989bfea13bca681b6cedcb003) -->
|
||||
</dependency>
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>aopalliance</groupId>
|
||||
<artifactId>aopalliance</artifactId>
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.ast;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -60,6 +62,11 @@ public final class ASTApexFile extends AbstractApexNode<AstNode> implements Root
|
||||
}
|
||||
|
||||
public List<Issue> getGlobalIssues() {
|
||||
return multifileAnalysis.getFileIssues(getAstInfo().getTextDocument().getPathId());
|
||||
String filename = getAstInfo().getTextDocument().getPathId();
|
||||
if (filename.length() > 7 && "file://".equalsIgnoreCase(filename.substring(0, 7))) {
|
||||
URI uri = URI.create(filename);
|
||||
filename = Paths.get(uri).toString();
|
||||
}
|
||||
return multifileAnalysis.getFileIssues(filename);
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,21 @@
|
||||
package net.sourceforge.pmd.lang.apex.rule.bestpractices;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTBlockStatement;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTLiteralExpression;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTReferenceExpression;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTVariableExpression;
|
||||
@ -19,6 +28,13 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule;
|
||||
import net.sourceforge.pmd.lang.rule.RuleTargetSelector;
|
||||
|
||||
public class UnusedLocalVariableRule extends AbstractApexRule {
|
||||
private static final Set<String> DATABASE_QUERY_METHODS = new HashSet<>(Arrays.asList(
|
||||
"Database.query".toLowerCase(Locale.ROOT),
|
||||
"Database.getQueryLocator".toLowerCase(Locale.ROOT),
|
||||
"Database.countQuery".toLowerCase(Locale.ROOT)
|
||||
));
|
||||
|
||||
private static final Pattern BINDING_VARIABLE = Pattern.compile("(?i):([a-z0-9]+)");
|
||||
|
||||
@Override
|
||||
protected @NonNull RuleTargetSelector buildTargetSelector() {
|
||||
@ -52,7 +68,56 @@ public class UnusedLocalVariableRule extends AbstractApexRule {
|
||||
}
|
||||
}
|
||||
|
||||
List<String> soqlBindingVariables = findBindingsInSOQLStringLiterals(variableContext);
|
||||
if (soqlBindingVariables.contains(variableName.toLowerCase(Locale.ROOT))) {
|
||||
return data;
|
||||
}
|
||||
|
||||
addViolation(data, node, variableName);
|
||||
return data;
|
||||
}
|
||||
|
||||
private List<String> findBindingsInSOQLStringLiterals(ASTBlockStatement variableContext) {
|
||||
List<String> bindingVariables = new ArrayList<>();
|
||||
|
||||
List<ASTMethodCallExpression> methodCalls = variableContext.findDescendantsOfType(ASTMethodCallExpression.class)
|
||||
.stream()
|
||||
.filter(m -> DATABASE_QUERY_METHODS.contains(m.getFullMethodName().toLowerCase(Locale.ROOT)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
methodCalls.forEach(databaseMethodCall -> {
|
||||
List<String> stringLiterals = new ArrayList<>();
|
||||
stringLiterals.addAll(databaseMethodCall.findDescendantsOfType(ASTLiteralExpression.class)
|
||||
.stream()
|
||||
.filter(ASTLiteralExpression::isString)
|
||||
.map(ASTLiteralExpression::getImage)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
databaseMethodCall.findDescendantsOfType(ASTVariableExpression.class).forEach(variableUsage -> {
|
||||
String referencedVariable = variableUsage.getImage();
|
||||
|
||||
// Search other usages of the same variable within this code block
|
||||
variableContext.findDescendantsOfType(ASTVariableExpression.class)
|
||||
.stream()
|
||||
.filter(usage -> referencedVariable.equalsIgnoreCase(usage.getImage()))
|
||||
.forEach(usage -> {
|
||||
stringLiterals.addAll(usage.getParent()
|
||||
.findChildrenOfType(ASTLiteralExpression.class)
|
||||
.stream()
|
||||
.filter(ASTLiteralExpression::isString)
|
||||
.map(ASTLiteralExpression::getImage)
|
||||
.collect(Collectors.toList()));
|
||||
});
|
||||
});
|
||||
|
||||
stringLiterals.forEach(s -> {
|
||||
Matcher matcher = BINDING_VARIABLE.matcher(s);
|
||||
while (matcher.find()) {
|
||||
bindingVariables.add(matcher.group(1).toLowerCase(Locale.ROOT));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return bindingVariables;
|
||||
}
|
||||
}
|
||||
|
@ -109,6 +109,53 @@ class Foo {
|
||||
return bar;
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
]]>
|
||||
</code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>[apex] UnusedLocalVariable - false positive on string query #2669</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code>
|
||||
<![CDATA[
|
||||
class Foo {
|
||||
public Database.QueryLocator start1(Database.BatchableContext BC) {
|
||||
String customValue = 'Test';
|
||||
String query = 'SELECT Id FROM Case ';
|
||||
query += 'WHERE CustomField__c = :customValue ';
|
||||
return Database.getQueryLocator(query);
|
||||
}
|
||||
|
||||
public Database.QueryLocator start2(Database.BatchableContext BC) {
|
||||
String customValue = 'Test';
|
||||
return Database.getQueryLocator('SELECT Id From Case WHERE CustomField__c = :customValue');
|
||||
}
|
||||
|
||||
public void doQuery1() {
|
||||
String customValue = 'Test';
|
||||
String query = 'SELECT Id FROM Case ';
|
||||
query += 'WHERE CustomField__c = :customValue ';
|
||||
Database.query(query);
|
||||
}
|
||||
|
||||
public void doQuery2() {
|
||||
String customValue = 'Test';
|
||||
Database.query('SELECT Id From Case WHERE CustomField__c = :customValue');
|
||||
}
|
||||
|
||||
public void doCount1() {
|
||||
String customValue = 'Test';
|
||||
String query = 'SELECT Id FROM Case ';
|
||||
query += 'WHERE CustomField__c = :customValue ';
|
||||
Database.countQuery(query);
|
||||
}
|
||||
|
||||
public void doCount2() {
|
||||
String customValue = 'Test';
|
||||
Database.countQuery('SELECT Id From Case WHERE CustomField__c = :customValue');
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</code>
|
||||
</test-code>
|
||||
</test-data>
|
||||
|
@ -9,7 +9,7 @@ import java.util.concurrent.Callable;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.event.Level;
|
||||
|
||||
import net.sourceforge.pmd.cli.internal.ExecutionResult;
|
||||
import net.sourceforge.pmd.cli.internal.CliExitCode;
|
||||
import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration;
|
||||
|
||||
import picocli.CommandLine.Model.CommandSpec;
|
||||
@ -46,7 +46,7 @@ public abstract class AbstractPmdSubcommand implements Callable<Integer> {
|
||||
// no-op, children may override
|
||||
}
|
||||
|
||||
protected abstract ExecutionResult execute();
|
||||
protected abstract CliExitCode execute();
|
||||
|
||||
private void setupCliLogger() {
|
||||
// only reconfigure logging, if debug flag was used on command line
|
||||
|
@ -17,7 +17,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.sourceforge.pmd.cli.commands.typesupport.internal.CpdLanguageTypeSupport;
|
||||
import net.sourceforge.pmd.cli.internal.ExecutionResult;
|
||||
import net.sourceforge.pmd.cli.internal.CliExitCode;
|
||||
import net.sourceforge.pmd.cpd.CPD;
|
||||
import net.sourceforge.pmd.cpd.CPDConfiguration;
|
||||
import net.sourceforge.pmd.cpd.CPDReport;
|
||||
@ -127,7 +127,7 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExecutionResult execute() {
|
||||
protected CliExitCode execute() {
|
||||
final Logger logger = LoggerFactory.getLogger(CpdCommand.class);
|
||||
|
||||
// TODO : Create a new CpdAnalysis to match PmdAnalysis
|
||||
@ -141,15 +141,15 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
configuration.getCPDReportRenderer().render(report, IOUtil.createWriter(Charset.defaultCharset(), null));
|
||||
|
||||
if (cpd.getMatches().hasNext() && configuration.isFailOnViolation()) {
|
||||
return ExecutionResult.VIOLATIONS_FOUND;
|
||||
return CliExitCode.VIOLATIONS_FOUND;
|
||||
}
|
||||
} catch (IOException | RuntimeException e) {
|
||||
logger.debug(e.toString(), e);
|
||||
logger.error(LogMessages.errorDetectedMessage(1, "cpd"));
|
||||
return ExecutionResult.ERROR;
|
||||
return CliExitCode.ERROR;
|
||||
}
|
||||
|
||||
return ExecutionResult.OK;
|
||||
return CliExitCode.OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
package net.sourceforge.pmd.cli.commands.internal;
|
||||
|
||||
import net.sourceforge.pmd.cli.internal.ExecutionResult;
|
||||
import net.sourceforge.pmd.cli.internal.CliExitCode;
|
||||
import net.sourceforge.pmd.util.fxdesigner.DesignerStarter;
|
||||
import net.sourceforge.pmd.util.fxdesigner.DesignerStarter.ExitStatus;
|
||||
import net.sourceforge.pmd.util.fxdesigner.DesignerVersion;
|
||||
@ -23,11 +23,11 @@ public class DesignerCommand extends AbstractPmdSubcommand {
|
||||
private boolean versionRequested;
|
||||
|
||||
@Override
|
||||
protected ExecutionResult execute() {
|
||||
protected CliExitCode execute() {
|
||||
final String[] rawArgs = spec.commandLine().getParseResult().expandedArgs().toArray(new String[0]);
|
||||
final ExitStatus status = DesignerStarter.launchGui(rawArgs);
|
||||
|
||||
return status == ExitStatus.OK ? ExecutionResult.OK : ExecutionResult.ERROR;
|
||||
return status == ExitStatus.OK ? CliExitCode.OK : CliExitCode.ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ package net.sourceforge.pmd.cli.commands.internal;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@ -26,7 +27,7 @@ import net.sourceforge.pmd.benchmark.TimingReport;
|
||||
import net.sourceforge.pmd.benchmark.TimingReportRenderer;
|
||||
import net.sourceforge.pmd.cli.commands.typesupport.internal.PmdLanguageTypeSupport;
|
||||
import net.sourceforge.pmd.cli.commands.typesupport.internal.PmdLanguageVersionTypeSupport;
|
||||
import net.sourceforge.pmd.cli.internal.ExecutionResult;
|
||||
import net.sourceforge.pmd.cli.internal.CliExitCode;
|
||||
import net.sourceforge.pmd.cli.internal.ProgressBarListener;
|
||||
import net.sourceforge.pmd.internal.LogMessages;
|
||||
import net.sourceforge.pmd.lang.Language;
|
||||
@ -84,7 +85,7 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
|
||||
private boolean benchmark;
|
||||
|
||||
private boolean shortnames;
|
||||
private List<Path> relativizeRootPaths;
|
||||
|
||||
private boolean showSuppressed;
|
||||
|
||||
@ -140,9 +141,21 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
this.benchmark = benchmark;
|
||||
}
|
||||
|
||||
@Option(names = "--short-names", description = "Prints shortened filenames in the report.")
|
||||
public void setShortnames(final boolean shortnames) {
|
||||
this.shortnames = shortnames;
|
||||
@Option(names = { "--relativize-paths-with", "-z"}, description = "Path relative to which directories are rendered in the report. "
|
||||
+ "This option allows shortening directories in the report; "
|
||||
+ "without it, paths are rendered as mentioned in the source directory (option \"--dir\"). "
|
||||
+ "The option can be repeated, in which case the shortest relative path will be used. "
|
||||
+ "If the root path is mentioned (e.g. \"/\" or \"C:\\\"), then the paths will be rendered as absolute.",
|
||||
arity = "1..*", split = ",")
|
||||
public void setRelativizePathsWith(List<Path> rootPaths) {
|
||||
this.relativizeRootPaths = rootPaths;
|
||||
|
||||
for (Path path : this.relativizeRootPaths) {
|
||||
if (Files.isRegularFile(path)) {
|
||||
throw new ParameterException(spec.commandLine(),
|
||||
"Expected a directory path for option '--relativize-paths-with', found a file: " + path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Option(names = "--show-suppressed", description = "Report should show suppressed rule violations.")
|
||||
@ -272,7 +285,9 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
configuration.setMinimumPriority(minimumPriority);
|
||||
configuration.setReportFile(reportFile);
|
||||
configuration.setReportProperties(properties);
|
||||
configuration.setReportShortNames(shortnames);
|
||||
if (relativizeRootPaths != null) {
|
||||
configuration.addRelativizeRoots(relativizeRootPaths);
|
||||
}
|
||||
configuration.setRuleSets(rulesets);
|
||||
configuration.setRuleSetFactoryCompatibilityEnabled(!this.noRuleSetCompatibility);
|
||||
configuration.setShowSuppressedViolations(showSuppressed);
|
||||
@ -305,7 +320,7 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExecutionResult execute() {
|
||||
protected CliExitCode execute() {
|
||||
if (benchmark) {
|
||||
TimeTracker.startGlobalTracking();
|
||||
}
|
||||
@ -320,7 +335,7 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
pmd = PmdAnalysis.create(configuration);
|
||||
} catch (final Exception e) {
|
||||
pmdReporter.errorEx("Could not initialize analysis", e);
|
||||
return ExecutionResult.ERROR;
|
||||
return CliExitCode.ERROR;
|
||||
}
|
||||
|
||||
LOG.debug("Current classpath:\n{}", System.getProperty("java.class.path"));
|
||||
@ -333,15 +348,15 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
pmd.addListener(new ProgressBarListener());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final ReportStats stats = pmd.runAndReturnStats();
|
||||
if (pmdReporter.numErrors() > 0) {
|
||||
// processing errors are ignored
|
||||
return ExecutionResult.ERROR;
|
||||
return CliExitCode.ERROR;
|
||||
} else if (stats.getNumViolations() > 0 && configuration.isFailOnViolation()) {
|
||||
return ExecutionResult.VIOLATIONS_FOUND;
|
||||
return CliExitCode.VIOLATIONS_FOUND;
|
||||
} else {
|
||||
return ExecutionResult.OK;
|
||||
return CliExitCode.OK;
|
||||
}
|
||||
} finally {
|
||||
if (pmd != null) {
|
||||
@ -352,7 +367,7 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
} catch (final Exception e) {
|
||||
pmdReporter.errorEx("Exception while running PMD.", e);
|
||||
printErrorDetected(pmdReporter, 1);
|
||||
return ExecutionResult.ERROR;
|
||||
return CliExitCode.ERROR;
|
||||
} finally {
|
||||
finishBenchmarker(pmdReporter);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import picocli.CommandLine.IVersionProvider;
|
||||
@Command(name = "pmd", mixinStandardHelpOptions = true,
|
||||
versionProvider = PMDVersionProvider.class,
|
||||
exitCodeListHeading = "Exit Codes:%n",
|
||||
exitCodeList = { "0:Succesful analysis, no violations found", "1:An unexpected error occurred during execution",
|
||||
exitCodeList = { "0:Successful analysis, no violations found", "1:An unexpected error occurred during execution",
|
||||
"2:Usage error, please refer to the command help", "4:Successful analysis, at least 1 violation found" },
|
||||
subcommands = { PmdCommand.class, CpdCommand.class, DesignerCommand.class, CpdGuiCommand.class, TreeExportCommand.class })
|
||||
public class PmdRootCommand {
|
||||
|
@ -15,7 +15,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.sourceforge.pmd.cli.commands.mixins.internal.EncodingMixin;
|
||||
import net.sourceforge.pmd.cli.commands.typesupport.internal.PmdLanguageTypeSupport;
|
||||
import net.sourceforge.pmd.cli.internal.ExecutionResult;
|
||||
import net.sourceforge.pmd.cli.internal.CliExitCode;
|
||||
import net.sourceforge.pmd.internal.LogMessages;
|
||||
import net.sourceforge.pmd.lang.Language;
|
||||
import net.sourceforge.pmd.properties.PropertyDescriptor;
|
||||
@ -106,16 +106,16 @@ public class TreeExportCommand extends AbstractPmdSubcommand {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ExecutionResult execute() {
|
||||
protected CliExitCode execute() {
|
||||
final TreeExporter exporter = new TreeExporter(toConfiguration());
|
||||
try {
|
||||
exporter.export();
|
||||
return ExecutionResult.OK;
|
||||
return CliExitCode.OK;
|
||||
} catch (final IOException e) {
|
||||
final SimpleMessageReporter reporter = new SimpleMessageReporter(LoggerFactory.getLogger(TreeExportCommand.class));
|
||||
reporter.error(e, LogMessages.errorDetectedMessage(1, "ast-dump"));
|
||||
|
||||
return ExecutionResult.ERROR;
|
||||
return CliExitCode.ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.cli.internal;
|
||||
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
|
||||
/**
|
||||
* The execution result of any given command.
|
||||
*/
|
||||
public enum CliExitCode {
|
||||
/** No errors, no violations. This is exit code {@code 0}. */
|
||||
OK(0),
|
||||
/**
|
||||
* Errors were detected, PMD may have not run to the end.
|
||||
* This is exit code {@code 1}.
|
||||
*/
|
||||
ERROR(1),
|
||||
/**
|
||||
* Indicates a problem with the CLI parameters: either a required
|
||||
* parameter is missing or an invalid parameter was provided.
|
||||
*/
|
||||
USAGE_ERROR(2),
|
||||
/**
|
||||
* No errors, but PMD found violations. This is exit code {@code 4}.
|
||||
* This is only returned if {@link PMDConfiguration#isFailOnViolation()}
|
||||
* is set (CLI flag {@code --failOnViolation}).
|
||||
*/
|
||||
VIOLATIONS_FOUND(4);
|
||||
|
||||
private final int exitCode;
|
||||
|
||||
CliExitCode(int exitCode) {
|
||||
this.exitCode = exitCode;
|
||||
}
|
||||
|
||||
public int getExitCode() {
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
public static CliExitCode fromInt(int i) {
|
||||
switch (i) {
|
||||
case 0: return OK;
|
||||
case 1: return ERROR;
|
||||
case 2: return USAGE_ERROR;
|
||||
case 4: return VIOLATIONS_FOUND;
|
||||
default:
|
||||
throw new IllegalArgumentException("Not a known exit code: " + i);
|
||||
}
|
||||
}
|
||||
}
|
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