Merge branch 'master' into pr/2964

This commit is contained in:
Clément Fournier
2021-01-08 21:31:39 +01:00
163 changed files with 4994 additions and 433 deletions
+4
View File
@@ -181,6 +181,10 @@ function pmd_ci_build_and_upload_doc() {
pmd_code_removeJavadoc "${VERSION}-SNAPSHOT"
# updating github release text
rm -f .bundle/config
bundle config set --local path vendor/bundle
bundle config set --local with release_notes_preprocessing
bundle install
# renders, and skips the first 6 lines - the Jekyll front-matter
local rendered_release_notes=$(bundle exec .ci/render_release_notes.rb docs/pages/release_notes.md | tail -n +6)
local release_name="PMD ${VERSION} ($(date -u +%d-%B-%Y))"
+12 -1
View File
@@ -20,7 +20,18 @@ function maven_dependencies_resolve() {
dokka_version=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${dokka.version}' \
--non-recursive org.codehaus.mojo:exec-maven-plugin:3.0.0:exec)
./mvnw dependency:resolve
# build first the modules, that have dependencies between themselves
# first build pmd-lang-test, pmd-test and pmd-core - used by all modules
./mvnw clean install -pl pmd-core,pmd-test,pmd-lang-test -DskipTests -Dpmd.skip=true \
-Dcheckstyle.skip=true -Dmaven.javadoc.skip=true -Dmaven.source.skip=true
# then build dependencies for pmd-visualforce needs: pmd-apex->pmd-apex-jorje+pmd-test+pmd-core
./mvnw clean install -pl pmd-core,pmd-test,pmd-lang-test,pmd-apex-jorje,pmd-apex -DskipTests -Dpmd.skip=true \
-Dcheckstyle.skip=true -Dmaven.javadoc.skip=true -Dmaven.source.skip=true
# the resolve most other projects. The excluded projects depend on other projects in the reactor, which is not
# completely built yet, so these are excluded.
./mvnw dependency:resolve -pl '!pmd-dist,!pmd-java8,!pmd-doc,!pmd-scala'
./mvnw dependency:get -DgroupId=org.jetbrains.dokka \
-DartifactId=dokka-maven-plugin \
-Dversion=${dokka_version} \
+4 -2
View File
@@ -61,15 +61,17 @@ function regression_tester_uploadBaseline() {
log_info "Generating and uploading baseline for pmdtester..."
cd ..
bundle config --local gemfile pmd/Gemfile
bundle config set --local path pmd/vendor/bundle
bundle exec pmdtester \
--mode single \
--local-git-repo ./pmd \
--patch-branch ${PMD_CI_BRANCH} \
--patch-branch ${PMD_CI_BRANCH:-$PMD_CI_TAG} \
--patch-config ./pmd/.ci/files/all-java.xml \
--list-of-project ./pmd/.ci/files/project-list.xml --html-flag \
--error-recovery
cd target/reports
BRANCH_FILENAME="${PMD_CI_BRANCH/\//_}"
BRANCH_FILENAME="${PMD_CI_BRANCH:-$PMD_CI_TAG}"
BRANCH_FILENAME="${BRANCH_FILENAME/\//_}"
zip -q -r ${BRANCH_FILENAME}-baseline.zip ${BRANCH_FILENAME}/
# ssh-key for pmd-code.org is setup already by pmd_ci_setup_ssh
scp ${BRANCH_FILENAME}-baseline.zip pmd@pmd-code.org:/httpdocs/pmd-regression-tester/
+3
View File
@@ -1,5 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Question
url: https://github.com/pmd/pmd/discussions?discussions_q=category%3AQ%26A
about: Feel free to ask any question about PMD and its usage
- name: PMD Designer Issues
url: https://github.com/pmd/pmd-designer/issues
about: Issues about the rule designer
-14
View File
@@ -1,14 +0,0 @@
---
name: Question
about: Feel free to ask any question about PMD and its usage
title: ''
labels: 'a:question'
assignees: ''
---
<!-- Have a look at https://github.com/pmd/pmd/issues?utf8=%E2%9C%93&q=label%3Aa%3Aquestion if there is already
a similar question -->
**Description:**
+4
View File
@@ -10,6 +10,10 @@ jobs:
continue-on-error: false
steps:
- uses: actions/checkout@v2
- name: Set up Ruby 2.7
uses: actions/setup-ruby@v1
with:
ruby-version: 2.7
- name: Check Environment
run: .ci/check-environment.sh
shell: bash
+1 -1
View File
@@ -1,7 +1,7 @@
# PMD
[![Join the chat at https://gitter.im/pmd/pmd](https://badges.gitter.im/pmd/pmd.svg)](https://gitter.im/pmd/pmd?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://github.com/pmd/pmd/workflows/.github/workflows/pushes.yml/badge.svg?branch=master)](https://github.com/pmd/pmd/actions)
[![Build Status](https://github.com/pmd/pmd/workflows/Pushes/badge.svg?branch=master)](https://github.com/pmd/pmd/actions)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.sourceforge.pmd/pmd/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.sourceforge.pmd/pmd)
[![Reproducible Builds](https://img.shields.io/badge/Reproducible_Builds-ok-green?labelColor=blue)](https://github.com/jvm-repo-rebuild/reproducible-central#net.sourceforge.pmd:pmd)
[![Coverage Status](https://coveralls.io/repos/github/pmd/pmd/badge.svg)](https://coveralls.io/github/pmd/pmd)
+3 -3
View File
@@ -1,9 +1,9 @@
repository: pmd/pmd
pmd:
version: 6.30.0-SNAPSHOT
previous_version: 6.29.0
date: ??-November-2020
version: 6.31.0-SNAPSHOT
previous_version: 6.30.0
date: ??-January-2021
release_type: minor
# release types: major, minor, bugfix
+41
View File
@@ -125,6 +125,47 @@ the breaking API changes will be performed in 7.0.0.
an API is tagged as `@Deprecated` or not in the latest minor release. During the development of 7.0.0,
we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %}
#### 6.30.0
##### Deprecated API
###### Around RuleSet parsing
* {% jdoc core::RuleSetFactory %} and {% jdoc core::RuleSetFactoryUtils %} have been deprecated in favor of {% jdoc core::RuleSetLoader %}. This is easier to configure, and more maintainable than the multiple overloads of `RuleSetFactoryUtils`.
* Some static creation methods have been added to {% jdoc core::RuleSet %} for simple cases, eg {% jdoc core::RuleSet#forSingleRule(core::Rule) %}. These replace some counterparts in {% jdoc core::RuleSetFactory %}
* Since {% jdoc core::RuleSets %} is also deprecated, many APIs that require a RuleSets instance now are deprecated, and have a counterpart that expects a `List<RuleSet>`.
* {% jdoc core::RuleSetReferenceId %}, {% jdoc core::RuleSetReference %}, {% jdoc core::RuleSetFactoryCompatibility %} are deprecated. They are most likely not relevant outside of the implementation of pmd-core.
###### Around the `PMD` class
Many classes around PMD's entry point ({% jdoc core::PMD %}) have been deprecated as internal, including:
* The contents of the packages {% jdoc_package core::cli %}, {% jdoc_package core::processor %}
* {% jdoc core::SourceCodeProcessor %}
* The constructors of {% jdoc core::PMD %} (the class will be made a utility class)
###### Miscellaneous
* {% jdoc !!java::lang.java.ast.ASTPackageDeclaration#getPackageNameImage() %},
{% jdoc !!java::lang.java.ast.ASTTypeParameter#getParameterName() %}
and the corresponding XPath attributes. In both cases they're replaced with a new method `getName`,
the attribute is `@Name`.
* {% jdoc !!java::lang.java.ast.ASTClassOrInterfaceBody#isAnonymousInnerClass() %},
and {% jdoc !!java::lang.java.ast.ASTClassOrInterfaceBody#isEnumChild() %},
refs [#905](https://github.com/pmd/pmd/issues/905)
##### Internal API
Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
You can identify them with the `@InternalApi` annotation. You'll also get a deprecation warning.
* {% jdoc !!javascript::lang.ecmascript.Ecmascript3Handler %}
* {% jdoc !!javascript::lang.ecmascript.Ecmascript3Parser %}
* {% jdoc !!javascript::lang.ecmascript.ast.EcmascriptParser#parserOptions %}
* {% jdoc !!javascript::lang.ecmascript.ast.EcmascriptParser#getSuppressMap() %}
* {% jdoc !!core::lang.rule.ParametricRuleViolation %}
* {% jdoc !!core::lang.ParserOptions#suppressMarker %}
* {% jdoc !!modelica::lang.modelica.rule.ModelicaRuleViolationFactory %}
#### 6.29.0
No changes.
+1 -1
View File
@@ -12,7 +12,7 @@ author: Tom Copeland, Xavier Le Vourch <xlv@users.sourceforge.net>
* JDK 11 or higher
{% include note.html content="While Java 11 is required for building, running PMD only requires Java 7 (or Java 8 for Apex and the Designer)." %}
{% include note.html content="While Java 11 is required for building, running PMD only requires Java 7 (or Java 8 for Apex, Scala, Visualforce, and the Designer)." %}
Youll need to either check out the source code or download the latest source release. Assuming youve got the latest source release, unzip it to a directory:
+1 -51
View File
@@ -14,61 +14,11 @@ This is a {{ site.pmd.release_type }} release.
### New and noteworthy
##### CPD
* The C# module now supports the new option [`--ignore-literal-sequences`](https://pmd.github.io/latest/pmd_userdocs_cpd.html#-ignore-literal-sequences), which can be used to avoid detection of some uninteresting clones. Support for other languages may be added in the future. See [#2945](https://github.com/pmd/pmd/pull/2945)
* The Scala module now supports [suppression](https://pmd.github.io/latest/pmd_userdocs_cpd.html#suppression) through `CPD-ON`/`CPD-OFF` comment pairs. See [#2929](https://github.com/pmd/pmd/pull/2929)
### Fixed Issues
* core
* [#1939](https://github.com/pmd/pmd/issues/1939): \[core] XPath expressions return handling
* [#1961](https://github.com/pmd/pmd/issues/1961): \[core] Text renderer should include name of violated rule
* [#2874](https://github.com/pmd/pmd/pull/2874): \[core] Fix XMLRenderer with UTF-16
* cs
* [#2938](https://github.com/pmd/pmd/pull/2938): \[cs] CPD: ignoring using directives could not be disabled
* java
* [#2911](https://github.com/pmd/pmd/issues/2911): \[java] `ClassTypeResolver#searchNodeNameForClass` leaks memory
* [#2934](https://github.com/pmd/pmd/pull/2934): \[java] CompareObjectsWithEquals / UseEqualsToCompareStrings - False negatives with fields
* [#2940](https://github.com/pmd/pmd/pull/2940): \[java] Catch additional TypeNotPresentExceptions / LinkageErrors
* scala
* [#2480](https://github.com/pmd/pmd/issues/2480): \[scala] Support CPD suppressions
### API Changes
#### Deprecated API
* {% jdoc !!java::lang.java.ast.ASTPackageDeclaration#getPackageNameImage() %},
{% jdoc !!java::lang.java.ast.ASTTypeParameter#getParameterName() %}
and the corresponding XPath attributes. In both cases they're replaced with a new method `getName`,
the attribute is `@Name`.
* {% jdoc !!java::lang.java.ast.ASTClassOrInterfaceBody#isAnonymousInnerClass() %},
and {% jdoc !!java::lang.java.ast.ASTClassOrInterfaceBody#isEnumChild() %},
refs [#905](https://github.com/pmd/pmd/issues/905)
#### Internal API
Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
You can identify them with the `@InternalApi` annotation. You'll also get a deprecation warning.
* {% jdoc !!javascript::lang.ecmascript.Ecmascript3Handler %}
* {% jdoc !!javascript::lang.ecmascript.Ecmascript3Parser %}
* {% jdoc !!javascript::lang.ecmascript.ast.EcmascriptParser#parserOptions %}
* {% jdoc !!javascript::lang.ecmascript.ast.EcmascriptParser#getSuppressMap() %}
* {% jdoc !!core::lang.rule.ParametricRuleViolation %}
* {% jdoc !!core::lang.ParserOptions#suppressMarker %}
* {% jdoc !!modelica::lang.modelica.rule.ModelicaRuleViolationFactory %}
### External Contributions
* [#2914](https://github.com/pmd/pmd/pull/2914): \[core] Include rule name in text renderer - [Gunther Schrijvers](https://github.com/GuntherSchrijvers)
* [#2925](https://github.com/pmd/pmd/pull/2925): Cleanup: Correct annotation array initializer indents from checkstyle #8083 - [Abhishek Kumar](https://github.com/Abhishek-kumar09)
* [#2929](https://github.com/pmd/pmd/pull/2929): \[scala] Add support for CPD-ON and CPD-OFF special comments - [Andy Robinson](https://github.com/andyrobinson)
* [#2936](https://github.com/pmd/pmd/pull/2936): \[java] (doc) Fix typo: "an accessor" not "a" - [Igor Moreno](https://github.com/igormoreno)
* [#2938](https://github.com/pmd/pmd/pull/2938): \[cs] CPD: fix issue where ignoring using directives could not be disabled - [Maikel Steneker](https://github.com/maikelsteneker)
* [#2945](https://github.com/pmd/pmd/pull/2945): \[cs] Add option to ignore sequences of literals - [Maikel Steneker](https://github.com/maikelsteneker)
{% endtocmaker %}
+117
View File
@@ -5,6 +5,123 @@ permalink: pmd_release_notes_old.html
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
## 12-December-2020 - 6.30.0
The PMD team is pleased to announce PMD 6.30.0.
This is a minor release.
### Table Of Contents
* [New and noteworthy](#new-and-noteworthy)
* [CPD](#cpd)
* [Type information for VisualForce](#type-information-for-visualforce)
* [Fixed Issues](#fixed-issues)
* [API Changes](#api-changes)
* [Deprecated API](#deprecated-api)
* [Around RuleSet parsing](#around-ruleset-parsing)
* [Around the `PMD` class](#around-the-`pmd`-class)
* [Miscellaneous](#miscellaneous)
* [Internal API](#internal-api)
* [External Contributions](#external-contributions)
* [Stats](#stats)
### New and noteworthy
##### CPD
* The C# module now supports the new option [`--ignore-literal-sequences`](https://pmd.github.io/latest/pmd_userdocs_cpd.html#-ignore-literal-sequences), which can be used to avoid detection of some uninteresting clones. Support for other languages may be added in the future. See [#2945](https://github.com/pmd/pmd/pull/2945)
* The Scala module now supports [suppression](https://pmd.github.io/latest/pmd_userdocs_cpd.html#suppression) through `CPD-ON`/`CPD-OFF` comment pairs. See [#2929](https://github.com/pmd/pmd/pull/2929)
##### Type information for VisualForce
The Visualforce AST now can resolve the data type of Visualforce expressions that reference Apex Controller properties and Custom Object fields. This feature improves the precision of existing rules, like [`VfUnescapeEl`](https://pmd.github.io/pmd-6.30.0/pmd_rules_vf_security.html#vfunescapeel).
This can be configured using two environment variables:
* `PMD_VF_APEXDIRECTORIES`: Comma separated list of directories for Apex classes. Absolute or relative to the Visualforce directory. Default is `../classes`. Specifying an empty string will disable data type resolution for Apex Controller properties.
* `PMD_VF_OBJECTSDIRECTORIES`: Comma separated list of directories for Custom Objects. Absolute or relative to the Visualforce directory. Default is `../objects`. Specifying an empty string will disable data type resolution for Custom Object fields.
This feature is experimental, in particular, expect changes to the way the configuration is specified. We'll probably extend the CLI instead of relying on environment variables in a future version.
Thanks to Jeff Bartolotta and Roopa Mohan for contributing this!
### Fixed Issues
* core
* [#1939](https://github.com/pmd/pmd/issues/1939): \[core] XPath expressions return handling
* [#1961](https://github.com/pmd/pmd/issues/1961): \[core] Text renderer should include name of violated rule
* [#2874](https://github.com/pmd/pmd/pull/2874): \[core] Fix XMLRenderer with UTF-16
* cs
* [#2938](https://github.com/pmd/pmd/pull/2938): \[cs] CPD: ignoring using directives could not be disabled
* java
* [#2911](https://github.com/pmd/pmd/issues/2911): \[java] `ClassTypeResolver#searchNodeNameForClass` leaks memory
* [#2934](https://github.com/pmd/pmd/pull/2934): \[java] CompareObjectsWithEquals / UseEqualsToCompareStrings - False negatives with fields
* [#2940](https://github.com/pmd/pmd/pull/2940): \[java] Catch additional TypeNotPresentExceptions / LinkageErrors
* scala
* [#2480](https://github.com/pmd/pmd/issues/2480): \[scala] Support CPD suppressions
### API Changes
#### Deprecated API
##### Around RuleSet parsing
* <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/RuleSetFactory.html#"><code>RuleSetFactory</code></a> and <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/RulesetsFactoryUtils.html#"><code>RulesetsFactoryUtils</code></a> have been deprecated in favor of <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/RuleSetLoader.html#"><code>RuleSetLoader</code></a>. This is easier to configure, and more maintainable than the multiple overloads of `RuleSetFactoryUtils`.
* Some static creation methods have been added to <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/RuleSet.html#"><code>RuleSet</code></a> for simple cases, eg <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/RuleSet.html#forSingleRule(net.sourceforge.pmd.Rule)"><code>forSingleRule</code></a>. These replace some counterparts in <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/RuleSetFactory.html#"><code>RuleSetFactory</code></a>
* Since <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/RuleSets.html#"><code>RuleSets</code></a> is also deprecated, many APIs that require a RuleSets instance now are deprecated, and have a counterpart that expects a `List<RuleSet>`.
* <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/RuleSetReferenceId.html#"><code>RuleSetReferenceId</code></a>, <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/RuleSetReference.html#"><code>RuleSetReference</code></a>, <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/RuleSetFactoryCompatibility.html#"><code>RuleSetFactoryCompatibility</code></a> are deprecated. They are most likely not relevant outside of the implementation of pmd-core.
##### Around the `PMD` class
Many classes around PMD's entry point (<a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/PMD.html#"><code>PMD</code></a>) have been deprecated as internal, including:
* The contents of the packages <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/cli/package-summary.html#"><code>net.sourceforge.pmd.cli</code></a>, <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/processor/package-summary.html#"><code>net.sourceforge.pmd.processor</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/SourceCodeProcessor.html#"><code>SourceCodeProcessor</code></a>
* The constructors of <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/PMD.html#"><code>PMD</code></a> (the class will be made a utility class)
##### Miscellaneous
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.30.0/net/sourceforge/pmd/lang/java/ast/ASTPackageDeclaration.html#getPackageNameImage()"><code>ASTPackageDeclaration#getPackageNameImage</code></a>,
<a href="https://docs.pmd-code.org/apidocs/pmd-java/6.30.0/net/sourceforge/pmd/lang/java/ast/ASTTypeParameter.html#getParameterName()"><code>ASTTypeParameter#getParameterName</code></a>
and the corresponding XPath attributes. In both cases they're replaced with a new method `getName`,
the attribute is `@Name`.
* <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.30.0/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBody.html#isAnonymousInnerClass()"><code>ASTClassOrInterfaceBody#isAnonymousInnerClass</code></a>,
and <a href="https://docs.pmd-code.org/apidocs/pmd-java/6.30.0/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBody.html#isEnumChild()"><code>ASTClassOrInterfaceBody#isEnumChild</code></a>,
refs [#905](https://github.com/pmd/pmd/issues/905)
#### Internal API
Those APIs are not intended to be used by clients, and will be hidden or removed with PMD 7.0.0.
You can identify them with the `@InternalApi` annotation. You'll also get a deprecation warning.
* <a href="https://docs.pmd-code.org/apidocs/pmd-javascript/6.30.0/net/sourceforge/pmd/lang/ecmascript/Ecmascript3Handler.html#"><code>net.sourceforge.pmd.lang.ecmascript.Ecmascript3Handler</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-javascript/6.30.0/net/sourceforge/pmd/lang/ecmascript/Ecmascript3Parser.html#"><code>net.sourceforge.pmd.lang.ecmascript.Ecmascript3Parser</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-javascript/6.30.0/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParser.html#parserOptions"><code>EcmascriptParser#parserOptions</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-javascript/6.30.0/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParser.html#getSuppressMap()"><code>EcmascriptParser#getSuppressMap</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/lang/rule/ParametricRuleViolation.html#"><code>net.sourceforge.pmd.lang.rule.ParametricRuleViolation</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.30.0/net/sourceforge/pmd/lang/ParserOptions.html#suppressMarker"><code>ParserOptions#suppressMarker</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-modelica/6.30.0/net/sourceforge/pmd/lang/modelica/rule/ModelicaRuleViolationFactory.html#"><code>net.sourceforge.pmd.lang.modelica.rule.ModelicaRuleViolationFactory</code></a>
### External Contributions
* [#2864](https://github.com/pmd/pmd/pull/2864): [vf] Provide expression type information to Visualforce rules to avoid false positives - [Jeff Bartolotta](https://github.com/jbartolotta-sfdc)
* [#2914](https://github.com/pmd/pmd/pull/2914): \[core] Include rule name in text renderer - [Gunther Schrijvers](https://github.com/GuntherSchrijvers)
* [#2925](https://github.com/pmd/pmd/pull/2925): Cleanup: Correct annotation array initializer indents from checkstyle #8083 - [Abhishek Kumar](https://github.com/Abhishek-kumar09)
* [#2929](https://github.com/pmd/pmd/pull/2929): \[scala] Add support for CPD-ON and CPD-OFF special comments - [Andy Robinson](https://github.com/andyrobinson)
* [#2936](https://github.com/pmd/pmd/pull/2936): \[java] (doc) Fix typo: "an accessor" not "a" - [Igor Moreno](https://github.com/igormoreno)
* [#2938](https://github.com/pmd/pmd/pull/2938): \[cs] CPD: fix issue where ignoring using directives could not be disabled - [Maikel Steneker](https://github.com/maikelsteneker)
* [#2945](https://github.com/pmd/pmd/pull/2945): \[cs] Add option to ignore sequences of literals - [Maikel Steneker](https://github.com/maikelsteneker)
* [#2962](https://github.com/pmd/pmd/pull/2962): \[cpp] Add support for C++ 14 binary literals - [Maikel Steneker](https://github.com/maikelsteneker)
### Stats
* 190 commits
* 25 closed tickets & PRs
* Days since last release: 49
## 24-October-2020 - 6.29.0
The PMD team is pleased to announce PMD 6.29.0.
+1 -1
View File
@@ -8,7 +8,7 @@
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>6.30.0-SNAPSHOT</version>
<version>6.31.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
+1 -1
View File
@@ -7,7 +7,7 @@
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>6.30.0-SNAPSHOT</version>
<version>6.31.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
@@ -14,16 +14,15 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.SystemErrRule;
import net.sourceforge.pmd.RulePriority;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.RuleSetFactory;
import net.sourceforge.pmd.RulesetsFactoryUtils;
import net.sourceforge.pmd.RuleSetLoader;
public class DefaultRulesetTest {
@Rule
public final SystemErrRule systemErrRule = new SystemErrRule().enableLog().muteForSuccessfulTests();
private RuleSetFactory factory = RulesetsFactoryUtils.createFactory(RulePriority.LOW, true, false);
private RuleSetFactory factory = new RuleSetLoader().enableCompatibility(false).toFactory();
@Test
public void loadDefaultRuleset() throws Exception {
+1 -1
View File
@@ -7,7 +7,7 @@
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>6.30.0-SNAPSHOT</version>
<version>6.31.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
@@ -11,16 +11,18 @@ import java.io.Writer;
import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.benchmark.TextTimingReportRenderer;
import net.sourceforge.pmd.benchmark.TimeTracker;
import net.sourceforge.pmd.benchmark.TimedOperation;
@@ -41,11 +43,9 @@ import net.sourceforge.pmd.processor.AbstractPMDProcessor;
import net.sourceforge.pmd.processor.MonoThreadProcessor;
import net.sourceforge.pmd.processor.MultiThreadProcessor;
import net.sourceforge.pmd.renderers.Renderer;
import net.sourceforge.pmd.stat.Metric;
import net.sourceforge.pmd.util.ClasspathClassLoader;
import net.sourceforge.pmd.util.FileUtil;
import net.sourceforge.pmd.util.IOUtil;
import net.sourceforge.pmd.util.ResourceLoader;
import net.sourceforge.pmd.util.database.DBMSMetadata;
import net.sourceforge.pmd.util.database.DBURI;
import net.sourceforge.pmd.util.database.SourceObject;
@@ -89,7 +89,10 @@ public class PMD {
/**
* Create a PMD instance using a default Configuration. Changes to the
* configuration may be required.
*
* @deprecated Just use the static methods, and maintain your {@link PMDConfiguration} separately.
*/
@Deprecated
public PMD() {
this(new PMDConfiguration());
}
@@ -97,9 +100,11 @@ public class PMD {
/**
* Create a PMD instance using the specified Configuration.
*
* @param configuration
* The runtime Configuration of PMD to use.
* @param configuration The runtime Configuration of PMD to use.
*
* @deprecated Just use the static methods, and maintain your {@link PMDConfiguration} separately.
*/
@Deprecated
public PMD(PMDConfiguration configuration) {
this.configuration = configuration;
this.rulesetsFileProcessor = new SourceCodeProcessor(configuration);
@@ -115,7 +120,10 @@ public class PMD {
* @throws PMDException
* if the URI couldn't be parsed
* @see DBURI
*
* @deprecated Will be hidden as part of the parsing of {@link PMD#getApplicableFiles(PMDConfiguration, Set)}
*/
@Deprecated
public static List<DataSource> getURIDataSources(String uriString) throws PMDException {
List<DataSource> dataSources = new ArrayList<>();
@@ -161,7 +169,11 @@ public class PMD {
* @param configuration
* the given configuration
* @return the pre-configured parser
*
* @deprecated This is internal
*/
@Deprecated
@InternalApi
public static Parser parserFor(LanguageVersion languageVersion, PMDConfiguration configuration) {
// TODO Handle Rules having different parser options.
@@ -179,7 +191,10 @@ public class PMD {
*
* @return The configuration.
* @see PMDConfiguration
*
* @deprecated Don't create a PMD instance just to create a {@link PMDConfiguration}
*/
@Deprecated
public PMDConfiguration getConfiguration() {
return configuration;
}
@@ -188,7 +203,9 @@ public class PMD {
* Gets the source code processor.
*
* @return SourceCodeProcessor
* @deprecated Source code processor is internal
*/
@Deprecated
public SourceCodeProcessor getSourceCodeProcessor() {
return rulesetsFileProcessor;
}
@@ -203,7 +220,7 @@ public class PMD {
public static int doPMD(PMDConfiguration configuration) {
// Load the RuleSets
final RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.getRulesetFactory(configuration, new ResourceLoader());
final RuleSetFactory ruleSetFactory = RuleSetLoader.fromPmdConfig(configuration).toFactory();
final RuleSets ruleSets = RulesetsFactoryUtils.getRuleSetsWithBenchmark(configuration.getRuleSets(), ruleSetFactory);
if (ruleSets == null) {
return PMDCommandLineInterface.NO_ERRORS_STATUS;
@@ -221,28 +238,15 @@ public class PMD {
renderer.start();
}
RuleContext ctx = new RuleContext();
final AtomicInteger violations = new AtomicInteger(0);
ctx.getReport().addListener(new ThreadSafeReportListener() {
@Override
public void ruleViolationAdded(RuleViolation ruleViolation) {
violations.getAndIncrement();
}
@Override
public void metricAdded(Metric metric) {
// ignored - not needed for counting violations
}
});
Report report;
try (TimedOperation to = TimeTracker.startOperation(TimedOperationCategory.FILE_PROCESSING)) {
processFiles(configuration, ruleSetFactory, files, ctx, renderers);
report = processFiles(configuration, Arrays.asList(ruleSets.getAllRuleSets()), files, renderers);
}
try (TimedOperation rto = TimeTracker.startOperation(TimedOperationCategory.REPORTING)) {
renderer.end();
renderer.flush();
return violations.get();
return report.getViolations().size();
}
} catch (Exception e) {
String message = e.getMessage();
@@ -274,7 +278,10 @@ public class PMD {
* @param sourceCodeFile
* the source code file
* @return the rule context
*
* @deprecated Not useful
*/
@Deprecated
public static RuleContext newRuleContext(String sourceCodeFilename, File sourceCodeFile) {
RuleContext context = new RuleContext();
@@ -297,19 +304,60 @@ public class PMD {
* RuleContext
* @param renderers
* List of {@link Renderer}s
*
* @deprecated Use {@link #processFiles(PMDConfiguration, List, Collection, List)}
* so as not to depend on {@link RuleSetFactory}. Note that this sorts the list of data sources in-place,
* which won't be fixed
*/
@Deprecated
public static void processFiles(final PMDConfiguration configuration, final RuleSetFactory ruleSetFactory,
final List<DataSource> files, final RuleContext ctx, final List<Renderer> renderers) {
// Note that this duplicates the other routine, because the old behavior was
// that we parsed rulesets (a second time) inside the processor execution.
// To not mess up error handling, we keep this behavior.
encourageToUseIncrementalAnalysis(configuration);
sortFiles(configuration, files);
// Make sure the cache is listening for analysis results
ctx.getReport().addListener(configuration.getAnalysisCache());
final RuleSetFactory silentFactory = new RuleSetFactory(ruleSetFactory, false);
final RuleSetFactory silentFactory = ruleSetFactory.toLoader().warnDeprecated(false).toFactory();
newFileProcessor(configuration).processFiles(silentFactory, files, ctx, renderers);
configuration.getAnalysisCache().persist();
}
/**
* Run PMD using the given configuration. This replaces the other overload.
*
* @param configuration Configuration for the run. Note that the files,
* and rulesets, are ignored, as they are supplied
* as parameters
* @param rulesets Parsed rulesets
* @param files Files to process, will be closed by this method.
* @param renderers Renderers that render the report
*
* @return Report in which violations are accumulated
*
* @throws RuntimeException If processing fails
*/
public static Report processFiles(final PMDConfiguration configuration,
final List<RuleSet> rulesets,
final Collection<? extends DataSource> files,
final List<Renderer> renderers) {
encourageToUseIncrementalAnalysis(configuration);
Report report = new Report();
report.addListener(configuration.getAnalysisCache());
List<DataSource> sortedFiles = new ArrayList<>(files);
sortFiles(configuration, sortedFiles);
RuleContext ctx = new RuleContext();
ctx.setReport(report);
newFileProcessor(configuration).processFiles(new RuleSets(rulesets), sortedFiles, ctx, renderers);
configuration.getAnalysisCache().persist();
return report;
}
private static void sortFiles(final PMDConfiguration configuration, final List<DataSource> files) {
if (configuration.isStressTest()) {
// randomize processing order
@@ -442,7 +490,7 @@ public class PMD {
}
/**
* Entry to invoke PMD as command line tool
* Entry to invoke PMD as command line tool. Note that this will invoke {@link System#exit(int)}.
*
* @param args
* command line arguments
@@ -452,7 +500,8 @@ public class PMD {
}
/**
* Parses the command line arguments and executes PMD.
* Parses the command line arguments and executes PMD. Returns the
* exit code without exiting the VM.
*
* @param args
* command line arguments
@@ -13,6 +13,7 @@ package net.sourceforge.pmd;
* @version $Revision$, $Date$
* @since August 30, 2002
*/
@Deprecated
public class PMDException extends Exception {
private static final long serialVersionUID = 6938647389367956874L;
@@ -47,6 +47,7 @@ public class Report implements Iterable<RuleViolation> {
private final List<ThreadSafeReportListener> listeners = new ArrayList<>();
private final List<ProcessingError> errors = new ArrayList<>();
private final List<ConfigurationError> configErrors = new ArrayList<>();
private final Object lock = new Object();
private Map<Integer, String> linesToSuppress = new HashMap<>();
private long start;
private long end;
@@ -394,11 +395,15 @@ public class Report implements Iterable<RuleViolation> {
* summary over all violations is needed as PMD creates one report per file
* by default.
*
* @param r
* the report to be merged into this.
* <p>This is synchronized on an internal lock (note that other mutation
* operations are not synchronized, todo for pmd 7).
*
* @param r the report to be merged into this.
*
* @see AbstractAccumulatingRenderer
*/
public void merge(Report r) {
synchronized (lock) {
errors.addAll(r.errors);
configErrors.addAll(r.configErrors);
metrics.addAll(r.metrics);
@@ -410,6 +415,7 @@ public class Report implements Iterable<RuleViolation> {
violationTree.addRuleViolation(violation);
}
}
}
/**
* Check whether any metrics have been reported
@@ -28,6 +28,7 @@ import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.rule.RuleReference;
import net.sourceforge.pmd.lang.rule.XPathRule;
import net.sourceforge.pmd.util.filter.Filter;
import net.sourceforge.pmd.util.filter.Filters;
@@ -100,6 +101,89 @@ public class RuleSet implements ChecksumAware {
filter = rs.filter; // filters are immutable, can be shared
}
/**
* Creates a new ruleset containing a single rule. The ruleset will
* have default description, name, and null file name.
*
* @param rule The rule being created
*
* @return The newly created RuleSet
*/
public static RuleSet forSingleRule(final Rule rule) {
final long checksum;
if (rule instanceof XPathRule) {
checksum = ((XPathRule) rule).getXPathExpression().hashCode();
} else {
// TODO : Is this good enough? all properties' values + rule name
checksum = rule.getPropertiesByPropertyDescriptor().values().hashCode() * 31 + rule.getName().hashCode();
}
final RuleSetBuilder builder =
new RuleSetBuilder(checksum)
.withName(rule.getName())
.withDescription("RuleSet for " + rule.getName());
builder.addRule(rule);
return builder.build();
}
/**
* Creates a new ruleset with the given metadata such as name, description,
* fileName, exclude/include patterns are used. The rules are taken from the given
* collection.
*
* <p><strong>Note:</strong> The rule instances are shared between the collection
* and the new ruleset (copy-by-reference). This might lead to concurrency issues,
* if the rules of the collection are also referenced by other rulesets and used
* in different threads.
* </p>
*
* @param name the name of the ruleset
* @param description the description
* @param fileName the filename
* @param excludePatterns list of exclude patterns
* @param includePatterns list of include patterns, that override the exclude patterns
* @param rules the collection with the rules to add to the new ruleset
*
* @return the new ruleset
*
* @throws NullPointerException If any parameter is null, or the collections contain null elements
*/
public static RuleSet create(String name,
String description,
String fileName,
Collection<Pattern> excludePatterns,
Collection<Pattern> includePatterns,
Iterable<? extends Rule> rules) {
RuleSetBuilder builder = new RuleSetBuilder(0L); // TODO: checksum missing
builder.withName(name)
.withDescription(description)
.withFileName(fileName)
.replaceFileExclusions(excludePatterns)
.replaceFileInclusions(includePatterns);
for (Rule rule : rules) {
builder.addRule(rule);
}
return builder.build();
}
/**
* Creates a copy of the given ruleset. All properties like name, description, fileName
* and exclude/include patterns are copied.
*
* <p><strong>Note:</strong> The rule instances are shared between the original
* and the new ruleset (copy-by-reference). This might lead to concurrency issues,
* if the original ruleset and the new ruleset are used in different threads.
* </p>
*
* @param original the original rule set to copy from
*
* @return the copy
*/
public static RuleSet copy(RuleSet original) {
return new RuleSet(original);
}
/* package */ static class RuleSetBuilder {
public String description;
@@ -13,7 +13,6 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -34,22 +33,20 @@ import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import net.sourceforge.pmd.RuleSet.RuleSetBuilder;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.rule.MockRule;
import net.sourceforge.pmd.lang.rule.RuleReference;
import net.sourceforge.pmd.lang.rule.XPathRule;
import net.sourceforge.pmd.rules.RuleFactory;
import net.sourceforge.pmd.util.ResourceLoader;
/**
* RuleSetFactory is responsible for creating RuleSet instances from XML
* content. By default Rules will be loaded using the {@link RulePriority#LOW} priority,
* with Rule deprecation warnings off;
* the ruleset compatibility filter is active, too (see {@link RuleSetFactoryCompatibility});
* if the ruleset contains rule references (e.g. for renamed or moved rules), these
* are ignored by default.
* content. See {@link RuleSetLoader} for configuration options and
* their defaults.
*
* @deprecated Use a {@link RuleSetLoader} instead. This will be hidden in PMD 7
* (it's the implementation, while {@link RuleSetLoader} is the API).
*/
@Deprecated
public class RuleSetFactory {
private static final Logger LOG = Logger.getLogger(RuleSetFactory.class.getName());
@@ -67,7 +64,7 @@ public class RuleSetFactory {
private final Map<RuleSetReferenceId, RuleSet> parsedRulesets = new HashMap<>();
/**
* @deprecated Use {@link RulesetsFactoryUtils#defaultFactory()}
* @deprecated Use a {@link RuleSetLoader} to build a new factory
*/
@Deprecated // to be removed with PMD 7.0.0.
public RuleSetFactory() {
@@ -75,8 +72,7 @@ public class RuleSetFactory {
}
/**
* @deprecated Use {@link RulesetsFactoryUtils#createFactory(ClassLoader, RulePriority, boolean, boolean)}
* or {@link RulesetsFactoryUtils#createFactory(RulePriority, boolean, boolean)}
* @deprecated Use a {@link RuleSetLoader} to build a new factory
*/
@Deprecated // to be removed with PMD 7.0.0.
public RuleSetFactory(final ClassLoader classLoader, final RulePriority minimumPriority,
@@ -85,8 +81,7 @@ public class RuleSetFactory {
}
/**
* @deprecated Use {@link RulesetsFactoryUtils#createFactory(ClassLoader, RulePriority, boolean, boolean)}
* or {@link RulesetsFactoryUtils#createFactory(RulePriority, boolean, boolean)}
* @deprecated Use a {@link RuleSetLoader} to build a new factory
*/
@Deprecated // to be hidden with PMD 7.0.0.
public RuleSetFactory(final ResourceLoader resourceLoader, final RulePriority minimumPriority,
@@ -111,16 +106,18 @@ public class RuleSetFactory {
/**
* Constructor copying all configuration from another factory.
*
* @param factory
* The factory whose configuration to copy.
* @param warnDeprecated
* Whether deprecation warnings are to be produced by this
* factory.
* @param factory The factory whose configuration to copy.
* @param warnDeprecated Whether deprecation warnings are to be produced by this
* factory
*
* @deprecated Use {@link #toLoader()} to rebuild a factory from a configuration
*/
@Deprecated
public RuleSetFactory(final RuleSetFactory factory, final boolean warnDeprecated) {
this(factory.resourceLoader, factory.minimumPriority, warnDeprecated, factory.compatibilityFilter != null);
}
/**
* Gets the compatibility filter in order to adjust it, e.g. add additional
* filters.
@@ -138,28 +135,12 @@ public class RuleSetFactory {
* @return An Iterator of RuleSet objects.
*
* @throws RuleSetNotFoundException if the ruleset file could not be found
*
* @deprecated Use {@link RuleSetLoader#getStandardRuleSets()}
*/
@Deprecated
public Iterator<RuleSet> getRegisteredRuleSets() throws RuleSetNotFoundException {
String rulesetsProperties = null;
List<RuleSetReferenceId> ruleSetReferenceIds = new ArrayList<>();
for (Language language : LanguageRegistry.findWithRuleSupport()) {
Properties props = new Properties();
rulesetsProperties = "category/" + language.getTerseName() + "/categories.properties";
try (InputStream inputStream = resourceLoader.loadClassPathResourceAsStreamOrThrow(rulesetsProperties)) {
props.load(inputStream);
String rulesetFilenames = props.getProperty("rulesets.filenames");
if (rulesetFilenames != null) {
ruleSetReferenceIds.addAll(RuleSetReferenceId.parse(rulesetFilenames));
}
} catch (RuleSetNotFoundException e) {
LOG.warning("The language " + language.getTerseName() + " provides no " + rulesetsProperties + ".");
} catch (IOException ioe) {
throw new RuntimeException("Couldn't find " + rulesetsProperties
+ "; please ensure that the directory is on the classpath. The current classpath is: "
+ System.getProperty("java.class.path"));
}
}
return createRuleSets(ruleSetReferenceIds).getRuleSetsIterator();
return toLoader().getStandardRuleSets().iterator();
}
/**
@@ -174,7 +155,11 @@ public class RuleSetFactory {
* @return The new RuleSets.
* @throws RuleSetNotFoundException
* if unable to find a resource.
*
* @deprecated Use {@link RuleSetLoader#loadFromResource(String)},
* but note that that method does not split on commas
*/
@Deprecated
public RuleSets createRuleSets(String referenceString) throws RuleSetNotFoundException {
return createRuleSets(RuleSetReferenceId.parse(referenceString));
}
@@ -188,7 +173,10 @@ public class RuleSetFactory {
* @return The new RuleSets.
* @throws RuleSetNotFoundException
* if unable to find a resource.
*
* @deprecated Will not be replaced
*/
@Deprecated
public RuleSets createRuleSets(List<RuleSetReferenceId> ruleSetReferenceIds) throws RuleSetNotFoundException {
RuleSets ruleSets = new RuleSets();
for (RuleSetReferenceId ruleSetReferenceId : ruleSetReferenceIds) {
@@ -210,7 +198,10 @@ public class RuleSetFactory {
* @return A new RuleSet.
* @throws RuleSetNotFoundException
* if unable to find a resource.
*
* @deprecated Use {@link RuleSetLoader#loadFromResource(String)} and discard the rest of the list.
*/
@Deprecated
public RuleSet createRuleSet(String referenceString) throws RuleSetNotFoundException {
List<RuleSetReferenceId> references = RuleSetReferenceId.parse(referenceString);
if (references.isEmpty()) {
@@ -229,7 +220,10 @@ public class RuleSetFactory {
* @return A new RuleSet.
* @throws RuleSetNotFoundException
* if unable to find a resource.
*
* @deprecated Will not be replaced
*/
@Deprecated
public RuleSet createRuleSet(RuleSetReferenceId ruleSetReferenceId) throws RuleSetNotFoundException {
return createRuleSet(ruleSetReferenceId, includeDeprecatedRuleReferences);
}
@@ -250,7 +244,10 @@ public class RuleSetFactory {
*
* @param original the original rule set to copy from
* @return the copy
*
* @deprecated Use {@link RuleSet#copy(RuleSet)}
*/
@Deprecated
public RuleSet createRuleSetCopy(RuleSet original) {
RuleSetBuilder builder = new RuleSetBuilder(original);
return builder.build();
@@ -274,23 +271,17 @@ public class RuleSetFactory {
* @param includePatterns list of include patterns, if any is not a valid regular expression, it will be ignored
* @param rules the collection with the rules to add to the new ruleset
* @return the new ruleset
*
* @deprecated Use {@link RuleSet#create(String, String, String, Collection, Collection, Iterable)}
*/
@Deprecated
public RuleSet createNewRuleSet(String name,
String description,
String fileName,
Collection<String> excludePatterns,
Collection<String> includePatterns,
Collection<Rule> rules) {
RuleSetBuilder builder = new RuleSetBuilder(0L); // TODO: checksum missing
builder.withName(name)
.withDescription(description)
.withFileName(fileName)
.replaceFileExclusions(toPatterns(excludePatterns))
.replaceFileInclusions(toPatterns(includePatterns));
for (Rule rule : rules) {
builder.addRule(rule);
}
return builder.build();
return RuleSet.create(name, description, fileName, toPatterns(excludePatterns), toPatterns(includePatterns), rules);
}
private Collection<Pattern> toPatterns(Collection<String> sources) {
@@ -308,24 +299,15 @@ public class RuleSetFactory {
/**
* Creates a new RuleSet containing a single rule.
*
* @param rule
* The rule being created
* @param rule The rule being created
*
* @return The newly created RuleSet
*
* @deprecated Use {@link RuleSet#forSingleRule(Rule)}
*/
public RuleSet createSingleRuleRuleSet(final Rule rule) { // TODO make static?
final long checksum;
if (rule instanceof XPathRule) {
checksum = ((XPathRule) rule).getXPathExpression().hashCode();
} else {
// TODO : Is this good enough? all properties' values + rule name
checksum = rule.getPropertiesByPropertyDescriptor().values().hashCode() * 31 + rule.getName().hashCode();
}
final RuleSetBuilder builder = new RuleSetBuilder(checksum)
.withName(rule.getName())
.withDescription("RuleSet for " + rule.getName());
builder.addRule(rule);
return builder.build();
@Deprecated
public RuleSet createSingleRuleRuleSet(final Rule rule) {
return RuleSet.forSingleRule(rule);
}
/**
@@ -348,7 +330,8 @@ public class RuleSetFactory {
private Rule createRule(RuleSetReferenceId ruleSetReferenceId, boolean withDeprecatedRuleReferences)
throws RuleSetNotFoundException {
if (ruleSetReferenceId.isAllRules()) {
throw new IllegalArgumentException("Cannot parse a single Rule from an all Rule RuleSet reference: <" + ruleSetReferenceId + ">.");
throw new IllegalArgumentException(
"Cannot parse a single Rule from an all Rule RuleSet reference: <" + ruleSetReferenceId + ">.");
}
RuleSet ruleSet;
// java8: computeIfAbsent
@@ -438,9 +421,6 @@ public class RuleSetFactory {
ruleSetBuilder.filterRulesByPriority(minimumPriority);
return ruleSetBuilder.build();
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
throw new RuntimeException("Couldn't find the class " + ex.getMessage(), ex);
} catch (ParserConfigurationException | IOException | SAXException ex) {
ex.printStackTrace();
throw new RuntimeException("Couldn't read the ruleset " + ruleSetReferenceId + ": " + ex.getMessage(), ex);
@@ -512,7 +492,7 @@ public class RuleSetFactory {
*/
private void parseRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSetBuilder ruleSetBuilder, Node ruleNode,
boolean withDeprecatedRuleReferences, Set<String> rulesetReferences)
throws ClassNotFoundException, InstantiationException, IllegalAccessException, RuleSetNotFoundException {
throws RuleSetNotFoundException {
Element ruleElement = (Element) ruleNode;
String ref = ruleElement.getAttribute("ref");
if (ref.endsWith("xml")) {
@@ -557,7 +537,7 @@ public class RuleSetFactory {
// load the ruleset with minimum priority low, so that we get all rules, to be able to exclude any rule
// minimum priority will be applied again, before constructing the final ruleset
RuleSetFactory ruleSetFactory = new RuleSetFactory(resourceLoader, RulePriority.LOW, false, this.compatibilityFilter != null);
RuleSetFactory ruleSetFactory = toLoader().filterAbovePriority(RulePriority.LOW).warnDeprecated(false).toFactory();
RuleSet otherRuleSet = ruleSetFactory.createRuleSet(RuleSetReferenceId.parse(ref).get(0));
List<RuleReference> potentialRules = new ArrayList<>();
int countDeprecated = 0;
@@ -620,7 +600,7 @@ public class RuleSetFactory {
* Must be a rule element node.
*/
private void parseSingleRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSetBuilder ruleSetBuilder,
Node ruleNode) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Node ruleNode) {
Element ruleElement = (Element) ruleNode;
// Stop if we're looking for a particular Rule, and this element is not
@@ -672,7 +652,7 @@ public class RuleSetFactory {
// load the ruleset with minimum priority low, so that we get all rules, to be able to exclude any rule
// minimum priority will be applied again, before constructing the final ruleset
RuleSetFactory ruleSetFactory = new RuleSetFactory(resourceLoader, RulePriority.LOW, false, this.compatibilityFilter != null);
RuleSetFactory ruleSetFactory = toLoader().filterAbovePriority(RulePriority.LOW).warnDeprecated(false).toFactory();
boolean isSameRuleSet = false;
RuleSetReferenceId otherRuleSetReferenceId = RuleSetReferenceId.parse(ref).get(0);
@@ -832,4 +812,19 @@ public class RuleSetFactory {
return false;
}
}
/**
* Create a new {@link RuleSetLoader} with the same config as this
* factory. This is a transitional API.
*/
public RuleSetLoader toLoader() {
return new RuleSetLoader().loadResourcesWith(resourceLoader)
.filterAbovePriority(minimumPriority)
.warnDeprecated(warnDeprecated)
.enableCompatibility(compatibilityFilter != null)
.includeDeprecatedRuleReferences(includeDeprecatedRuleReferences);
}
}
@@ -18,13 +18,20 @@ import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
import net.sourceforge.pmd.annotation.InternalApi;
/**
* Provides a simple filter mechanism to avoid failing to parse an old ruleset,
* which references rules, that have either been removed from PMD already or
* renamed or moved to another ruleset.
*
* @see <a href="https://sourceforge.net/p/pmd/bugs/1360/">issue 1360</a>
*
* @deprecated Use {@link RuleSetLoader#enableCompatibility(boolean)} to enable this feature.
* This implementation is internal API.
*/
@InternalApi
@Deprecated
public class RuleSetFactoryCompatibility {
private static final Logger LOG = Logger.getLogger(RuleSetFactoryCompatibility.class.getName());
@@ -0,0 +1,32 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd;
import net.sourceforge.pmd.annotation.InternalApi;
/**
* An exception that is thrown when something wrong occurs while
* {@linkplain RuleSetLoader loading rulesets}. This may be because the
* XML is not well-formed, does not respect the ruleset schema, is
* not a valid ruleset or is otherwise unparsable.
*
* <p>In the new {@link RuleSetLoader} API, this is thrown instead of
* {@link RuleSetNotFoundException}.
*/
public final class RuleSetLoadException extends RuntimeException {
/** Constructors are internal. */
@InternalApi
public RuleSetLoadException(String message, Throwable cause) {
super(message, cause);
}
/** Constructors are internal. */
@InternalApi
public RuleSetLoadException(String message) {
super(message);
}
}
@@ -0,0 +1,230 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.util.CollectionUtil;
import net.sourceforge.pmd.util.ResourceLoader;
/**
* Configurable object to load rulesets from XML resources.
* This can be configured using a fluent API, see eg {@link #warnDeprecated(boolean)}.
* To create a new ruleset, use {@link #loadFromResource(String)}
* or some such overload.
*/
public final class RuleSetLoader {
private static final Logger LOG = Logger.getLogger(RuleSetLoader.class.getName());
private ResourceLoader resourceLoader = new ResourceLoader(RuleSetLoader.class.getClassLoader());
private RulePriority minimumPriority = RulePriority.LOW;
private boolean warnDeprecated = true;
private boolean enableCompatibility = true;
private boolean includeDeprecatedRuleReferences = false;
/**
* Specify that the given classloader should be used to resolve
* paths to external ruleset references. The default uses PMD's
* own classpath.
*/
public RuleSetLoader loadResourcesWith(ClassLoader classLoader) {
this.resourceLoader = new ResourceLoader(classLoader);
return this;
}
// internal
RuleSetLoader loadResourcesWith(ResourceLoader loader) {
this.resourceLoader = loader;
return this;
}
/**
* Filter loaded rules to only those that match or are above
* the given priority. The default is {@link RulePriority#LOW},
* ie, no filtering occurs.
*
* @return This instance, modified
*/
public RuleSetLoader filterAbovePriority(RulePriority minimumPriority) {
this.minimumPriority = minimumPriority;
return this;
}
/**
* Log a warning when referencing a deprecated rule.
* This is enabled by default.
*
* @return This instance, modified
*/
public RuleSetLoader warnDeprecated(boolean warn) {
this.warnDeprecated = warn;
return this;
}
/**
* Enable translating old rule references to newer ones, if they have
* been moved or renamed. This is enabled by default, if disabled,
* unresolved references will not be translated and will produce an
* error.
*
* @return This instance, modified
*/
public RuleSetLoader enableCompatibility(boolean enable) {
this.enableCompatibility = enable;
return this;
}
/**
* Follow deprecated rule references. By default this is off,
* and those references will be ignored (with a warning depending
* on {@link #enableCompatibility(boolean)}).
*
* @return This instance, modified
*/
public RuleSetLoader includeDeprecatedRuleReferences(boolean enable) {
this.includeDeprecatedRuleReferences = enable;
return this;
}
/**
* Create a new rule set factory, if you have to (that class is deprecated).
* That factory will use the configuration that was set using the setters of this.
*
* @deprecated {@link RuleSetFactory} is deprecated, replace its usages
* with usages of this class, or of static factory methods of {@link RuleSet}
*/
@Deprecated
public RuleSetFactory toFactory() {
return new RuleSetFactory(
this.resourceLoader,
this.minimumPriority,
this.warnDeprecated,
this.enableCompatibility,
this.includeDeprecatedRuleReferences
);
}
/**
* Parses and returns a ruleset from its location. The location may
* be a file system path, or a resource path (see {@link #loadResourcesWith(ClassLoader)}).
*
* <p>This replaces {@link RuleSetFactory#createRuleSet(String)},
* but does not split commas.
*
* @param rulesetPath A reference to a single ruleset
*
* @throws RuleSetLoadException If any error occurs (eg, invalid syntax, or resource not found)
*/
public RuleSet loadFromResource(String rulesetPath) {
return loadFromResource(new RuleSetReferenceId(rulesetPath));
}
/**
* Parses several resources into a list of rulesets.
*
* @param paths Paths
*
* @throws RuleSetLoadException If any error occurs (eg, invalid syntax, or resource not found),
* for any of the parameters
* @throws NullPointerException If the parameter, or any component is null
*/
public List<RuleSet> loadFromResources(Collection<String> paths) {
List<RuleSet> ruleSets = new ArrayList<>(paths.size());
for (String path : paths) {
ruleSets.add(loadFromResource(path));
}
return ruleSets;
}
/**
* Parses several resources into a list of rulesets.
*
* @param first First path
* @param rest Paths
*
* @throws RuleSetLoadException If any error occurs (eg, invalid syntax, or resource not found),
* for any of the parameters
* @throws NullPointerException If the parameter, or any component is null
*/
public List<RuleSet> loadFromResources(String first, String... rest) {
return loadFromResources(CollectionUtil.listOf(first, rest));
}
// package private
RuleSet loadFromResource(RuleSetReferenceId ruleSetReferenceId) {
try {
return toFactory().createRuleSet(ruleSetReferenceId);
} catch (Exception e) {
throw new RuleSetLoadException("Cannot parse " + ruleSetReferenceId, e);
}
}
/**
* Configure a new ruleset factory builder according to the parameters
* of the given PMD configuration.
*/
public static RuleSetLoader fromPmdConfig(PMDConfiguration configuration) {
return new RuleSetLoader().filterAbovePriority(configuration.getMinimumPriority())
.enableCompatibility(configuration.isRuleSetFactoryCompatibilityEnabled());
}
/**
* Returns an Iterator of RuleSet objects loaded from descriptions from the
* "categories.properties" resource for each language. This
* uses the classpath of the resource loader ({@link #loadResourcesWith(ClassLoader)}).
*
* @return A list of all category rulesets
*
* @throws RuleSetLoadException If a standard ruleset cannot be loaded.
* This is a corner case, that probably should not be caught by clients.
* The standard rulesets are well-formed, at least in stock PMD distributions.
*
*/
public List<RuleSet> getStandardRuleSets() {
String rulesetsProperties;
List<RuleSetReferenceId> ruleSetReferenceIds = new ArrayList<>();
for (Language language : LanguageRegistry.findWithRuleSupport()) {
Properties props = new Properties();
rulesetsProperties = "category/" + language.getTerseName() + "/categories.properties";
try (InputStream inputStream = resourceLoader.loadClassPathResourceAsStreamOrThrow(rulesetsProperties)) {
props.load(inputStream);
String rulesetFilenames = props.getProperty("rulesets.filenames");
if (rulesetFilenames != null) {
ruleSetReferenceIds.addAll(RuleSetReferenceId.parse(rulesetFilenames));
}
} catch (RuleSetNotFoundException e) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("The language " + language.getTerseName() + " provides no " + rulesetsProperties + ".");
}
} catch (IOException ioe) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("Couldn't read " + rulesetsProperties
+ "; please ensure that the directory is on the classpath. The current classpath is: "
+ System.getProperty("java.class.path"));
LOG.fine(ioe.toString());
}
}
}
List<RuleSet> ruleSets = new ArrayList<>();
for (RuleSetReferenceId id : ruleSetReferenceIds) {
ruleSets.add(loadFromResource(id)); // may throw
}
return ruleSets;
}
}
@@ -4,10 +4,20 @@
package net.sourceforge.pmd;
/**
* @deprecated This is now only thrown by deprecated apis. {@link RuleSetLoader}
* throws {@link RuleSetLoadException} instead
*/
@Deprecated
public class RuleSetNotFoundException extends Exception {
private static final long serialVersionUID = -4617033110919250810L;
public RuleSetNotFoundException(String msg) {
super(msg);
}
public RuleSetNotFoundException(String msg, Throwable cause) {
super(msg, cause);
}
}
@@ -8,9 +8,15 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import net.sourceforge.pmd.annotation.InternalApi;
/**
* This class represents a reference to RuleSet.
*
* @deprecated This is part of the internals of the {@link RuleSetLoader}.
*/
@Deprecated
@InternalApi
public class RuleSetReference {
private final String ruleSetFileName;
private final boolean allRules;
@@ -14,6 +14,7 @@ import java.util.List;
import org.apache.commons.lang3.StringUtils;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.util.ResourceLoader;
/**
@@ -78,7 +79,11 @@ import net.sourceforge.pmd.util.ResourceLoader;
* </tr>
* </tbody>
* </table>
*
* @deprecated This is part of the internals of the {@link RuleSetLoader}.
*/
@Deprecated
@InternalApi
public class RuleSetReferenceId {
private final boolean external;
private final String ruleSetFileName;
@@ -56,21 +56,31 @@ public class RuleSets {
/**
* Public constructor. Add the given rule set.
*
* @param ruleSet
* the RuleSet
* @param ruleSet the RuleSet
*/
public RuleSets(RuleSet ruleSet) {
addRuleSet(ruleSet);
}
/**
* Aggregate the given rulesets.
*/
public RuleSets(List<RuleSet> ruleSet) {
for (RuleSet set : ruleSet) {
addRuleSet(set);
}
}
/**
* Add a ruleset for a language. Only one ruleset can be added for a
* specific language. If ruleSet.getLanguage() is null, it is assumed to be
* a RuleSet of java rules.
*
* @param ruleSet
* the RuleSet
* @param ruleSet the RuleSet
*
* @deprecated Use {@link #RuleSets(List)} and don't mutate RuleSets after creation
*/
@Deprecated
public void addRuleSet(RuleSet ruleSet) {
ruleSets.add(ruleSet);
ruleChain.add(ruleSet);
@@ -85,6 +95,11 @@ public class RuleSets {
return ruleSets.toArray(new RuleSet[0]);
}
// internal
List<RuleSet> getRuleSetsInternal() {
return ruleSets;
}
public Iterator<RuleSet> getRuleSetsIterator() {
return ruleSets.iterator();
}
@@ -13,6 +13,10 @@ import net.sourceforge.pmd.benchmark.TimedOperation;
import net.sourceforge.pmd.benchmark.TimedOperationCategory;
import net.sourceforge.pmd.util.ResourceLoader;
/**
* @deprecated Use a {@link RuleSetLoader} instead
*/
@Deprecated
public final class RulesetsFactoryUtils {
private static final Logger LOG = Logger.getLogger(RulesetsFactoryUtils.class.getName());
@@ -76,7 +80,7 @@ public final class RulesetsFactoryUtils {
}
/**
* @deprecated Use {@link #createFactory(PMDConfiguration)} or {@link #createFactory(PMDConfiguration, ClassLoader)}
* @deprecated Use a {@link RuleSetLoader}
*/
@InternalApi
@Deprecated
@@ -96,7 +100,10 @@ public final class RulesetsFactoryUtils {
* @return A ruleset factory
*
* @see #createFactory(PMDConfiguration, ClassLoader)
*
* @deprecated Use {@link RuleSetLoader#fromPmdConfig(PMDConfiguration)}
*/
@Deprecated
public static RuleSetFactory createFactory(final PMDConfiguration configuration) {
return createFactory(configuration, RulesetsFactoryUtils.class.getClassLoader());
}
@@ -107,7 +114,7 @@ public final class RulesetsFactoryUtils {
*
* @return A ruleset factory
*
* @see #createFactory(PMDConfiguration, ClassLoader)
* @see RuleSetLoader
*/
public static RuleSetFactory defaultFactory() {
return new RuleSetFactory();
@@ -124,7 +131,10 @@ public final class RulesetsFactoryUtils {
* @return A ruleset factory
*
* @see #createFactory(PMDConfiguration)
*
* @deprecated Use a {@link RuleSetLoader}
*/
@Deprecated
public static RuleSetFactory createFactory(final PMDConfiguration configuration, ClassLoader classLoader) {
return createFactory(classLoader,
configuration.getMinimumPriority(),
@@ -145,7 +155,10 @@ public final class RulesetsFactoryUtils {
* @return A ruleset factory
*
* @see #createFactory(PMDConfiguration)
*
* @deprecated Use a {@link RuleSetLoader}
*/
@Deprecated
public static RuleSetFactory createFactory(ClassLoader classLoader,
RulePriority minimumPriority,
boolean warnDeprecated,
@@ -166,11 +179,13 @@ public final class RulesetsFactoryUtils {
* @return A ruleset factory
*
* @see #createFactory(PMDConfiguration)
*
* @deprecated Use a {@link RuleSetLoader}
*/
@Deprecated
public static RuleSetFactory createFactory(RulePriority minimumPriority,
boolean warnDeprecated,
boolean enableCompatibility) {
return new RuleSetFactory(new ResourceLoader(), minimumPriority, warnDeprecated, enableCompatibility);
}
@@ -190,7 +205,9 @@ public final class RulesetsFactoryUtils {
* @return A ruleset factory
*
* @see #createFactory(PMDConfiguration)
* @deprecated Use a {@link RuleSetLoader}
*/
@Deprecated
public static RuleSetFactory createFactory(RulePriority minimumPriority,
boolean warnDeprecated,
boolean enableCompatibility,
@@ -11,6 +11,7 @@ import java.io.Reader;
import java.util.Collections;
import java.util.List;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.benchmark.TimeTracker;
import net.sourceforge.pmd.benchmark.TimedOperation;
import net.sourceforge.pmd.benchmark.TimedOperationCategory;
@@ -23,6 +24,11 @@ import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.ast.ParseException;
import net.sourceforge.pmd.lang.xpath.Initializer;
/**
* Source code processor is internal.
*/
@Deprecated
@InternalApi
public class SourceCodeProcessor {
private final PMDConfiguration configuration;

Some files were not shown because too many files have changed in this diff Show More