Merge branch 'master' into pmd7-textfile-display-name
This commit is contained in:
commit
ac86bb21dc
@ -3,7 +3,7 @@ repository: pmd/pmd
|
||||
pmd:
|
||||
version: 7.0.0-SNAPSHOT
|
||||
previous_version: 6.55.0
|
||||
date: ??-????-2023
|
||||
date: 27-May-2023
|
||||
release_type: major
|
||||
|
||||
# release types: major, minor, bugfix
|
||||
|
@ -9,10 +9,7 @@ author: Tom Copeland, Andreas Dangel <andreas.dangel@adangel.org>
|
||||
|
||||
## Overview
|
||||
|
||||
The processing starts e.g. with the main class: `net.sourceforge.pmd.PMD`
|
||||
|
||||
{%include note.html content="This is the command line interface. There are many other means, who
|
||||
PMD can be invoked. E.g. via ant, maven, gradle..." %}
|
||||
The processing starts with the main class {% jdoc core::PmdAnalysis %}.
|
||||
|
||||
* Parse command line parameters (see net.sourceforge.pmd.cli.PMDParameters)
|
||||
Also load the incremental analysis cache file
|
||||
|
@ -192,8 +192,7 @@ then the violation will be suppressed. Note that the query shouldn't be finding
|
||||
the violation nodes to suppress, but rather, finding a non-empty sequence of nodes
|
||||
when evaluated with the violation node as a context node.
|
||||
|
||||
The XPath version used by those queries is XPath 1.0, so it doesn't support various XPath 2.0
|
||||
features. This will be updated with PMD 7.0.0.
|
||||
The XPath version used by those queries is XPath 3.1 since PMD 7. Before then XPath 1.0 was used.
|
||||
|
||||
For example, to suppress reporting specifically "String" parameters which are unused:
|
||||
|
||||
|
@ -30,186 +30,6 @@ Note: You'll need to select a specific version. This is done in the example via
|
||||
|
||||
This will transitively pull in the artifact `pmd-core` which contains the API.
|
||||
|
||||
## Command line interface
|
||||
|
||||
The easiest way is to call PMD with the same interface as from command line. The main class is
|
||||
`net.sourceforge.pmd.PMD`:
|
||||
|
||||
``` java
|
||||
import net.sourceforge.pmd.PMD;
|
||||
|
||||
public class Example {
|
||||
public static void main(String[] args) {
|
||||
String[] pmdArgs = {
|
||||
"-d", "/home/workspace/src/main/java/code",
|
||||
"-R", "rulesets/java/quickstart.xml",
|
||||
"-f", "xml",
|
||||
"-r", "/home/workspace/pmd-report.xml"
|
||||
};
|
||||
PMD.main(pmdArgs);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It uses the same options as described in [PMD CLI reference](pmd_userdocs_cli_reference.html).
|
||||
|
||||
## Programmatically, variant 1
|
||||
|
||||
This is very similar:
|
||||
|
||||
``` java
|
||||
import net.sourceforge.pmd.PMD;
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
|
||||
public class PmdExample {
|
||||
|
||||
public static void main(String[] args) {
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
configuration.setInputPaths("/home/workspace/src/main/java/code");
|
||||
configuration.addRuleSet("rulesets/java/quickstart.xml");
|
||||
configuration.setReportFormat("xml");
|
||||
configuration.setReportFile("/home/workspace/pmd-report.xml");
|
||||
|
||||
PMD.runPmd(configuration);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Programmatically, variant 2
|
||||
|
||||
This gives you more control over which files are processed, but is also more complicated.
|
||||
You can also provide your own custom renderers.
|
||||
|
||||
1. First we create a `PMDConfiguration` and configure it, first the rules:
|
||||
|
||||
```java
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
configuration.setMinimumPriority(RulePriority.MEDIUM);
|
||||
configuration.addRuleSet("rulesets/java/quickstart.xml");
|
||||
```
|
||||
|
||||
2. Then we configure, which paths to analyze:
|
||||
|
||||
```java
|
||||
configuration.setInputPaths("/home/workspace/src/main/java/code");
|
||||
```
|
||||
|
||||
3. The we configure the default language version for Java. And in order to support type resolution,
|
||||
PMD needs to have access to the compiled classes and dependencies as well. This is called
|
||||
"auxclasspath" and is also configured here.
|
||||
|
||||
Note: you can specify multiple class paths separated by `:` on Unix-systems or `;` under Windows.
|
||||
|
||||
```java
|
||||
configuration.setDefaultLanguageVersion(LanguageRegistry.findLanguageByTerseName("java").getVersion("11"));
|
||||
configuration.prependAuxClasspath("/home/workspace/target/classes:/home/.m2/repository/my/dependency.jar");
|
||||
```
|
||||
|
||||
4. Then we configure the reporting. Configuring the report file is optional. If not specified, the report
|
||||
will be written to `stdout`.
|
||||
|
||||
```java
|
||||
configuration.setReportFormat("xml");
|
||||
configuration.setReportFile("/home/workspace/pmd-report.xml");
|
||||
```
|
||||
|
||||
5. Now an optional step: If you want to use additional renderers as in the example, set them up before
|
||||
calling PMD. You can use a built-in renderer, e.g. `XMLRenderer` or a custom renderer implementing
|
||||
`Renderer`. Note, that you must manually initialize the renderer by setting a suitable `Writer`:
|
||||
|
||||
```java
|
||||
Writer rendererOutput = new StringWriter();
|
||||
Renderer renderer = createRenderer(rendererOutput);
|
||||
|
||||
// ...
|
||||
private static Renderer createRenderer(Writer writer) {
|
||||
XMLRenderer xml = new XMLRenderer("UTF-8");
|
||||
xml.setWriter(writer);
|
||||
return xml;
|
||||
}
|
||||
```
|
||||
|
||||
6. Finally we can start the PMD analysis. There is the possibility to fine-tune the configuration
|
||||
by adding additional files to analyze or adding additional rulesets or renderers:
|
||||
|
||||
```java
|
||||
try (PmdAnalysis pmd = PmdAnalysis.create(configuration)) {
|
||||
// optional: add more rulesets
|
||||
pmd.addRuleSet(pmd.newRuleSetLoader().loadFromResource("custom-ruleset.xml"));
|
||||
// optional: add more files
|
||||
pmd.files().addFile(Paths.get("src", "main", "more-java", "ExtraSource.java"));
|
||||
// optional: add more renderers
|
||||
pmd.addRenderer(renderer);
|
||||
|
||||
// or just call PMD
|
||||
pmd.performAnalysis();
|
||||
}
|
||||
```
|
||||
|
||||
The renderer will be automatically flushed and closed at the end of the analysis.
|
||||
|
||||
7. Then you can check the rendered output.
|
||||
|
||||
``` java
|
||||
System.out.println("Rendered Report:");
|
||||
System.out.println(rendererOutput.toString());
|
||||
```
|
||||
|
||||
Here is a complete example:
|
||||
|
||||
``` java
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
import net.sourceforge.pmd.PmdAnalysis;
|
||||
import net.sourceforge.pmd.RulePriority;
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.renderers.Renderer;
|
||||
import net.sourceforge.pmd.renderers.XMLRenderer;
|
||||
|
||||
public class PmdExample2 {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
configuration.setMinimumPriority(RulePriority.MEDIUM);
|
||||
configuration.addRuleSet("rulesets/java/quickstart.xml");
|
||||
|
||||
configuration.setInputPaths("/home/workspace/src/main/java/code");
|
||||
|
||||
configuration.setDefaultLanguageVersion(LanguageRegistry.findLanguageByTerseName("java").getVersion("11"));
|
||||
configuration.prependAuxClasspath("/home/workspace/target/classes");
|
||||
|
||||
configuration.setReportFormat("xml");
|
||||
configuration.setReportFile("/home/workspace/pmd-report.xml");
|
||||
|
||||
Writer rendererOutput = new StringWriter();
|
||||
Renderer renderer = createRenderer(rendererOutput);
|
||||
|
||||
try (PmdAnalysis pmd = PmdAnalysis.create(configuration)) {
|
||||
// optional: add more rulesets
|
||||
pmd.addRuleSet(pmd.newRuleSetLoader().loadFromResource("custom-ruleset.xml"));
|
||||
// optional: add more files
|
||||
pmd.files().addFile(Paths.get("src", "main", "more-java", "ExtraSource.java"));
|
||||
// optional: add more renderers
|
||||
pmd.addRenderer(renderer);
|
||||
|
||||
// or just call PMD
|
||||
pmd.performAnalysis();
|
||||
}
|
||||
|
||||
System.out.println("Rendered Report:");
|
||||
System.out.println(rendererOutput.toString());
|
||||
}
|
||||
|
||||
private static Renderer createRenderer(Writer writer) {
|
||||
XMLRenderer xml = new XMLRenderer("UTF-8");
|
||||
xml.setWriter(writer);
|
||||
return xml;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Running PMD programmatically
|
||||
|
||||
The programmatic API for PMD is centered around {% jdoc core::PmdAnalysis %}, please see the javadocs for usage information.
|
||||
|
@ -34,64 +34,10 @@ for all.</p>
|
||||
|
||||
{% tocmaker is_release_notes_processor %}
|
||||
|
||||
### Changes since 7.0.0-rc1
|
||||
### Changes since 7.0.0-rc2
|
||||
|
||||
This section lists the most important changes from the last release candidate.
|
||||
The remaining section describe the complete release notes for 7.0.0.
|
||||
|
||||
#### API Changes
|
||||
* Moved the two classes {% jdoc core::cpd.impl.AntlrTokenizer %} and {% jdoc core::cpd.impl.JavaCCTokenizer %} from
|
||||
`internal` package into package {% jdoc_package core::cpd.impl %}. These two classes are part of the API and
|
||||
are base classes for CPD language implementations.
|
||||
* `AntlrBaseRule` is gone in favor of {% jdoc core::lang.rule.AbstractVisitorRule %}.
|
||||
* The classes {% jdoc kotlin::lang.kotlin.ast.KotlinInnerNode %} and {% jdoc swift::lang.swift.ast.SwiftInnerNode %}
|
||||
are package-private now.
|
||||
* The parameter order of {% jdoc core::lang.document.FileCollector#addSourceFile(String, String) %} has been swapped
|
||||
in order to have the same meaning as in 6.55.0. That will make it easier if you upgrade from 6.55.0 to 7.0.0.
|
||||
However, that means, that you need to change these method calls if you have migrated to 7.0.0-rc1 already.
|
||||
|
||||
#### 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/7.0.0-rc1).
|
||||
|
||||
#### Rule Changes
|
||||
* {% rule "java/design/ImmutableField" %}: the property `ignoredAnnotations` has been removed. The property was
|
||||
deprecated since PMD 6.52.0.
|
||||
|
||||
#### Fixed Issues
|
||||
* cli
|
||||
* [#4482](https://github.com/pmd/pmd/issues/4482): \[cli] pmd.bat can only be executed once
|
||||
* [#4484](https://github.com/pmd/pmd/issues/4484): \[cli] ast-dump with no properties produce an NPE
|
||||
* core
|
||||
* [#2500](https://github.com/pmd/pmd/issues/2500): \[core] Clarify API for ANTLR based languages
|
||||
* doc
|
||||
* [#2501](https://github.com/pmd/pmd/issues/2501): \[doc] Verify ANTLR Documentation
|
||||
* [#4438](https://github.com/pmd/pmd/issues/4438): \[doc] Documentation links in VS Code are outdated
|
||||
* java-codestyle
|
||||
* [#4273](https://github.com/pmd/pmd/issues/4273): \[java] CommentDefaultAccessModifier ignoredAnnotations should include "org.junit.jupiter.api.extension.RegisterExtension" by default
|
||||
* [#4487](https://github.com/pmd/pmd/issues/4487): \[java] UnnecessaryConstructor: false-positive with @<!-- -->Inject and @<!-- -->Autowired
|
||||
* java-design
|
||||
* [#4254](https://github.com/pmd/pmd/issues/4254): \[java] ImmutableField - false positive with Lombok @<!-- -->Setter
|
||||
* [#4477](https://github.com/pmd/pmd/issues/4477): \[java] SignatureDeclareThrowsException: false-positive with TestNG annotations
|
||||
* [#4490](https://github.com/pmd/pmd/issues/4490): \[java] ImmutableField - false negative with Lombok @<!-- -->Getter
|
||||
* java-errorprone
|
||||
* [#4449](https://github.com/pmd/pmd/issues/4449): \[java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression
|
||||
* [#4493](https://github.com/pmd/pmd/issues/4493): \[java] MissingStaticMethodInNonInstantiatableClass: false-positive about @<!-- -->Inject
|
||||
* [#4505](https://github.com/pmd/pmd/issues/4505): \[java] ImplicitSwitchFallThrough NPE in PMD 7.0.0-rc1
|
||||
* java-multithreading
|
||||
* [#4483](https://github.com/pmd/pmd/issues/4483): \[java] NonThreadSafeSingleton false positive with double-checked locking
|
||||
* miscellaneous
|
||||
* [#4462](https://github.com/pmd/pmd/issues/4462): Provide Software Bill of Materials (SBOM)
|
||||
|
||||
#### External contributions
|
||||
* [#4444](https://github.com/pmd/pmd/pull/4444): \[java] CommentDefaultAccessModifier - ignore org.junit.jupiter.api.extension.RegisterExtension by default - [Nirvik Patel](https://github.com/nirvikpatel) (@nirvikpatel)
|
||||
* [#4450](https://github.com/pmd/pmd/pull/4450): \[java] Fix #4449 AvoidAccessibilityAlteration: Correctly handle Lambda expressions in PrivilegedAction scenarios - [Seren](https://github.com/mohui1999) (@mohui1999)
|
||||
* [#4452](https://github.com/pmd/pmd/pull/4452): \[doc] Update PMD_APEX_ROOT_DIRECTORY documentation reference - [nwcm](https://github.com/nwcm) (@nwcm)
|
||||
* [#4474](https://github.com/pmd/pmd/pull/4474): \[java] ImmutableField: False positive with lombok (fixes #4254) - [Pim van der Loos](https://github.com/PimvanderLoos) (@PimvanderLoos)
|
||||
* [#4488](https://github.com/pmd/pmd/pull/4488): \[java] Fix #4477: A false-positive about SignatureDeclareThrowsException - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe)
|
||||
* [#4494](https://github.com/pmd/pmd/pull/4494): \[java] Fix #4487: A false-positive about UnnecessaryConstructor and @<!-- -->Inject and @<!-- -->Autowired - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe)
|
||||
* [#4495](https://github.com/pmd/pmd/pull/4495): \[java] Fix #4493: false-positive about MissingStaticMethodInNonInstantiatableClass and @<!-- -->Inject - [AnnaDev](https://github.com/LynnBroe) (@LynnBroe)
|
||||
* [#4520](https://github.com/pmd/pmd/pull/4520): \[doc] Fix typo: missing closing quotation mark after CPD-END - [João Dinis Ferreira](https://github.com/joaodinissf) (@joaodinissf)
|
||||
The remaining section describes the complete release notes for 7.0.0.
|
||||
|
||||
### 🚀 Major Features and Enhancements
|
||||
|
||||
@ -214,33 +160,116 @@ Contributors: [Wener](https://github.com/wener-tiobe) (@wener-tiobe)
|
||||
|
||||
#### Changed Rules
|
||||
|
||||
**Java**
|
||||
**General changes**
|
||||
|
||||
* {% rule "java/codestyle/UnnecessaryFullyQualifiedName" %}: the rule has two new properties,
|
||||
* All statistical rules (like ExcessiveClassLength, ExcessiveParameterList) have been simplified and unified.
|
||||
The properties `topscore` and `sigma` have been removed. The property `minimum` is still there, however the type is not
|
||||
a decimal number anymore but has been changed to an integer. This affects rules in the languages Apex, Java, PLSQL
|
||||
and Velocity Template Language (vm):
|
||||
* Apex: {% rule apex/design/ExcessiveClassLength %}, {% rule apex/design/ExcessiveParameterList %},
|
||||
{% rule apex/design/ExcessivePublicCount %}, {% rule apex/design/NcssConstructorCount %},
|
||||
{% rule apex/design/NcssMethodCount %}, {% rule apex/design/NcssTypeCount %}
|
||||
* Java: {% rule java/design/ExcessiveImports %}, {% rule java/design/ExcessiveParameterList %},
|
||||
{% rule java/design/ExcessivePublicCount %}, {% rule java/design/SwitchDensity %}
|
||||
* PLSQL: {% rule plsql/design/ExcessiveMethodLength %}, {% rule plsql/design/ExcessiveObjectLength %},
|
||||
{% rule plsql/design/ExcessivePackageBodyLength %}, {% rule plsql/design/ExcessivePackageSpecificationLength %},
|
||||
{% rule plsql/design/ExcessiveParameterList %}, {% rule plsql/design/ExcessiveTypeLength %},
|
||||
{% rule plsql/design/NcssMethodCount %}, {% rule plsql/design/NcssObjectCount %},
|
||||
{% rule plsql/design/NPathComplexity %}
|
||||
* VM: {% rule vm/design/ExcessiveTemplateLength %}
|
||||
|
||||
* The general property `violationSuppressXPath` which is available for all rules to
|
||||
[suppress warnings]({{ baseurl }}pmd_userdocs_suppressing_warnings.html) now uses XPath version 3.1 by default.
|
||||
This version of the XPath language is mostly identical to XPath 2.0. In PMD 6, XPath 1.0 has been used.
|
||||
If you upgrade from PMD 6, you need to verify your `violationSuppressXPath` properties.
|
||||
|
||||
**Apex General changes**
|
||||
|
||||
* The properties `cc_categories`, `cc_remediation_points_multiplier`, `cc_block_highlighting` have been removed
|
||||
from all rules. These properties have been deprecated since PMD 6.13.0.
|
||||
See [issue #1648](https://github.com/pmd/pmd/issues/1648) for more details.
|
||||
|
||||
**Java General changes**
|
||||
|
||||
* Violations reported on methods or classes previously reported the line range of the entire method
|
||||
or class. With PMD 7.0.0, the reported location is now just the identifier of the method or class.
|
||||
This affects various rules, e.g. {% rule java/design/CognitiveComplexity %}.
|
||||
|
||||
The report location is controlled by the overrides of the method {% jdoc core::lang.ast.Node#getReportLocation() %}
|
||||
in different node types.
|
||||
|
||||
See [issue #4439](https://github.com/pmd/pmd/issues/4439) and [issue #730](https://github.com/pmd/pmd/issues/730)
|
||||
for more details.
|
||||
|
||||
**Java Best Practices**
|
||||
|
||||
* {% rule java/bestpractices/ArrayIsStoredDirectly %}: Violations are now reported on the assignment and not
|
||||
anymore on the formal parameter. The reported line numbers will probably move.
|
||||
* {% rule java/bestpractices/AvoidReassigningLoopVariables %}: This rule might not report anymore all
|
||||
reassignments of the control variable in for-loops when the property `forReassign` is set to `skip`.
|
||||
See [issue #4500](https://github.com/pmd/pmd/issues/4500) for more details.
|
||||
* {% rule java/bestpractices/LooseCoupling %}: The rule has a new property to allow some types to be coupled
|
||||
to (`allowedTypes`).
|
||||
* {% rule java/bestpractices/UnusedLocalVariable %}: This rule has some important false-negatives fixed
|
||||
and finds many more cases now. For details see issues [#2130](https://github.com/pmd/pmd/issues/2130),
|
||||
[#4516](https://github.com/pmd/pmd/issues/4516), and [#4517](https://github.com/pmd/pmd/issues/4517).
|
||||
|
||||
**Java Codestyle**
|
||||
|
||||
* {% rule java/codestyle/MethodNamingConventions %}: The property `checkNativeMethods` has been removed. The
|
||||
property was deprecated since PMD 6.3.0. Use the property `nativePattern` to control whether native methods
|
||||
should be considered or not.
|
||||
* {% rule java/codestyle/ShortVariable %}: This rule now also reports short enum constant names.
|
||||
* {% rule java/codestyle/UseDiamondOperator %}: The property `java7Compatibility` has been removed. The rule now
|
||||
handles Java 7 properly without a property.
|
||||
* {% rule java/codestyle/UnnecessaryFullyQualifiedName %}: The rule has two new properties,
|
||||
to selectively disable reporting on static field and method qualifiers. The rule also has been improved
|
||||
to be more precise.
|
||||
* {% rule "java/codestyle/UselessParentheses" %}: the rule has two new properties which control how strict
|
||||
* {% rule java/codestyle/UselessParentheses %}: The rule has two new properties which control how strict
|
||||
the rule should be applied. With `ignoreClarifying` (default: true) parentheses that are strictly speaking
|
||||
not necessary are allowed, if they separate expressions of different precedence.
|
||||
The other property `ignoreBalancing` (default: true) is similar, in that it allows parentheses that help
|
||||
reading and understanding the expressions.
|
||||
* {% rule "java/bestpractices/LooseCoupling" %}: the rule has a new property to allow some types to be coupled
|
||||
to (`allowedTypes`).
|
||||
* {% rule "java/errorprone/EmptyCatchBlock" %}: `CloneNotSupportedException` and `InterruptedException` are not
|
||||
special-cased anymore. Rename the exception parameter to `ignored` to ignore them.
|
||||
* {% rule "java/errorprone/DontImportSun" %}: `sun.misc.Signal` is not special-cased anymore.
|
||||
* {% rule "java/codestyle/UseDiamondOperator" %}: the property `java7Compatibility` is removed. The rule now
|
||||
handles Java 7 properly without a property.
|
||||
* {% rule "java/design/SingularField" %}: Properties `checkInnerClasses` and `disallowNotAssignment` are removed.
|
||||
The rule is now more precise and will check these cases properly.
|
||||
* {% rule "java/design/UseUtilityClass" %}: The property `ignoredAnnotations` has been removed.
|
||||
* {% rule "java/design/LawOfDemeter" %}: the rule has a new property `trustRadius`. This defines the maximum degree
|
||||
of trusted data. The default of 1 is the most restrictive.
|
||||
* {% rule "java/documentation/CommentContent" %}: The properties `caseSensitive` and `disallowedTerms` are removed. The
|
||||
new property `fobiddenRegex` can be used now to define the disallowed terms with a single regular
|
||||
expression.
|
||||
* {% rule "java/design/ImmutableField" %}: the property `ignoredAnnotations` has been removed. The property was
|
||||
|
||||
**Java Design**
|
||||
|
||||
* {% rule java/design/CyclomaticComplexity %}: The property `reportLevel` has been removed. The property was
|
||||
deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods using
|
||||
`classReportLevel` and `methodReportLevel` instead.
|
||||
* {% rule java/design/ImmutableField %}: The property `ignoredAnnotations` has been removed. The property was
|
||||
deprecated since PMD 6.52.0.
|
||||
* {% rule java/design/LawOfDemeter %}: The rule has a new property `trustRadius`. This defines the maximum degree
|
||||
of trusted data. The default of 1 is the most restrictive.
|
||||
* {% rule java/design/NPathComplexity %}: The property `minimum` has been removed. It was deprecated since PMD 6.0.0.
|
||||
Use the property `reportLevel` instead.
|
||||
* {% rule java/design/SingularField %}: The properties `checkInnerClasses` and `disallowNotAssignment` have been removed.
|
||||
The rule is now more precise and will check these cases properly.
|
||||
* {% rule java/design/UseUtilityClass %}: The property `ignoredAnnotations` has been removed.
|
||||
|
||||
**Java Documentation**
|
||||
|
||||
* {% rule java/documentation/CommentContent %}: The properties `caseSensitive` and `disallowedTerms` are removed. The
|
||||
new property `forbiddenRegex` can be used now to define the disallowed terms with a single regular
|
||||
expression.
|
||||
* {% rule java/documentation/CommentRequired %}:
|
||||
* Overridden methods are now detected even without the `@Override`
|
||||
annotation. This is relevant for the property `methodWithOverrideCommentRequirement`.
|
||||
See also [pull request #3757](https://github.com/pmd/pmd/pull/3757).
|
||||
* Elements in annotation types are now detected as well. This might lead to an increased number of violations
|
||||
for missing public method comments.
|
||||
* {% rule java/documentation/CommentSize %}: When determining the line-length of a comment, the leading comment
|
||||
prefix markers (e.g. `*` or `//`) are ignored and don't add up to the line-length.
|
||||
See also [pull request #4369](https://github.com/pmd/pmd/pull/4369).
|
||||
|
||||
**Java Error Prone**
|
||||
|
||||
* {% rule java/errorprone/AvoidDuplicateLiterals %}: The property `exceptionfile` has been removed. The property was
|
||||
deprecated since PMD 6.10.0. Use the property `exceptionList` instead.
|
||||
* {% rule java/errorprone/DontImportSun %}: `sun.misc.Signal` is not special-cased anymore.
|
||||
* {% rule java/errorprone/EmptyCatchBlock %}: `CloneNotSupportedException` and `InterruptedException` are not
|
||||
special-cased anymore. Rename the exception parameter to `ignored` to ignore them.
|
||||
* {% rule java/errorprone/ImplicitSwitchFallThrough %}: Violations are now reported on the case statements
|
||||
rather than on the switch statements. This is more accurate but might result in more violations now.
|
||||
|
||||
#### Removed Rules
|
||||
|
||||
@ -334,6 +363,7 @@ Language specific fixes:
|
||||
* [#4427](https://github.com/pmd/pmd/issues/4427): \[apex] ApexBadCrypto test failing to detect inline code
|
||||
* apex-design
|
||||
* [#2667](https://github.com/pmd/pmd/issues/2667): \[apex] Integrate nawforce/ApexLink to build robust Unused rule
|
||||
* [#4509](https://github.com/pmd/pmd/issues/4509): \[apex] ExcessivePublicCount doesn't consider inner classes correctly
|
||||
* java
|
||||
* [#520](https://github.com/pmd/pmd/issues/520): \[java] Allow `@SuppressWarnings` with constants instead of literals
|
||||
* [#864](https://github.com/pmd/pmd/issues/864): \[java] Similar/duplicated implementations for determining FQCN
|
||||
@ -370,7 +400,7 @@ Language specific fixes:
|
||||
* [#1212](https://github.com/pmd/pmd/issues/1212): \[java] Don't raise JUnitTestContainsTooManyAsserts on JUnit 5's assertAll
|
||||
* [#1422](https://github.com/pmd/pmd/issues/1422): \[java] JUnitTestsShouldIncludeAssert false positive with inherited @<!-- -->Rule field
|
||||
* [#1455](https://github.com/pmd/pmd/issues/1455): \[java] JUnitTestsShouldIncludeAssert: False positives for assert methods named "check" and "verify"
|
||||
* [#1563](https://github.com/pmd/pmd/issues/1563): \[java] False positive ForLoopCanBeForeach
|
||||
* [#1563](https://github.com/pmd/pmd/issues/1563): \[java] ForLoopCanBeForeach false positive with method call using index variable
|
||||
* [#1565](https://github.com/pmd/pmd/issues/1565): \[java] JUnitAssertionsShouldIncludeMessage false positive with AssertJ
|
||||
* [#1747](https://github.com/pmd/pmd/issues/1747): \[java] PreserveStackTrace false-positive
|
||||
* [#1969](https://github.com/pmd/pmd/issues/1969): \[java] MissingOverride false-positive triggered by package-private method overwritten in another package by extending class
|
||||
@ -392,10 +422,13 @@ Language specific fixes:
|
||||
* [#3672](https://github.com/pmd/pmd/pull/3672): \[java] LooseCoupling - fix false positive with generics
|
||||
* [#3675](https://github.com/pmd/pmd/pull/3675): \[java] MissingOverride - fix false positive with mixing type vars
|
||||
* [#3858](https://github.com/pmd/pmd/issues/3858): \[java] UseCollectionIsEmpty should infer local variable type from method invocation
|
||||
* [#4516](https://github.com/pmd/pmd/issues/4516): \[java] UnusedLocalVariable: false-negative with try-with-resources
|
||||
* [#4517](https://github.com/pmd/pmd/issues/4517): \[java] UnusedLocalVariable: false-negative with compound assignments
|
||||
* [#4518](https://github.com/pmd/pmd/issues/4518): \[java] UnusedLocalVariable: false-positive with multiple for-loop indices
|
||||
* java-codestyle
|
||||
* [#1208](https://github.com/pmd/pmd/issues/1208): \[java] PrematureDeclaration rule false-positive on variable declared to measure time
|
||||
* [#1429](https://github.com/pmd/pmd/issues/1429): \[java] PrematureDeclaration as result of method call (false positive)
|
||||
* [#1480](https://github.com/pmd/pmd/issues/1480): \[java] IdenticalCatchBranches false positive
|
||||
* [#1480](https://github.com/pmd/pmd/issues/1480): \[java] IdenticalCatchBranches false positive with return expressions
|
||||
* [#1673](https://github.com/pmd/pmd/issues/1673): \[java] UselessParentheses false positive with conditional operator
|
||||
* [#1790](https://github.com/pmd/pmd/issues/1790): \[java] UnnecessaryFullyQualifiedName false positive with enum constant
|
||||
* [#1918](https://github.com/pmd/pmd/issues/1918): \[java] UselessParentheses false positive with boolean operators
|
||||
@ -414,6 +447,8 @@ Language specific fixes:
|
||||
* [#4273](https://github.com/pmd/pmd/issues/4273): \[java] CommentDefaultAccessModifier ignoredAnnotations should include "org.junit.jupiter.api.extension.RegisterExtension" by default
|
||||
* [#4357](https://github.com/pmd/pmd/pull/4357): \[java] Fix IllegalStateException in UseDiamondOperator rule
|
||||
* [#4487](https://github.com/pmd/pmd/issues/4487): \[java] UnnecessaryConstructor: false-positive with @<!-- -->Inject and @<!-- -->Autowired
|
||||
* [#4511](https://github.com/pmd/pmd/issues/4511): \[java] LocalVariableCouldBeFinal shouldn't report unused variables
|
||||
* [#4512](https://github.com/pmd/pmd/issues/4512): \[java] MethodArgumentCouldBeFinal shouldn't report unused parameters
|
||||
* java-design
|
||||
* [#1014](https://github.com/pmd/pmd/issues/1014): \[java] LawOfDemeter: False positive with lambda expression
|
||||
* [#1605](https://github.com/pmd/pmd/issues/1605): \[java] LawOfDemeter: False positive for standard UTF-8 charset name
|
||||
@ -456,6 +491,8 @@ Language specific fixes:
|
||||
* [#4449](https://github.com/pmd/pmd/issues/4449): \[java] AvoidAccessibilityAlteration: Possible false positive in AvoidAccessibilityAlteration rule when using Lambda expression
|
||||
* [#4493](https://github.com/pmd/pmd/issues/4493): \[java] MissingStaticMethodInNonInstantiatableClass: false-positive about @<!-- -->Inject
|
||||
* [#4505](https://github.com/pmd/pmd/issues/4505): \[java] ImplicitSwitchFallThrough NPE in PMD 7.0.0-rc1
|
||||
* [#4513](https://github.com/pmd/pmd/issues/4513): \[java] UselessOperationOnImmutable various false negatives with String
|
||||
* [#4514](https://github.com/pmd/pmd/issues/4514): \[java] AvoidLiteralsInIfCondition false positive and negative for String literals when ignoreExpressions=true
|
||||
* java-multithreading
|
||||
* [#2537](https://github.com/pmd/pmd/issues/2537): \[java] DontCallThreadRun can't detect the case that call run() in `this.run()`
|
||||
* [#2538](https://github.com/pmd/pmd/issues/2538): \[java] DontCallThreadRun can't detect the case that call run() in `foo.bar.run()`
|
||||
@ -500,9 +537,8 @@ Language specific fixes:
|
||||
* [#4520](https://github.com/pmd/pmd/pull/4520): \[doc] Fix typo: missing closing quotation mark after CPD-END - [João Dinis Ferreira](https://github.com/joaodinissf) (@joaodinissf)
|
||||
|
||||
### 📈 Stats
|
||||
* 4416 commits
|
||||
* 464 closed tickets & PRs
|
||||
* Days since last release: 28
|
||||
* 4557 commits
|
||||
* 572 closed tickets & PRs
|
||||
* Days since last release: 35
|
||||
|
||||
{% endtocmaker %}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -488,6 +488,20 @@ We are shipping the following rules:
|
||||
Contributors: [Jeroen Borgers](https://github.com/jborgers) (@jborgers),
|
||||
[Peter Paul Bakker](https://github.com/stokpop) (@stokpop)
|
||||
|
||||
#### New: CPD support for TypeScript
|
||||
|
||||
Thanks to a contribution, CPD now supports the TypeScript language. It is shipped
|
||||
with the rest of the JavaScript support in the module `pmd-javascript`.
|
||||
|
||||
Contributors: [Paul Guyot](https://github.com/pguyot) (@pguyot)
|
||||
|
||||
#### New: CPD support for Julia
|
||||
|
||||
Thanks to a contribution, CPD now supports the Julia language. It is shipped
|
||||
in the new module `pmd-julia`.
|
||||
|
||||
Contributors: [Wener](https://github.com/wener-tiobe) (@wener-tiobe)
|
||||
|
||||
### Changed: JavaScript support
|
||||
|
||||
The JS specific parser options have been removed. The parser now always retains comments and uses version ES6.
|
||||
@ -530,33 +544,116 @@ Related issue: [[core] Explicitly name all language versions (#4120)](https://gi
|
||||
|
||||
### Changed Rules
|
||||
|
||||
**Java**
|
||||
**General changes**
|
||||
|
||||
* {% rule "java/codestyle/UnnecessaryFullyQualifiedName" %}: the rule has two new properties,
|
||||
* All statistical rules (like ExcessiveClassLength, ExcessiveParameterList) have been simplified and unified.
|
||||
The properties `topscore` and `sigma` have been removed. The property `minimum` is still there, however the type is not
|
||||
a decimal number anymore but has been changed to an integer. This affects rules in the languages Apex, Java, PLSQL
|
||||
and Velocity Template Language (vm):
|
||||
* Apex: {% rule apex/design/ExcessiveClassLength %}, {% rule apex/design/ExcessiveParameterList %},
|
||||
{% rule apex/design/ExcessivePublicCount %}, {% rule apex/design/NcssConstructorCount %},
|
||||
{% rule apex/design/NcssMethodCount %}, {% rule apex/design/NcssTypeCount %}
|
||||
* Java: {% rule java/design/ExcessiveImports %}, {% rule java/design/ExcessiveParameterList %},
|
||||
{% rule java/design/ExcessivePublicCount %}, {% rule java/design/SwitchDensity %}
|
||||
* PLSQL: {% rule plsql/design/ExcessiveMethodLength %}, {% rule plsql/design/ExcessiveObjectLength %},
|
||||
{% rule plsql/design/ExcessivePackageBodyLength %}, {% rule plsql/design/ExcessivePackageSpecificationLength %},
|
||||
{% rule plsql/design/ExcessiveParameterList %}, {% rule plsql/design/ExcessiveTypeLength %},
|
||||
{% rule plsql/design/NcssMethodCount %}, {% rule plsql/design/NcssObjectCount %},
|
||||
{% rule plsql/design/NPathComplexity %}
|
||||
* VM: {% rule vm/design/ExcessiveTemplateLength %}
|
||||
|
||||
* The general property `violationSuppressXPath` which is available for all rules to
|
||||
[suppress warnings](pmd_userdocs_suppressing_warnings.html) now uses XPath version 3.1 by default.
|
||||
This version of the XPath language is mostly identical to XPath 2.0. In PMD 6, XPath 1.0 has been used.
|
||||
If you upgrade from PMD 6, you need to verify your `violationSuppressXPath` properties.
|
||||
|
||||
**Apex General changes**
|
||||
|
||||
* The properties `cc_categories`, `cc_remediation_points_multiplier`, `cc_block_highlighting` have been removed
|
||||
from all rules. These properties have been deprecated since PMD 6.13.0.
|
||||
See [issue #1648](https://github.com/pmd/pmd/issues/1648) for more details.
|
||||
|
||||
**Java General changes**
|
||||
|
||||
* Violations reported on methods or classes previously reported the line range of the entire method
|
||||
or class. With PMD 7.0.0, the reported location is now just the identifier of the method or class.
|
||||
This affects various rules, e.g. {% rule java/design/CognitiveComplexity %}.
|
||||
|
||||
The report location is controlled by the overrides of the method {% jdoc core::lang.ast.Node#getReportLocation() %}
|
||||
in different node types.
|
||||
|
||||
See [issue #4439](https://github.com/pmd/pmd/issues/4439) and [issue #730](https://github.com/pmd/pmd/issues/730)
|
||||
for more details.
|
||||
|
||||
**Java Best Practices**
|
||||
|
||||
* {% rule java/bestpractices/ArrayIsStoredDirectly %}: Violations are now reported on the assignment and not
|
||||
anymore on the formal parameter. The reported line numbers will probably move.
|
||||
* {% rule java/bestpractices/AvoidReassigningLoopVariables %}: This rule might not report anymore all
|
||||
reassignments of the control variable in for-loops when the property `forReassign` is set to `skip`.
|
||||
See [issue #4500](https://github.com/pmd/pmd/issues/4500) for more details.
|
||||
* {% rule java/bestpractices/LooseCoupling %}: The rule has a new property to allow some types to be coupled
|
||||
to (`allowedTypes`).
|
||||
* {% rule java/bestpractices/UnusedLocalVariable %}: This rule has some important false-negatives fixed
|
||||
and finds many more cases now. For details see issues [#2130](https://github.com/pmd/pmd/issues/2130),
|
||||
[#4516](https://github.com/pmd/pmd/issues/4516), and [#4517](https://github.com/pmd/pmd/issues/4517).
|
||||
|
||||
**Java Codestyle**
|
||||
|
||||
* {% rule java/codestyle/MethodNamingConventions %}: The property `checkNativeMethods` has been removed. The
|
||||
property was deprecated since PMD 6.3.0. Use the property `nativePattern` to control whether native methods
|
||||
should be considered or not.
|
||||
* {% rule java/codestyle/ShortVariable %}: This rule now also reports short enum constant names.
|
||||
* {% rule java/codestyle/UseDiamondOperator %}: The property `java7Compatibility` has been removed. The rule now
|
||||
handles Java 7 properly without a property.
|
||||
* {% rule java/codestyle/UnnecessaryFullyQualifiedName %}: The rule has two new properties,
|
||||
to selectively disable reporting on static field and method qualifiers. The rule also has been improved
|
||||
to be more precise.
|
||||
* {% rule "java/codestyle/UselessParentheses" %}: the rule has two new properties which control how strict
|
||||
* {% rule java/codestyle/UselessParentheses %}: The rule has two new properties which control how strict
|
||||
the rule should be applied. With `ignoreClarifying` (default: true) parentheses that are strictly speaking
|
||||
not necessary are allowed, if they separate expressions of different precedence.
|
||||
The other property `ignoreBalancing` (default: true) is similar, in that it allows parentheses that help
|
||||
reading and understanding the expressions.
|
||||
* {% rule "java/bestpractices/LooseCoupling" %}: the rule has a new property to allow some types to be coupled
|
||||
to (`allowedTypes`).
|
||||
* {% rule "java/errorprone/EmptyCatchBlock" %}: `CloneNotSupportedException` and `InterruptedException` are not
|
||||
special-cased anymore. Rename the exception parameter to `ignored` to ignore them.
|
||||
* {% rule "java/errorprone/DontImportSun" %}: `sun.misc.Signal` is not special-cased anymore.
|
||||
* {% rule "java/codestyle/UseDiamondOperator" %}: the property `java7Compatibility` is removed. The rule now
|
||||
handles Java 7 properly without a property.
|
||||
* {% rule "java/design/SingularField" %}: Properties `checkInnerClasses` and `disallowNotAssignment` are removed.
|
||||
The rule is now more precise and will check these cases properly.
|
||||
* {% rule "java/design/UseUtilityClass" %}: The property `ignoredAnnotations` has been removed.
|
||||
* {% rule "java/design/LawOfDemeter" %}: the rule has a new property `trustRadius`. This defines the maximum degree
|
||||
of trusted data. The default of 1 is the most restrictive.
|
||||
* {% rule "java/documentation/CommentContent" %}: The properties `caseSensitive` and `disallowedTerms` are removed. The
|
||||
new property `fobiddenRegex` can be used now to define the disallowed terms with a single regular
|
||||
expression.
|
||||
* {% rule "java/design/ImmutableField" %}: the property `ignoredAnnotations` has been removed. The property was
|
||||
|
||||
**Java Design**
|
||||
|
||||
* {% rule java/design/CyclomaticComplexity %}: The property `reportLevel` has been removed. The property was
|
||||
deprecated since PMD 6.0.0. The report level can now be configured separated for classes and methods using
|
||||
`classReportLevel` and `methodReportLevel` instead.
|
||||
* {% rule java/design/ImmutableField %}: The property `ignoredAnnotations` has been removed. The property was
|
||||
deprecated since PMD 6.52.0.
|
||||
* {% rule java/design/LawOfDemeter %}: The rule has a new property `trustRadius`. This defines the maximum degree
|
||||
of trusted data. The default of 1 is the most restrictive.
|
||||
* {% rule java/design/NPathComplexity %}: The property `minimum` has been removed. It was deprecated since PMD 6.0.0.
|
||||
Use the property `reportLevel` instead.
|
||||
* {% rule java/design/SingularField %}: The properties `checkInnerClasses` and `disallowNotAssignment` have been removed.
|
||||
The rule is now more precise and will check these cases properly.
|
||||
* {% rule java/design/UseUtilityClass %}: The property `ignoredAnnotations` has been removed.
|
||||
|
||||
**Java Documentation**
|
||||
|
||||
* {% rule java/documentation/CommentContent %}: The properties `caseSensitive` and `disallowedTerms` are removed. The
|
||||
new property `forbiddenRegex` can be used now to define the disallowed terms with a single regular
|
||||
expression.
|
||||
* {% rule java/documentation/CommentRequired %}:
|
||||
* Overridden methods are now detected even without the `@Override`
|
||||
annotation. This is relevant for the property `methodWithOverrideCommentRequirement`.
|
||||
See also [pull request #3757](https://github.com/pmd/pmd/pull/3757).
|
||||
* Elements in annotation types are now detected as well. This might lead to an increased number of violations
|
||||
for missing public method comments.
|
||||
* {% rule java/documentation/CommentSize %}: When determining the line-length of a comment, the leading comment
|
||||
prefix markers (e.g. `*` or `//`) are ignored and don't add up to the line-length.
|
||||
See also [pull request #4369](https://github.com/pmd/pmd/pull/4369).
|
||||
|
||||
**Java Error Prone**
|
||||
|
||||
* {% rule java/errorprone/AvoidDuplicateLiterals %}: The property `exceptionfile` has been removed. The property was
|
||||
deprecated since PMD 6.10.0. Use the property `exceptionList` instead.
|
||||
* {% rule java/errorprone/DontImportSun %}: `sun.misc.Signal` is not special-cased anymore.
|
||||
* {% rule java/errorprone/EmptyCatchBlock %}: `CloneNotSupportedException` and `InterruptedException` are not
|
||||
special-cased anymore. Rename the exception parameter to `ignored` to ignore them.
|
||||
* {% rule java/errorprone/ImplicitSwitchFallThrough %}: Violations are now reported on the case statements
|
||||
rather than on the switch statements. This is more accurate but might result in more violations now.
|
||||
|
||||
### Deprecated Rules
|
||||
|
||||
|
@ -3,9 +3,7 @@
|
||||
~ BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>pmd</artifactId>
|
||||
<groupId>net.sourceforge.pmd</groupId>
|
||||
|
@ -115,7 +115,7 @@ public class SomeClass {
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>class with inner classes</description>
|
||||
<description>#4509 class with inner classes</description>
|
||||
<rule-property name="minimum">1</rule-property>
|
||||
<expected-problems>2</expected-problems>
|
||||
<expected-linenumbers>1,5</expected-linenumbers>
|
||||
|
@ -38,7 +38,7 @@
|
||||
<arguments>
|
||||
<argument>-Dpicocli.autocomplete.systemExitOnError</argument>
|
||||
<argument>-cp</argument>
|
||||
<classpath/>
|
||||
<classpath />
|
||||
<argument>picocli.AutoComplete</argument>
|
||||
<argument>--force</argument>
|
||||
<argument>--completionScript</argument>
|
||||
|
@ -97,7 +97,6 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
*/
|
||||
public CPDConfiguration toConfiguration() {
|
||||
final CPDConfiguration configuration = new CPDConfiguration();
|
||||
configuration.setDebug(debug);
|
||||
configuration.setExcludes(excludes);
|
||||
configuration.setFailOnViolation(failOnViolation);
|
||||
configuration.setFileListPath(fileListPath == null ? null : fileListPath.toString());
|
||||
|
@ -282,7 +282,6 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand {
|
||||
configuration.setIgnoreFilePath(ignoreListPath);
|
||||
configuration.setInputUri(uri);
|
||||
configuration.setReportFormat(format);
|
||||
configuration.setDebug(debug);
|
||||
configuration.setSourceEncoding(encoding.getEncoding().name());
|
||||
configuration.setMinimumPriority(minimumPriority);
|
||||
configuration.setReportFile(reportFile);
|
||||
|
@ -85,7 +85,6 @@ public class TreeExportCommand extends AbstractPmdSubcommand {
|
||||
|
||||
public TreeExportConfiguration toConfiguration() {
|
||||
final TreeExportConfiguration configuration = new TreeExportConfiguration();
|
||||
configuration.setDebug(debug);
|
||||
configuration.setFile(file);
|
||||
configuration.setFormat(format);
|
||||
configuration.setLanguage(language);
|
||||
|
@ -49,10 +49,6 @@
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr4-runtime</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.beust</groupId>
|
||||
<artifactId>jcommander</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.sf.saxon</groupId>
|
||||
|
@ -14,7 +14,6 @@ import java.nio.charset.Charset;
|
||||
public abstract class AbstractConfiguration {
|
||||
|
||||
private Charset sourceEncoding = Charset.forName(System.getProperty("file.encoding"));
|
||||
private boolean debug;
|
||||
|
||||
/**
|
||||
* Create a new abstract configuration.
|
||||
@ -42,25 +41,4 @@ public abstract class AbstractConfiguration {
|
||||
this.sourceEncoding = Charset.forName(sourceEncoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the debug indicator. If this value is <code>true</code> then PMD
|
||||
* will log debug information.
|
||||
*
|
||||
* @return <code>true</code> if debug logging is enabled, <code>false</code>
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean isDebug() {
|
||||
return debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the debug indicator.
|
||||
*
|
||||
* @param debug
|
||||
* The debug indicator to set.
|
||||
* @see #isDebug()
|
||||
*/
|
||||
public void setDebug(boolean debug) {
|
||||
this.debug = debug;
|
||||
}
|
||||
}
|
||||
|
@ -1,251 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.event.Level;
|
||||
|
||||
import net.sourceforge.pmd.benchmark.TextTimingReportRenderer;
|
||||
import net.sourceforge.pmd.benchmark.TimeTracker;
|
||||
import net.sourceforge.pmd.benchmark.TimingReport;
|
||||
import net.sourceforge.pmd.benchmark.TimingReportRenderer;
|
||||
import net.sourceforge.pmd.cli.PMDCommandLineInterface;
|
||||
import net.sourceforge.pmd.cli.PmdParametersParseResult;
|
||||
import net.sourceforge.pmd.internal.LogMessages;
|
||||
import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration;
|
||||
import net.sourceforge.pmd.reporting.ReportStats;
|
||||
import net.sourceforge.pmd.util.log.MessageReporter;
|
||||
import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter;
|
||||
|
||||
/**
|
||||
* Entry point for PMD's CLI. Use {@link #runPmd(PMDConfiguration)}
|
||||
* or {@link #runPmd(String...)} to mimic a CLI run. This class is
|
||||
* not a supported programmatic API anymore, use {@link PmdAnalysis}
|
||||
* for fine control over the PMD integration and execution.
|
||||
*
|
||||
* <p><strong>Warning:</strong> This class is not intended to be instantiated or subclassed. It will
|
||||
* be made final in PMD7.
|
||||
*
|
||||
* @deprecated This class is to be removed in PMD 7 in favor of a unified PmdCli entry point. {@link PmdAnalysis} should be used for non-CLI use-cases.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class PMD {
|
||||
|
||||
private static final String PMD_PACKAGE = "net.sourceforge.pmd";
|
||||
// not final, in order to re-initialize logging
|
||||
private static Logger log = LoggerFactory.getLogger(PMD_PACKAGE);
|
||||
|
||||
private PMD() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry to invoke PMD as command line tool. Note that this will
|
||||
* invoke {@link System#exit(int)}.
|
||||
*
|
||||
* @param args command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
StatusCode exitCode = runPmd(args);
|
||||
PMDCommandLineInterface.setStatusCodeOrExit(exitCode.toInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the command line arguments and executes PMD. Returns the
|
||||
* status code without exiting the VM. Note that the arguments parsing
|
||||
* may itself fail and produce a {@link StatusCode#ERROR}. This will
|
||||
* print the error message to standard error.
|
||||
*
|
||||
* @param args command line arguments
|
||||
*
|
||||
* @return the status code. Note that {@link PMDConfiguration#isFailOnViolation()}
|
||||
* (flag {@code --failOnViolation}) may turn an {@link StatusCode#OK} into a {@link
|
||||
* StatusCode#VIOLATIONS_FOUND}.
|
||||
*/
|
||||
public static StatusCode runPmd(String... args) {
|
||||
PmdParametersParseResult parseResult = PmdParametersParseResult.extractParameters(args);
|
||||
|
||||
// todo these warnings/errors should be output on a PmdRenderer
|
||||
if (!parseResult.getDeprecatedOptionsUsed().isEmpty()) {
|
||||
Entry<String, String> first = parseResult.getDeprecatedOptionsUsed().entrySet().iterator().next();
|
||||
log.warn("Some deprecated options were used on the command-line, including {}", first.getKey());
|
||||
log.warn("Consider replacing it with {}", first.getValue());
|
||||
}
|
||||
|
||||
if (parseResult.isVersion()) {
|
||||
System.out.println("PMD " + PMDVersion.VERSION);
|
||||
return StatusCode.OK;
|
||||
} else if (parseResult.isHelp()) {
|
||||
PMDCommandLineInterface.printJcommanderUsageOnConsole();
|
||||
System.out.println(PMDCommandLineInterface.buildUsageText());
|
||||
return StatusCode.OK;
|
||||
} else if (parseResult.isError()) {
|
||||
System.err.println(parseResult.getError().getMessage());
|
||||
System.err.println(LogMessages.runWithHelpFlagMessage());
|
||||
return StatusCode.ERROR;
|
||||
}
|
||||
|
||||
PMDConfiguration configuration = null;
|
||||
try {
|
||||
configuration = Objects.requireNonNull(
|
||||
parseResult.toConfiguration()
|
||||
);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.println("Cannot start analysis: " + e);
|
||||
log.debug(ExceptionUtils.getStackTrace(e));
|
||||
return StatusCode.ERROR;
|
||||
}
|
||||
|
||||
|
||||
Level curLogLevel = Slf4jSimpleConfiguration.getDefaultLogLevel();
|
||||
boolean resetLogLevel = false;
|
||||
try {
|
||||
// only reconfigure logging, if debug flag was used on command line
|
||||
// otherwise just use whatever is in conf/simplelogger.properties which happens automatically
|
||||
if (configuration.isDebug()) {
|
||||
Slf4jSimpleConfiguration.reconfigureDefaultLogLevel(Level.TRACE);
|
||||
// need to reload the logger with the new configuration
|
||||
log = LoggerFactory.getLogger(PMD_PACKAGE);
|
||||
resetLogLevel = true;
|
||||
}
|
||||
|
||||
MessageReporter pmdReporter = setupMessageReporter();
|
||||
configuration.setReporter(pmdReporter);
|
||||
|
||||
return runPmd(configuration);
|
||||
} finally {
|
||||
if (resetLogLevel) {
|
||||
// reset to the previous value
|
||||
Slf4jSimpleConfiguration.reconfigureDefaultLogLevel(curLogLevel);
|
||||
log = LoggerFactory.getLogger(PMD_PACKAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute PMD from a configuration. Returns the status code without
|
||||
* exiting the VM. This is the main entry point to run a full PMD run
|
||||
* with a manually created configuration.
|
||||
*
|
||||
* @param configuration Configuration to run
|
||||
*
|
||||
* @return the status code. Note that {@link PMDConfiguration#isFailOnViolation()}
|
||||
* (flag {@code --failOnViolation}) may turn an {@link StatusCode#OK} into a {@link
|
||||
* StatusCode#VIOLATIONS_FOUND}.
|
||||
*/
|
||||
public static StatusCode runPmd(PMDConfiguration configuration) {
|
||||
if (configuration.isBenchmark()) {
|
||||
TimeTracker.startGlobalTracking();
|
||||
}
|
||||
|
||||
MessageReporter pmdReporter = configuration.getReporter();
|
||||
try {
|
||||
PmdAnalysis pmd;
|
||||
try {
|
||||
pmd = PmdAnalysis.create(configuration);
|
||||
} catch (Exception e) {
|
||||
pmdReporter.errorEx("Could not initialize analysis", e);
|
||||
return StatusCode.ERROR;
|
||||
}
|
||||
try {
|
||||
log.debug("Current classpath:\n{}", System.getProperty("java.class.path"));
|
||||
ReportStats stats = pmd.runAndReturnStats();
|
||||
if (pmdReporter.numErrors() > 0) {
|
||||
// processing errors are ignored
|
||||
return StatusCode.ERROR;
|
||||
} else if (stats.getNumViolations() > 0 && configuration.isFailOnViolation()) {
|
||||
return StatusCode.VIOLATIONS_FOUND;
|
||||
} else {
|
||||
return StatusCode.OK;
|
||||
}
|
||||
} finally {
|
||||
pmd.close();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
pmdReporter.errorEx("Exception while running PMD.", e);
|
||||
PmdAnalysis.printErrorDetected(pmdReporter, 1);
|
||||
return StatusCode.ERROR;
|
||||
} finally {
|
||||
finishBenchmarker(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull MessageReporter setupMessageReporter() {
|
||||
|
||||
// create a top-level reporter
|
||||
// TODO CLI errors should also be reported through this
|
||||
// TODO this should not use the logger as backend, otherwise without
|
||||
// slf4j implementation binding, errors are entirely ignored.
|
||||
MessageReporter pmdReporter = new SimpleMessageReporter(log);
|
||||
// always install java.util.logging to slf4j bridge
|
||||
Slf4jSimpleConfiguration.installJulBridge();
|
||||
// logging, mostly for testing purposes
|
||||
Level defaultLogLevel = Slf4jSimpleConfiguration.getDefaultLogLevel();
|
||||
log.info("Log level is at {}", defaultLogLevel);
|
||||
return pmdReporter;
|
||||
}
|
||||
|
||||
private static void finishBenchmarker(PMDConfiguration configuration) {
|
||||
if (configuration.isBenchmark()) {
|
||||
final TimingReport timingReport = TimeTracker.stopGlobalTracking();
|
||||
|
||||
// TODO get specified report format from config
|
||||
final TimingReportRenderer renderer = new TextTimingReportRenderer();
|
||||
try {
|
||||
// Don't close this writer, we don't want to close stderr
|
||||
@SuppressWarnings("PMD.CloseResource")
|
||||
final Writer writer = new OutputStreamWriter(System.err);
|
||||
renderer.render(timingReport, writer);
|
||||
} catch (final IOException e) {
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents status codes that are used as exit codes during CLI runs.
|
||||
*
|
||||
* @see #runPmd(String[])
|
||||
* @deprecated This class is to be removed in PMD 7 in favor of a unified PmdCli entry point.
|
||||
*/
|
||||
@Deprecated
|
||||
public enum StatusCode {
|
||||
/** 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),
|
||||
/**
|
||||
* 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 code;
|
||||
|
||||
StatusCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/** Returns the exit code as used in CLI. */
|
||||
public int toInt() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -27,7 +27,6 @@ import net.sourceforge.pmd.annotation.DeprecatedUntil700;
|
||||
import net.sourceforge.pmd.cache.AnalysisCache;
|
||||
import net.sourceforge.pmd.cache.FileAnalysisCache;
|
||||
import net.sourceforge.pmd.cache.NoopAnalysisCache;
|
||||
import net.sourceforge.pmd.cli.PmdParametersParseResult;
|
||||
import net.sourceforge.pmd.internal.util.ClasspathClassLoader;
|
||||
import net.sourceforge.pmd.lang.Language;
|
||||
import net.sourceforge.pmd.lang.LanguagePropertyBundle;
|
||||
@ -41,45 +40,39 @@ import net.sourceforge.pmd.util.log.MessageReporter;
|
||||
import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter;
|
||||
|
||||
/**
|
||||
* This class contains the details for the runtime configuration of a PMD run.
|
||||
* You can either create one and set individual fields, or mimic a CLI run by
|
||||
* using {@link PmdParametersParseResult#extractParameters(String...) extractParameters}.
|
||||
* This class contains the details for the runtime configuration of a
|
||||
* PMD run. Once configured, use {@link PmdAnalysis#create(PMDConfiguration)}
|
||||
* in a try-with-resources to execute the analysis (see {@link PmdAnalysis}).
|
||||
*
|
||||
* <p>There are several aspects to the configuration of PMD.
|
||||
* <h3>Rulesets</h3>
|
||||
*
|
||||
* <p>The aspects related to generic PMD behavior:</p>
|
||||
* <ul>
|
||||
* <li>Suppress marker is used in source files to suppress a RuleViolation,
|
||||
* defaults to {@value DEFAULT_SUPPRESS_MARKER}. {@link #getSuppressMarker()}</li>
|
||||
* <li>The number of threads to create when invoking on multiple files, defaults
|
||||
* one thread per available processor. {@link #getThreads()}</li>
|
||||
* <li>A ClassLoader to use when loading classes during Rule processing (e.g.
|
||||
* during type resolution), defaults to ClassLoader of the Configuration class.
|
||||
* {@link #getClassLoader()}</li>
|
||||
* <li>A means to configure a ClassLoader using a prepended classpath String,
|
||||
* instead of directly setting it programmatically.
|
||||
* {@link #prependAuxClasspath(String)}</li>
|
||||
* <li>A LanguageVersionDiscoverer instance, which defaults to using the default
|
||||
* LanguageVersion of each Language. Means are provided to change the
|
||||
* LanguageVersion for each Language.
|
||||
* {@link #getLanguageVersionDiscoverer()}</li>
|
||||
* <li>You can configure paths to the rulesets to use with {@link #addRuleSet(String)}.
|
||||
* These can be file paths or classpath resources.</li>
|
||||
* <li>Use {@link #setMinimumPriority(RulePriority)} to control the minimum priority a
|
||||
* rule must have to be included. Defaults to the lowest priority, ie all rules are loaded.</li>
|
||||
* <li>Use {@link #setRuleSetFactoryCompatibilityEnabled(boolean)} to disable the
|
||||
* compatibility measures for removed and renamed rules in the rulesets that will
|
||||
* be loaded.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The aspects related to Rules and Source files are:</p>
|
||||
* <h3>Source files</h3>
|
||||
*
|
||||
* <ul>
|
||||
* <li>RuleSets URIs: {@link #getRuleSetPaths()}</li>
|
||||
* <li>A minimum priority threshold when loading Rules from RuleSets, defaults
|
||||
* to {@link RulePriority#LOW}. {@link #getMinimumPriority()}</li>
|
||||
* <li>The character encoding of source files, defaults to the system default as
|
||||
* <li>The default encoding of source files is the system default as
|
||||
* returned by <code>System.getProperty("file.encoding")</code>.
|
||||
* {@link #getSourceEncoding()}</li>
|
||||
* <li>A list of input paths to process for source files. This
|
||||
* may include files, directories, archives (e.g. ZIP files), etc.
|
||||
* {@link #getInputPathList()}</li>
|
||||
* <li>A flag which controls, whether {@link RuleSetLoader#enableCompatibility(boolean)} filter
|
||||
* should be used or not: #isRuleSetFactoryCompatibilityEnabled;
|
||||
* You can set it with {@link #setSourceEncoding(String)}.</li>
|
||||
* <li>The source files to analyze can be given in many ways. See
|
||||
* {@link #addInputPath(Path)} {@link #setInputFilePath(Path)}, {@link #setInputUri(URI)}.
|
||||
* <li>Files are assigned a language based on their name. The language
|
||||
* version of languages can be given with
|
||||
* {@link #setDefaultLanguageVersion(LanguageVersion)}.
|
||||
* The default language assignment can be overridden with
|
||||
* {@link #setForceLanguageVersion(LanguageVersion)}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>Rendering</h3>
|
||||
*
|
||||
* <ul>
|
||||
* <li>The renderer format to use for Reports. {@link #getReportFormat()}</li>
|
||||
* <li>The file to which the Report should render. {@link #getReportFile()}</li>
|
||||
@ -91,14 +84,18 @@ import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter;
|
||||
* {@link #isShowSuppressedViolations()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>The aspects related to special PMD behavior are:</p>
|
||||
* <h3>Language configuration </h3>
|
||||
* <ul>
|
||||
* <li>An indicator of whether PMD should log debug information.
|
||||
* {@link #isDebug()}</li>
|
||||
* <li>An indicator of whether PMD should perform stress testing behaviors, such
|
||||
* as randomizing the order of file processing. {@link #isStressTest()}</li>
|
||||
* <li>An indicator of whether PMD should log benchmarking information.
|
||||
* {@link #isBenchmark()}</li>
|
||||
* <li>Use {@link #setSuppressMarker(String)} to change the comment marker for suppression comments. Defaults to {@value #DEFAULT_SUPPRESS_MARKER}.</li>
|
||||
* <li>See {@link #setClassLoader(ClassLoader)} and {@link #prependAuxClasspath(String)} for
|
||||
* information for how to configure classpath for Java analysis.</li>
|
||||
* <li>You can set additional language properties with {@link #getLanguageProperties(Language)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>Miscellaneous</h3>
|
||||
* <ul>
|
||||
* <li>Use {@link #setThreads(int)} to control the parallelism of the analysis. Defaults
|
||||
* one thread per available processor. {@link #getThreads()}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class PMDConfiguration extends AbstractConfiguration {
|
||||
@ -113,7 +110,7 @@ public class PMDConfiguration extends AbstractConfiguration {
|
||||
private ClassLoader classLoader = getClass().getClassLoader();
|
||||
private final LanguageVersionDiscoverer languageVersionDiscoverer;
|
||||
private LanguageVersion forceLanguageVersion;
|
||||
private MessageReporter reporter = new SimpleMessageReporter(LoggerFactory.getLogger(PMD.class));
|
||||
private MessageReporter reporter = new SimpleMessageReporter(LoggerFactory.getLogger(PmdAnalysis.class));
|
||||
|
||||
// Rule and source file options
|
||||
private List<String> ruleSets = new ArrayList<>();
|
||||
@ -131,10 +128,6 @@ public class PMDConfiguration extends AbstractConfiguration {
|
||||
private boolean showSuppressedViolations = false;
|
||||
private boolean failOnViolation = true;
|
||||
|
||||
@Deprecated
|
||||
private boolean stressTest;
|
||||
@Deprecated
|
||||
private boolean benchmark;
|
||||
private AnalysisCache analysisCache = new NoopAnalysisCache();
|
||||
private boolean ignoreIncrementalAnalysis;
|
||||
private final LanguageRegistry langRegistry;
|
||||
@ -253,6 +246,9 @@ public class PMDConfiguration extends AbstractConfiguration {
|
||||
* <code>file://</code>) the file will be read with each line representing
|
||||
* an entry on the classpath.</p>
|
||||
*
|
||||
* <p>You can specify multiple class paths separated by `:` on Unix-systems or `;` under Windows.
|
||||
* See {@link File#pathSeparator}.
|
||||
*
|
||||
* @param classpath The prepended classpath.
|
||||
*
|
||||
* @throws IllegalArgumentException if the given classpath is invalid (e.g. does not exist)
|
||||
@ -738,60 +734,6 @@ public class PMDConfiguration extends AbstractConfiguration {
|
||||
this.reportProperties = reportProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the stress test indicator. If this value is <code>true</code> then
|
||||
* PMD will randomize the order of file processing to attempt to shake out
|
||||
* bugs.
|
||||
*
|
||||
* @return <code>true</code> if stress test is enbaled, <code>false</code>
|
||||
* otherwise.
|
||||
*
|
||||
* @deprecated For removal
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isStressTest() {
|
||||
return stressTest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the stress test indicator.
|
||||
*
|
||||
* @param stressTest
|
||||
* The stree test indicator to set.
|
||||
* @see #isStressTest()
|
||||
* @deprecated For removal.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setStressTest(boolean stressTest) {
|
||||
this.stressTest = stressTest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the benchmark indicator. If this value is <code>true</code> then
|
||||
* PMD will log benchmark information.
|
||||
*
|
||||
* @return <code>true</code> if benchmark logging is enbaled,
|
||||
* <code>false</code> otherwise.
|
||||
* @deprecated This behavior is down to CLI, not part of the core analysis.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isBenchmark() {
|
||||
return benchmark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the benchmark indicator.
|
||||
*
|
||||
* @param benchmark
|
||||
* The benchmark indicator to set.
|
||||
* @see #isBenchmark()
|
||||
* @deprecated This behavior is down to CLI, not part of the core analysis.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setBenchmark(boolean benchmark) {
|
||||
this.benchmark = benchmark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether PMD should exit with status 4 (the default behavior, true) if
|
||||
* violations are found or just with 0 (to not break the build, e.g.).
|
||||
|
@ -44,6 +44,7 @@ import net.sourceforge.pmd.lang.document.FileCollector;
|
||||
import net.sourceforge.pmd.lang.document.TextFile;
|
||||
import net.sourceforge.pmd.renderers.Renderer;
|
||||
import net.sourceforge.pmd.reporting.ConfigurableFileNameRenderer;
|
||||
import net.sourceforge.pmd.reporting.FileAnalysisListener;
|
||||
import net.sourceforge.pmd.reporting.GlobalAnalysisListener;
|
||||
import net.sourceforge.pmd.reporting.ListenerInitializer;
|
||||
import net.sourceforge.pmd.reporting.ReportStats;
|
||||
@ -53,11 +54,19 @@ import net.sourceforge.pmd.util.StringUtil;
|
||||
import net.sourceforge.pmd.util.log.MessageReporter;
|
||||
|
||||
/**
|
||||
* Main programmatic API of PMD. Create and configure a {@link PMDConfiguration},
|
||||
* Main programmatic API of PMD. This is not a CLI entry point, see module
|
||||
* {@code pmd-cli} for that.
|
||||
*
|
||||
* <h3>Usage overview</h3>
|
||||
*
|
||||
* Create and configure a {@link PMDConfiguration},
|
||||
* then use {@link #create(PMDConfiguration)} to obtain an instance.
|
||||
* You can perform additional configuration on the instance, eg adding
|
||||
* You can perform additional configuration on the instance, e.g. adding
|
||||
* files to process, or additional rulesets and renderers. Then, call
|
||||
* {@link #performAnalysis()}. Example:
|
||||
* {@link #performAnalysis()} or one of the related terminal methods.
|
||||
*
|
||||
* <h3>Simple example</h3>
|
||||
*
|
||||
* <pre>{@code
|
||||
* PMDConfiguration config = new PMDConfiguration();
|
||||
* config.setDefaultLanguageVersion(LanguageRegistry.findLanguageByTerseName("java").getVersion("11"));
|
||||
@ -81,6 +90,42 @@ import net.sourceforge.pmd.util.log.MessageReporter;
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Rendering reports</h3>
|
||||
*
|
||||
* If you just want to render a report to a file like with the CLI, you
|
||||
* should use a {@link Renderer}. You can add a custom one with {@link PmdAnalysis#addRenderer(Renderer)}.
|
||||
* You can add one of the builtin renderers from its ID using {@link PMDConfiguration#setReportFormat(String)}.
|
||||
*
|
||||
* <h3>Reports and events</h3>
|
||||
*
|
||||
* <p>If you want strongly typed access to violations and other analysis events,
|
||||
* you can implement and register a {@link GlobalAnalysisListener} with {@link #addListener(GlobalAnalysisListener)}.
|
||||
* The listener needs to provide a new {@link FileAnalysisListener} for each file,
|
||||
* which will receive events from the analysis. The listener's lifecycle
|
||||
* happens only once the analysis is started ({@link #performAnalysis()}).
|
||||
*
|
||||
* <p>If you want access to all events once the analysis ends instead of processing
|
||||
* events as they go, you can obtain a {@link Report} instance from {@link #performAnalysisAndCollectReport()},
|
||||
* or use {@link Report.GlobalReportBuilderListener} manually. Keep in
|
||||
* mind collecting a report is less memory-efficient than using a listener.
|
||||
*
|
||||
* <p>If you want to process events in batches, one per file, you can
|
||||
* use {@link Report.ReportBuilderListener}. to implement {@link GlobalAnalysisListener#startFileAnalysis(TextFile)}.
|
||||
*
|
||||
* <p>Listeners can be used alongside renderers.
|
||||
*
|
||||
* <h3>Specifying the Java classpath</h3>
|
||||
*
|
||||
* Java rules work better if you specify the path to the compiled classes
|
||||
* of the analysed sources. See {@link PMDConfiguration#prependAuxClasspath(String)}.
|
||||
*
|
||||
* <h3>Customizing message output</h3>
|
||||
*
|
||||
* <p>The analysis reports messages like meta warnings and errors through a
|
||||
* {@link MessageReporter} instance. To override how those messages are output,
|
||||
* you can set it in {@link PMDConfiguration#setReporter(MessageReporter)}.
|
||||
* By default, it forwards messages to SLF4J.
|
||||
*
|
||||
*/
|
||||
public final class PmdAnalysis implements AutoCloseable {
|
||||
|
||||
|
@ -1,228 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.cli;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sourceforge.pmd.PMD;
|
||||
import net.sourceforge.pmd.PMD.StatusCode;
|
||||
import net.sourceforge.pmd.PMDVersion;
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.Language;
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
import net.sourceforge.pmd.properties.PropertyDescriptor;
|
||||
import net.sourceforge.pmd.renderers.Renderer;
|
||||
import net.sourceforge.pmd.renderers.RendererFactory;
|
||||
|
||||
import com.beust.jcommander.JCommander;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
|
||||
/**
|
||||
* @author Romain Pelisse <belaran@gmail.com>
|
||||
* @deprecated Internal API. Use {@link PMD#runPmd(String...)} or {@link PMD#main(String[])},
|
||||
* or {@link PmdParametersParseResult} if you just want to produce a configuration.
|
||||
*/
|
||||
@Deprecated
|
||||
@InternalApi
|
||||
public final class PMDCommandLineInterface {
|
||||
|
||||
@Deprecated
|
||||
public static final String PROG_NAME = "pmd";
|
||||
|
||||
/**
|
||||
* @deprecated This is used for testing, but support for it will be removed in PMD 7.
|
||||
* Use {@link PMD#runPmd(String...)} or an overload to avoid exiting the VM. In PMD 7,
|
||||
* {@link PMD#main(String[])} will call {@link System#exit(int)} always.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String NO_EXIT_AFTER_RUN = "net.sourceforge.pmd.cli.noExit";
|
||||
|
||||
/**
|
||||
* @deprecated This is used for testing, but support for it will be removed in PMD 7.
|
||||
* Use {@link PMD#runPmd(String...)} or an overload to avoid exiting the VM. In PMD 7,
|
||||
* {@link PMD#main(String[])} will call {@link System#exit(int)} always.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String STATUS_CODE_PROPERTY = "net.sourceforge.pmd.cli.status";
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link StatusCode#OK}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int NO_ERRORS_STATUS = 0;
|
||||
/**
|
||||
* @deprecated Use {@link StatusCode#ERROR}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int ERROR_STATUS = 1;
|
||||
/**
|
||||
* @deprecated Use {@link StatusCode#VIOLATIONS_FOUND}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int VIOLATIONS_FOUND = 4;
|
||||
|
||||
private PMDCommandLineInterface() { }
|
||||
|
||||
/**
|
||||
* Note: this may terminate the VM.
|
||||
*
|
||||
* @deprecated Use {@link PmdParametersParseResult#extractParameters(String...)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static PMDParameters extractParameters(PMDParameters arguments, String[] args, String progName) {
|
||||
JCommander jcommander = new JCommander(arguments);
|
||||
jcommander.setProgramName(progName);
|
||||
|
||||
try {
|
||||
jcommander.parse(args);
|
||||
if (arguments.isHelp()) {
|
||||
jcommander.usage();
|
||||
System.out.println(buildUsageText());
|
||||
setStatusCodeOrExit(NO_ERRORS_STATUS);
|
||||
}
|
||||
} catch (ParameterException e) {
|
||||
jcommander.usage();
|
||||
System.out.println(buildUsageText());
|
||||
System.err.println(e.getMessage());
|
||||
setStatusCodeOrExit(ERROR_STATUS);
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public static String buildUsageText() {
|
||||
return "\n"
|
||||
+ "Mandatory arguments:\n"
|
||||
+ "1) A java source code filename or directory\n"
|
||||
+ "2) A report format \n"
|
||||
+ "3) A ruleset filename or a comma-delimited string of ruleset filenames\n"
|
||||
+ "\n"
|
||||
+ "For example: \n"
|
||||
+ getWindowsLaunchCmd() + " -d c:\\my\\source\\code -f html -R java-unusedcode\n\n"
|
||||
+ supportedVersions() + "\n"
|
||||
+ "Available report formats and their configuration properties are:" + "\n" + getReports()
|
||||
+ "\n" + getExamples() + "\n" + "\n" + "\n";
|
||||
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static String buildUsageText(JCommander jcommander) {
|
||||
return buildUsageText();
|
||||
}
|
||||
|
||||
private static String getExamples() {
|
||||
return getWindowsExample() + getUnixExample();
|
||||
}
|
||||
|
||||
private static String getWindowsLaunchCmd() {
|
||||
final String WINDOWS_PROMPT = "C:\\>";
|
||||
final String launchCmd = "pmd-bin-" + PMDVersion.VERSION + "\\bin\\pmd.bat";
|
||||
return WINDOWS_PROMPT + launchCmd;
|
||||
}
|
||||
|
||||
private static String getWindowsExample() {
|
||||
final String launchCmd = getWindowsLaunchCmd();
|
||||
final String WINDOWS_PATH_TO_CODE = "c:\\my\\source\\code ";
|
||||
|
||||
return "For example on windows: " + "\n"
|
||||
+ launchCmd + " --dir " + WINDOWS_PATH_TO_CODE
|
||||
+ "--format text -R rulesets/java/quickstart.xml --use-version java-1.5 --debug" + "\n"
|
||||
+ launchCmd + " -dir " + WINDOWS_PATH_TO_CODE
|
||||
+ "-f xml --rulesets rulesets/java/quickstart.xml,category/java/codestyle.xml --encoding UTF-8" + "\n"
|
||||
+ launchCmd + " --d " + WINDOWS_PATH_TO_CODE
|
||||
+ "--rulesets rulesets/java/quickstart.xml --aux-classpath lib\\commons-collections.jar;lib\\derby.jar"
|
||||
+ "\n"
|
||||
+ launchCmd + " -d " + WINDOWS_PATH_TO_CODE
|
||||
+ "-f html -R rulesets/java/quickstart.xml --aux-classpath file:///C:/my/classpathfile" + "\n" + "\n";
|
||||
}
|
||||
|
||||
private static String getUnixExample() {
|
||||
final String launchCmd = "$ pmd-bin-" + PMDVersion.VERSION + "/bin/run.sh pmd";
|
||||
return "For example on *nix: " + "\n"
|
||||
+ launchCmd
|
||||
+ " --dir /home/workspace/src/main/java/code -f html --rulesets rulesets/java/quickstart.xml,category/java/codestyle.xml"
|
||||
+ "\n"
|
||||
+ launchCmd
|
||||
+ " -d ./src/main/java/code -R rulesets/java/quickstart.xml -f xslt --property xsltFilename=my-own.xsl"
|
||||
+ "\n"
|
||||
+ launchCmd
|
||||
+ " -d ./src/main/java/code -R rulesets/java/quickstart.xml -f xslt --property xsltFilename=html-report-v2.xslt"
|
||||
+ "\n"
|
||||
+ " - html-report-v2.xslt is at https://github.com/pmd/pmd/tree/master/pmd-core/etc/xslt/html-report-v2.xslt"
|
||||
+ launchCmd
|
||||
+ " -d ./src/main/java/code -f html -R rulesets/java/quickstart.xml --aux-classpath commons-collections.jar:derby.jar"
|
||||
+ "\n";
|
||||
}
|
||||
|
||||
private static String supportedVersions() {
|
||||
return "Languages and version supported:" + "\n"
|
||||
+ LanguageRegistry.PMD.commaSeparatedList(Language::getId)
|
||||
+ "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing purpose only...
|
||||
*
|
||||
* @param args
|
||||
*
|
||||
* @deprecated Use {@link PMD#runPmd(String...)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static void main(String[] args) {
|
||||
System.out.println(PMDCommandLineInterface.buildUsageText());
|
||||
}
|
||||
|
||||
public static String jarName() {
|
||||
return "pmd-" + PMDVersion.VERSION + ".jar";
|
||||
}
|
||||
|
||||
private static String getReports() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (String reportName : RendererFactory.supportedRenderers()) {
|
||||
Renderer renderer = RendererFactory.createRenderer(reportName, new Properties());
|
||||
buf.append(" ").append(reportName).append(": ");
|
||||
if (!reportName.equals(renderer.getName())) {
|
||||
buf.append(" Deprecated alias for '").append(renderer.getName()).append("\n");
|
||||
continue;
|
||||
}
|
||||
buf.append(renderer.getDescription()).append("\n");
|
||||
|
||||
for (PropertyDescriptor<?> property : renderer.getPropertyDescriptors()) {
|
||||
buf.append(" ").append(property.name()).append(" - ");
|
||||
buf.append(property.description());
|
||||
Object deflt = property.defaultValue();
|
||||
if (deflt != null) {
|
||||
buf.append(" default: ").append(deflt);
|
||||
}
|
||||
buf.append("\n");
|
||||
}
|
||||
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static void setStatusCodeOrExit(int status) {
|
||||
if (isExitAfterRunSet()) {
|
||||
System.exit(status);
|
||||
} else {
|
||||
setStatusCode(status);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isExitAfterRunSet() {
|
||||
String noExit = System.getenv(NO_EXIT_AFTER_RUN);
|
||||
if (noExit == null) {
|
||||
noExit = System.getProperty(NO_EXIT_AFTER_RUN);
|
||||
}
|
||||
return noExit == null;
|
||||
}
|
||||
|
||||
private static void setStatusCode(int statusCode) {
|
||||
System.setProperty(STATUS_CODE_PROPERTY, Integer.toString(statusCode));
|
||||
}
|
||||
|
||||
public static void printJcommanderUsageOnConsole() {
|
||||
new JCommander(new PMDParameters()).usage();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,184 +0,0 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.cli;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
|
||||
import com.beust.jcommander.JCommander;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
|
||||
/**
|
||||
* Result of parsing a bunch of CLI arguments. Parsing may fail with an
|
||||
* exception, or succeed and produce a {@link PMDConfiguration}. If the
|
||||
* {@code --help} argument is mentioned, no configuration is produced.
|
||||
*/
|
||||
public final class PmdParametersParseResult {
|
||||
|
||||
private final PMDParameters result;
|
||||
private final ParameterException error;
|
||||
private final Map<String, String> deprecatedOptionsUsed;
|
||||
|
||||
PmdParametersParseResult(PMDParameters result,
|
||||
Map<String, String> deprecatedOptionsUsed) {
|
||||
this.result = Objects.requireNonNull(result);
|
||||
this.deprecatedOptionsUsed = deprecatedOptionsUsed;
|
||||
this.error = null;
|
||||
}
|
||||
|
||||
PmdParametersParseResult(ParameterException error, Map<String, String> deprecatedOptionsUsed) {
|
||||
this.result = null;
|
||||
this.error = Objects.requireNonNull(error);
|
||||
this.deprecatedOptionsUsed = deprecatedOptionsUsed;
|
||||
}
|
||||
|
||||
/** Returns true if parsing failed. */
|
||||
public boolean isError() {
|
||||
return result == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether parsing just requested the {@code --help} text.
|
||||
* In this case no configuration is produced.
|
||||
*/
|
||||
public boolean isHelp() {
|
||||
return !isError() && result.isHelp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether parsing just requested the {@code --version} text.
|
||||
* In this case no configuration is produced.
|
||||
*/
|
||||
public boolean isVersion() {
|
||||
return !isError() && result.isVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error if parsing failed. Parsing may fail if required
|
||||
* parameters are not provided, or if some parameters don't pass validation.
|
||||
* Otherwise returns null.
|
||||
*/
|
||||
public ParameterException getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of deprecated CLI options used by the command that
|
||||
* created this instance. Each key is a deprecated option that was used,
|
||||
* and the value is a suggested replacement (a piece of English text).
|
||||
*/
|
||||
public Map<String, String> getDeprecatedOptionsUsed() {
|
||||
return deprecatedOptionsUsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resulting configuration if parsing succeeded and neither {@link #isHelp()} nor {@link #isVersion()} is requested.
|
||||
* Otherwise returns null.
|
||||
*/
|
||||
public @Nullable PMDConfiguration toConfiguration() {
|
||||
return isValidParameterSet() ? result.toConfiguration() : null;
|
||||
}
|
||||
|
||||
private boolean isValidParameterSet() {
|
||||
return result != null && !isHelp() && !isVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an array of CLI parameters and returns a result (which may be failed).
|
||||
*
|
||||
* @param args Array of parameters
|
||||
*
|
||||
* @return A parse result
|
||||
*
|
||||
* @throws NullPointerException If the parameter array is null
|
||||
*/
|
||||
public static PmdParametersParseResult extractParameters(String... args) {
|
||||
Objects.requireNonNull(args, "Null parameter array");
|
||||
PMDParameters result = new PMDParameters();
|
||||
JCommander jcommander = new JCommander(result);
|
||||
jcommander.setProgramName("pmd");
|
||||
|
||||
try {
|
||||
parseAndValidate(jcommander, result, args);
|
||||
return new PmdParametersParseResult(result, filterDeprecatedOptions(args));
|
||||
} catch (ParameterException e) {
|
||||
return new PmdParametersParseResult(e, filterDeprecatedOptions(args));
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseAndValidate(JCommander jcommander, PMDParameters result, String[] args) {
|
||||
jcommander.parse(args);
|
||||
if (result.isHelp() || result.isVersion()) {
|
||||
return;
|
||||
}
|
||||
// jcommander has no special support for global parameter validation like this
|
||||
// For consistency we report this with a ParameterException
|
||||
if (result.getInputPaths().isEmpty()
|
||||
&& null == result.getUri()
|
||||
&& null == result.getFileListPath()) {
|
||||
throw new ParameterException(
|
||||
"Please provide a parameter for source root directory (--dir or -d), database URI (--uri or -u), or file list path (--file-list).");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Map<String, String> filterDeprecatedOptions(String... args) {
|
||||
Map<String, String> argSet = new LinkedHashMap<>(SUGGESTED_REPLACEMENT);
|
||||
argSet.keySet().retainAll(new HashSet<>(Arrays.asList(args)));
|
||||
return Collections.unmodifiableMap(argSet);
|
||||
}
|
||||
|
||||
/** Map of deprecated option to suggested replacement. */
|
||||
private static final Map<String, String> SUGGESTED_REPLACEMENT;
|
||||
|
||||
|
||||
static {
|
||||
Map<String, String> m = new LinkedHashMap<>();
|
||||
|
||||
m.put("-rulesets", "--rulesets (or -R)");
|
||||
m.put("-uri", "--uri");
|
||||
m.put("-dir", "--dir (or -d)");
|
||||
m.put("-filelist", "--file-list");
|
||||
m.put("-ignorelist", "--ignore-list");
|
||||
m.put("-format", "--format (or -f)");
|
||||
m.put("-debug", "--debug");
|
||||
m.put("-verbose", "--verbose");
|
||||
m.put("-help", "--help");
|
||||
m.put("-encoding", "--encoding");
|
||||
m.put("-threads", "--threads");
|
||||
m.put("-benchmark", "--benchmark");
|
||||
m.put("-stress", "--stress");
|
||||
m.put("-shortnames", PMDParameters.RELATIVIZE_PATHS_WITH);
|
||||
m.put("--short-names", PMDParameters.RELATIVIZE_PATHS_WITH);
|
||||
m.put("-showsuppressed", "--show-suppressed");
|
||||
m.put("-suppressmarker", "--suppress-marker");
|
||||
m.put("-minimumpriority", "--minimum-priority");
|
||||
m.put("-property", "--property");
|
||||
m.put("-reportfile", "--report-file");
|
||||
m.put("-force-language", "--force-language");
|
||||
m.put("-auxclasspath", "--aux-classpath");
|
||||
m.put("-failOnViolation", "--fail-on-violation");
|
||||
m.put("--failOnViolation", "--fail-on-violation");
|
||||
m.put("-norulesetcompatibility", "--no-ruleset-compatibility");
|
||||
m.put("-cache", "--cache");
|
||||
m.put("-no-cache", "--no-cache");
|
||||
m.put("-v", "--use-version"); // In PMD 7, -v will enable verbose mode
|
||||
m.put("-V", "--verbose"); // In PMD 7, -V will show the tool version
|
||||
m.put("-min", "--minimum-priority");
|
||||
m.put("-version", "--use-version");
|
||||
m.put("-language", "--use-version");
|
||||
m.put("-l", "--use-version");
|
||||
|
||||
SUGGESTED_REPLACEMENT = Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
@ -85,8 +85,6 @@ public class CPDConfiguration extends AbstractConfiguration {
|
||||
|
||||
private boolean failOnViolation = true;
|
||||
|
||||
private boolean debug = false;
|
||||
|
||||
public SourceCode sourceCodeFor(File file) {
|
||||
return new SourceCode(new SourceCode.FileCodeLoader(file, getSourceEncoding().name()));
|
||||
}
|
||||
@ -396,13 +394,4 @@ public class CPDConfiguration extends AbstractConfiguration {
|
||||
this.failOnViolation = failOnViolation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebug() {
|
||||
return debug;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDebug(boolean debug) {
|
||||
this.debug = debug;
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,6 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
import net.sourceforge.pmd.cli.PMDParameters;
|
||||
|
||||
public final class ShortFilenameUtil {
|
||||
|
||||
private ShortFilenameUtil() {
|
||||
@ -27,8 +24,6 @@ public final class ShortFilenameUtil {
|
||||
* @param inputFileName
|
||||
* @return
|
||||
*
|
||||
* @see PMDConfiguration#isReportShortNames()
|
||||
* @see PMDParameters#isShortnames()
|
||||
*/
|
||||
public static String determineFileName(List<String> inputPathPrefixes, String inputFileName) {
|
||||
for (final String prefix : inputPathPrefixes) {
|
||||
|
@ -97,6 +97,17 @@ public interface Language extends Comparable<Language> {
|
||||
*/
|
||||
List<LanguageVersion> getVersions();
|
||||
|
||||
/**
|
||||
* Returns the latest language version. May not be the
|
||||
* {@linkplain #getDefaultVersion() default}.
|
||||
*
|
||||
* @return The latest language version
|
||||
*/
|
||||
default LanguageVersion getLatestVersion() {
|
||||
List<LanguageVersion> versions = getVersions();
|
||||
return versions.get(versions.size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a complete set of supported version names for this language
|
||||
* including all aliases.
|
||||
|
@ -6,7 +6,10 @@ package net.sourceforge.pmd.renderers;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Objects;
|
||||
|
||||
import net.sourceforge.pmd.AbstractConfiguration;
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
import net.sourceforge.pmd.annotation.Experimental;
|
||||
import net.sourceforge.pmd.internal.util.IOUtil;
|
||||
import net.sourceforge.pmd.lang.document.FileId;
|
||||
@ -66,16 +69,20 @@ public abstract class AbstractRenderer extends AbstractPropertySource implements
|
||||
|
||||
@Override
|
||||
public void setFileNameRenderer(FileNameRenderer fileNameRenderer) {
|
||||
this.fileNameRenderer = fileNameRenderer;
|
||||
this.fileNameRenderer = Objects.requireNonNull(fileNameRenderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the filename that should be used in the report depending on the
|
||||
* option "shortnames". If the option is enabled, then the filename in the report
|
||||
* is without the directory prefix of the directories, that have been analyzed.
|
||||
* If the option "shortnames" is not enabled, then the fileId is returned as-is.
|
||||
* Determines the filename that should be used in the report for the
|
||||
* given ID. This uses the {@link FileNameRenderer} of this renderer.
|
||||
* In the PMD CLI, the file name renderer respects the {@link PMDConfiguration#getRelativizeRoots()}
|
||||
* relativize roots to output relative paths.
|
||||
*
|
||||
* <p>A renderer does not have to use this method to output paths.
|
||||
* Some report formats require a specific format for paths, eg URIs.
|
||||
* They can implement this ad-hoc.
|
||||
*/
|
||||
protected String determineFileName(FileId fileId) {
|
||||
protected final String determineFileName(FileId fileId) {
|
||||
return fileNameRenderer.getDisplayName(fileId);
|
||||
}
|
||||
|
||||
|
@ -110,13 +110,20 @@ public interface Renderer extends PropertySource {
|
||||
*/
|
||||
Writer getWriter();
|
||||
|
||||
/**
|
||||
* Set the {@link FileNameRenderer} used to render file paths to the report.
|
||||
* Note that this renderer does not have to use the parameter to output paths.
|
||||
* Some report formats require a specific format for paths (eg a URI), and are
|
||||
* allowed to circumvent the provided strategy.
|
||||
*
|
||||
* @param fileNameRenderer a non-null file name renderer
|
||||
*/
|
||||
void setFileNameRenderer(FileNameRenderer fileNameRenderer);
|
||||
|
||||
/**
|
||||
* Set the Writer for the Renderer.
|
||||
*
|
||||
* @param writer
|
||||
* The Writer.
|
||||
* @param writer The Writer.
|
||||
*/
|
||||
void setWriter(Writer writer);
|
||||
|
||||
|
@ -8,6 +8,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.Report;
|
||||
import net.sourceforge.pmd.Report.ProcessingError;
|
||||
import net.sourceforge.pmd.Report.SuppressedViolation;
|
||||
import net.sourceforge.pmd.RuleViolation;
|
||||
@ -17,10 +18,13 @@ import net.sourceforge.pmd.util.AssertionUtil;
|
||||
/**
|
||||
* A handler for events occuring during analysis of a single file. Instances
|
||||
* are only used on a single thread for their entire lifetime, so don't
|
||||
* need to be synchronized to access state they own.
|
||||
* need to be synchronized to access state they own. File listeners are
|
||||
* spawned by a {@link GlobalAnalysisListener}.
|
||||
*
|
||||
* <p>Listeners are assumed to be ready to receive events as soon as they
|
||||
* are constructed.
|
||||
*
|
||||
* @see Report.ReportBuilderListener
|
||||
*/
|
||||
public interface FileAnalysisListener extends AutoCloseable {
|
||||
|
||||
|
@ -216,30 +216,6 @@ class PmdConfigurationTest {
|
||||
assertEquals(0, configuration.getReportProperties().size(), "Replaced report properties size");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDebug() {
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
assertEquals(false, configuration.isDebug(), "Default debug");
|
||||
configuration.setDebug(true);
|
||||
assertEquals(true, configuration.isDebug(), "Changed debug");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStressTest() {
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
assertEquals(false, configuration.isStressTest(), "Default stress test");
|
||||
configuration.setStressTest(true);
|
||||
assertEquals(true, configuration.isStressTest(), "Changed stress test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBenchmark() {
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
assertEquals(false, configuration.isBenchmark(), "Default benchmark");
|
||||
configuration.setBenchmark(true);
|
||||
assertEquals(true, configuration.isBenchmark(), "Changed benchmark");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAnalysisCache(@TempDir Path folder) throws IOException {
|
||||
final PMDConfiguration configuration = new PMDConfiguration();
|
||||
|
@ -1,110 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.cli;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
import net.sourceforge.pmd.cache.NoopAnalysisCache;
|
||||
import net.sourceforge.pmd.lang.LanguageRegistry;
|
||||
|
||||
import com.github.stefanbirkner.systemlambda.SystemLambda;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test for {@link PMDCommandLineInterface}
|
||||
*/
|
||||
class PMDCommandLineInterfaceTest {
|
||||
|
||||
@BeforeEach
|
||||
void clearSystemProperties() {
|
||||
System.clearProperty(PMDCommandLineInterface.NO_EXIT_AFTER_RUN);
|
||||
System.clearProperty(PMDCommandLineInterface.STATUS_CODE_PROPERTY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testProperties() {
|
||||
PMDParameters params = new PMDParameters();
|
||||
String[] args = { "-d", "source_folder", "-f", "yahtml", "-P", "outputDir=output_folder", "-R", "java-empty", };
|
||||
PMDCommandLineInterface.extractParameters(params, args, "PMD");
|
||||
|
||||
assertEquals("output_folder", params.getProperties().getProperty("outputDir"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleProperties() {
|
||||
PMDParameters params = new PMDParameters();
|
||||
String[] args = { "-d", "source_folder", "-f", "ideaj", "-P", "sourcePath=/home/user/source/", "-P",
|
||||
"fileName=Foo.java", "-P", "classAndMethodName=Foo.method", "-R", "java-empty", };
|
||||
PMDCommandLineInterface.extractParameters(params, args, "PMD");
|
||||
|
||||
assertEquals("/home/user/source/", params.getProperties().getProperty("sourcePath"));
|
||||
assertEquals("Foo.java", params.getProperties().getProperty("fileName"));
|
||||
assertEquals("Foo.method", params.getProperties().getProperty("classAndMethodName"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testNoCacheSwitch() {
|
||||
PMDParameters params = new PMDParameters();
|
||||
String[] args = {"-d", "source_folder", "-f", "ideaj", "-R", "java-empty", "-cache", "/home/user/.pmd/cache", "-no-cache", };
|
||||
PMDCommandLineInterface.extractParameters(params, args, "PMD");
|
||||
|
||||
assertTrue(params.isIgnoreIncrementalAnalysis());
|
||||
PMDConfiguration config = params.toConfiguration(LanguageRegistry.PMD);
|
||||
assertTrue(config.isIgnoreIncrementalAnalysis());
|
||||
assertTrue(config.getAnalysisCache() instanceof NoopAnalysisCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoCacheSwitchLongOption() {
|
||||
PMDParameters params = new PMDParameters();
|
||||
String[] args = {"-d", "source_folder", "-f", "ideaj", "-R", "java-empty", "--cache", "/home/user/.pmd/cache", "--no-cache", };
|
||||
PMDCommandLineInterface.extractParameters(params, args, "PMD");
|
||||
|
||||
assertTrue(params.isIgnoreIncrementalAnalysis());
|
||||
PMDConfiguration config = params.toConfiguration();
|
||||
assertTrue(config.isIgnoreIncrementalAnalysis());
|
||||
assertTrue(config.getAnalysisCache() instanceof NoopAnalysisCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetStatusCodeOrExitDoExit() throws Exception {
|
||||
int code = SystemLambda.catchSystemExit(() -> PMDCommandLineInterface.setStatusCodeOrExit(0));
|
||||
assertEquals(0, code);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetStatusCodeOrExitSetStatus() {
|
||||
System.setProperty(PMDCommandLineInterface.NO_EXIT_AFTER_RUN, "1");
|
||||
|
||||
PMDCommandLineInterface.setStatusCodeOrExit(0);
|
||||
assertEquals(System.getProperty(PMDCommandLineInterface.STATUS_CODE_PROPERTY), "0");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuildUsageText() {
|
||||
// no exception..
|
||||
assertNotNull(PMDCommandLineInterface.buildUsageText());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOnlyFileListOption() {
|
||||
PMDParameters params = new PMDParameters();
|
||||
String[] args = {"--file-list", "pmd.filelist", "-f", "text", "-R", "rulesets/java/quickstart.xml", "--no-cache", };
|
||||
PMDCommandLineInterface.extractParameters(params, args, "PMD");
|
||||
|
||||
PMDConfiguration config = params.toConfiguration();
|
||||
assertEquals("pmd.filelist", config.getInputFile().toString());
|
||||
assertThat(config.getInputPathList(), empty()); // no additional input paths
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.cli;
|
||||
|
||||
import static net.sourceforge.pmd.util.CollectionUtil.listOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
import net.sourceforge.pmd.util.CollectionUtil;
|
||||
|
||||
class PMDParametersTest {
|
||||
|
||||
@Test
|
||||
void testMultipleDirsAndRuleSets() {
|
||||
PmdParametersParseResult result = PmdParametersParseResult.extractParameters(
|
||||
"-d", "a", "b", "-R", "x.xml", "y.xml"
|
||||
);
|
||||
assertMultipleDirsAndRulesets(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleDirsAndRuleSetsWithCommas() {
|
||||
PmdParametersParseResult result = PmdParametersParseResult.extractParameters(
|
||||
"-d", "a,b", "-R", "x.xml,y.xml"
|
||||
);
|
||||
assertMultipleDirsAndRulesets(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleDirsAndRuleSetsWithRepeatedOption() {
|
||||
PmdParametersParseResult result = PmdParametersParseResult.extractParameters(
|
||||
"-d", "a", "-d", "b", "-R", "x.xml", "-R", "y.xml"
|
||||
);
|
||||
assertMultipleDirsAndRulesets(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoPositionalParametersAllowed() {
|
||||
assertError(
|
||||
// vvvv
|
||||
"-R", "x.xml", "-d", "a", "--", "-d", "b"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private void assertMultipleDirsAndRulesets(PmdParametersParseResult result) {
|
||||
assertFalse(result.isError());
|
||||
PMDConfiguration config = result.toConfiguration();
|
||||
assertEquals(CollectionUtil.map(config.getInputPathList(), Path::toString), listOf("a", "b"));
|
||||
assertEquals(config.getRuleSetPaths(), listOf("x.xml", "y.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyDirOption() {
|
||||
assertError("-d", "-R", "y.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyRulesetOption() {
|
||||
assertError("-R", "-d", "something");
|
||||
}
|
||||
|
||||
private void assertError(String... params) {
|
||||
PmdParametersParseResult result = PmdParametersParseResult.extractParameters(params);
|
||||
assertTrue(result.isError());
|
||||
}
|
||||
|
||||
}
|
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