forked from phoedos/pmd
Merge branch 'master' into designer-breadcrumbbar
This commit is contained in:
@ -1,9 +1,9 @@
|
|||||||
repository: pmd/pmd
|
repository: pmd/pmd
|
||||||
|
|
||||||
pmd:
|
pmd:
|
||||||
version: 6.11.0
|
version: 6.12.0
|
||||||
previous_version: 6.10.0
|
previous_version: 6.11.0
|
||||||
date: ??-January-2019
|
date: ??-February-2019
|
||||||
release_type: minor
|
release_type: minor
|
||||||
|
|
||||||
output: web
|
output: web
|
||||||
|
@ -97,7 +97,7 @@ class JavadocTag < Liquid::Tag
|
|||||||
QNAME_NO_NAMESPACE_REGEX = /((?:\w+\.)*\w+)/
|
QNAME_NO_NAMESPACE_REGEX = /((?:\w+\.)*\w+)/
|
||||||
|
|
||||||
ARG_REGEX = Regexp.new(Regexp.union(JDocNamespaceDeclaration::NAMESPACED_FQCN_REGEX, QNAME_NO_NAMESPACE_REGEX).source + '(\[\])*')
|
ARG_REGEX = Regexp.new(Regexp.union(JDocNamespaceDeclaration::NAMESPACED_FQCN_REGEX, QNAME_NO_NAMESPACE_REGEX).source + '(\[\])*')
|
||||||
ARGUMENTS_REGEX = Regexp.new('\(\)|\((' + ARG_REGEX.source + "(?:," + ARG_REGEX.source + ")*" + ')\)')
|
ARGUMENTS_REGEX = Regexp.new('\(\)|\((' + ARG_REGEX.source + "(?:,(?:" + ARG_REGEX.source + "))*" + ')\)')
|
||||||
|
|
||||||
|
|
||||||
def initialize(tag_name, doc_ref, tokens)
|
def initialize(tag_name, doc_ref, tokens)
|
||||||
|
@ -73,6 +73,16 @@ 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,
|
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." %}
|
we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %}
|
||||||
|
|
||||||
|
#### 6.11.0
|
||||||
|
|
||||||
|
* {% jdoc core::lang.rule.stat.StatisticalRule %} and the related helper classes and base rule classes
|
||||||
|
are deprecated for removal in 7.0.0. This includes all of {% jdoc_package core::stat %} and {% jdoc_package core::lang.rule.stat %},
|
||||||
|
and also {% jdoc java::lang.java.rule.AbstractStatisticalJavaRule %}, {% jdoc apex::lang.apex.rule.AbstractStatisticalApexRule %} and the like.
|
||||||
|
The methods {% jdoc !c!core::Report#addMetric(core::stat.Metric) %} and {% jdoc core::ThreadSafeReportListener#metricAdded(core::stat.Metric) %}
|
||||||
|
will also be removed.
|
||||||
|
* {% jdoc core::properties.PropertySource#setProperty(core::properties.MultiValuePropertyDescriptor, Object[]) %} is deprecated,
|
||||||
|
because {% jdoc core::properties.MultiValuePropertyDescriptor %} is deprecated as well
|
||||||
|
|
||||||
#### 6.10.0
|
#### 6.10.0
|
||||||
|
|
||||||
##### Properties framework
|
##### Properties framework
|
||||||
|
@ -14,98 +14,11 @@ This is a {{ site.pmd.release_type }} release.
|
|||||||
|
|
||||||
### New and noteworthy
|
### New and noteworthy
|
||||||
|
|
||||||
### Updatex Apex Support
|
|
||||||
|
|
||||||
* The Apex language support has been bumped to version 45 (Spring '19). All new language features are now properly
|
|
||||||
parsed and processed.
|
|
||||||
|
|
||||||
#### New Rules
|
|
||||||
|
|
||||||
* The new Java rule {% rule "java/multithreading/UnsynchronizedStaticFormatter" %} (`java-multithreading`) detects
|
|
||||||
unsynchronized usages of static `java.text.Format` instances. This rule is a more generic replacement of the
|
|
||||||
rule {% rule "java/multithreading/UnsynchronizedStaticDateFormatter" %} which focused just on `DateFormat`.
|
|
||||||
|
|
||||||
* The new Java rule {% rule "java/bestpractices/ForLoopVariableCount" %} (`java-bestpractices`) checks for
|
|
||||||
the number of control variables in a for-loop. Having a lot of control variables makes it harder to understand
|
|
||||||
what the loop does. The maximum allowed number of variables is by default 1 and can be configured by a
|
|
||||||
property.
|
|
||||||
|
|
||||||
* The new Java rule {% rule "java/bestpractices/AvoidReassigningLoopVariables" %} (`java-bestpractices`) searches
|
|
||||||
for loop variables that are reassigned. Changing the loop variables additionally to the loop itself can lead to
|
|
||||||
hard-to-find bugs.
|
|
||||||
|
|
||||||
* The new Java rule {% rule "java/codestyle/UseDiamondOperator" %} (`java-codestyle`) looks for constructor
|
|
||||||
calls with explicit type parameters. Since Java 1.7, these type parameters are not necessary anymore, as they
|
|
||||||
can be inferred now.
|
|
||||||
|
|
||||||
#### Modified Rules
|
|
||||||
|
|
||||||
* The Java rule {% rule "java/codestyle/LocalVariableCouldBeFinal" %} (`java-codestyle`) has a new
|
|
||||||
property `ignoreForEachDecl`, which is by default disabled. The new property allows for ignoring
|
|
||||||
non-final loop variables in a for-each statement.
|
|
||||||
|
|
||||||
#### Deprecated Rules
|
|
||||||
|
|
||||||
* The Java rule {% rule "java/multithreading/UnsynchronizedStaticDateFormatter" %} has been deprecated and
|
|
||||||
will be removed with PMD 7.0.0. The rule is replaced by the more general
|
|
||||||
{% rule "java/multithreading/UnsynchronizedStaticFormatter" %}.
|
|
||||||
|
|
||||||
### Fixed Issues
|
### Fixed Issues
|
||||||
|
|
||||||
* all
|
|
||||||
* [#1196](https://github.com/pmd/pmd/issues/1196): \[core] CPD results not consistent between runs
|
|
||||||
* apex
|
|
||||||
* [#1542](https://github.com/pmd/pmd/pull/1542): \[apex] Include the documentation category
|
|
||||||
* [#1546](https://github.com/pmd/pmd/issues/1546): \[apex] PMD parsing exception for Apex classes using 'inherited sharing' keyword
|
|
||||||
* java
|
|
||||||
* [#1556](https://github.com/pmd/pmd/issues/1556): \[java] Default methods should not be considered abstract
|
|
||||||
* [#1578](https://github.com/pmd/pmd/issues/1578): \[java] Private field is detected as public inside nested classes in interfaces
|
|
||||||
* java-bestpractices
|
|
||||||
* [#658](https://github.com/pmd/pmd/issues/658): \[java] OneDeclarationPerLine: False positive for loops
|
|
||||||
* [#1518](https://github.com/pmd/pmd/issues/1518): \[java] New rule: AvoidReassigningLoopVariable
|
|
||||||
* [#1519](https://github.com/pmd/pmd/issues/1519): \[java] New rule: ForLoopVariableCount
|
|
||||||
* java-codestyle
|
|
||||||
* [#1513](https://github.com/pmd/pmd/issues/1513): \[java] LocalVariableCouldBeFinal: allow excluding the variable in a for-each loop
|
|
||||||
* [#1517](https://github.com/pmd/pmd/issues/1517): \[java] New Rule: UseDiamondOperator
|
|
||||||
* java-errorprone
|
|
||||||
* [#1035](https://github.com/pmd/pmd/issues/1035): \[java] ReturnFromFinallyBlock: False positive on lambda expression in finally block
|
|
||||||
* [#1549](https://github.com/pmd/pmd/issues/1549): \[java] NPE in PMD 6.8.0 InvalidSlf4jMessageFormat
|
|
||||||
* java-multithreading
|
|
||||||
* [#1533](https://github.com/pmd/pmd/issues/1533): \[java] New rule: UnsynchronizedStaticFormatter
|
|
||||||
* plsql
|
|
||||||
* [#1507](https://github.com/pmd/pmd/issues/1507): \[plsql] Parse Exception when using '||' operator in where clause
|
|
||||||
* [#1508](https://github.com/pmd/pmd/issues/1508): \[plsql] Parse Exception when using SELECT COUNT(\*)
|
|
||||||
* [#1509](https://github.com/pmd/pmd/issues/1509): \[plsql] Parse Exception with OUTER/INNER Joins
|
|
||||||
* [#1511](https://github.com/pmd/pmd/issues/1511): \[plsql] Parse Exception with IS NOT NULL
|
|
||||||
* [#1583](https://github.com/pmd/pmd/issues/1583): \[plsql] Update Set Clause should allow multiple columns
|
|
||||||
* [#1586](https://github.com/pmd/pmd/issues/1586): \[plsql] Parse Exception when functions are used with LIKE
|
|
||||||
|
|
||||||
### API Changes
|
### API Changes
|
||||||
|
|
||||||
#### Deprecated API
|
|
||||||
|
|
||||||
* {% jdoc core::lang.rule.stat.StatisticalRule %} and the related helper classes and base rule classes
|
|
||||||
are deprecated for removal in 7.0.0. This includes all of {% jdoc_package core::stat %} and {% jdoc_package core::lang.rule.stat %},
|
|
||||||
and also {% jdoc java::lang.java.rule.AbstractStatisticalJavaRule %}, {% jdoc apex::lang.apex.rule.AbstractStatisticalApexRule %} and the like.
|
|
||||||
The methods {% jdoc !c!core::Report#addMetric(core::stat.Metric) %} and {% jdoc core::ThreadSafeReportListener#metricAdded(core::stat.Metric) %}
|
|
||||||
will also be removed.
|
|
||||||
|
|
||||||
|
|
||||||
### External Contributions
|
### External Contributions
|
||||||
|
|
||||||
* [#1503](https://github.com/pmd/pmd/pull/1503): \[java] Fix for ReturnFromFinallyBlock false-positives - [RishabhDeep Singh](https://github.com/rishabhdeepsingh)
|
|
||||||
* [#1514](https://github.com/pmd/pmd/pull/1514): \[java] LocalVariableCouldBeFinal: allow excluding the variable in a for-each loop - [Kris Scheibe](https://github.com/kris-scheibe)
|
|
||||||
* [#1516](https://github.com/pmd/pmd/pull/1516): \[java] OneDeclarationPerLine: Don't report multiple variables in a for statement. - [Kris Scheibe](https://github.com/kris-scheibe)
|
|
||||||
* [#1520](https://github.com/pmd/pmd/pull/1520): \[java] New rule: ForLoopVariableCount: check the number of control variables in a for loop - [Kris Scheibe](https://github.com/kris-scheibe)
|
|
||||||
* [#1521](https://github.com/pmd/pmd/pull/1521): \[java] Upgrade to ASM7 for JDK 11 support - [Mark Pritchard](https://github.com/markpritchard)
|
|
||||||
* [#1530](https://github.com/pmd/pmd/pull/1530): \[java] New rule: AvoidReassigningLoopVariables - [Kris Scheibe](https://github.com/kris-scheibe)
|
|
||||||
* [#1534](https://github.com/pmd/pmd/pull/1534): \[java] This is the change regarding the usediamondoperator #1517 - [hemanshu070](https://github.com/hemanshu070)
|
|
||||||
* [#1545](https://github.com/pmd/pmd/pull/1545): \[doc] fixing dead links + tool to check for dead links automatically - [Kris Scheibe](https://github.com/kris-scheibe)
|
|
||||||
* [#1551](https://github.com/pmd/pmd/pull/1551): \[java] InvalidSlf4jMessageFormatRule should not throw NPE for enums - [Robbie Martinus](https://github.com/rmartinus)
|
|
||||||
* [#1552](https://github.com/pmd/pmd/pull/1552): \[core] Upgrading Google Gson from 2.5 to 2.8.5 - [Thunderforge](https://github.com/Thunderforge)
|
|
||||||
* [#1553](https://github.com/pmd/pmd/pull/1553): \[core] Upgrading System Rules dependency from 1.8.0 to 1.19.0 - [Thunderforge](https://github.com/Thunderforge)
|
|
||||||
* [#1554](https://github.com/pmd/pmd/pull/1554): \[plsql] updates should allow for multiple statements - [tashiscool](https://github.com/tashiscool)
|
|
||||||
* [#1584](https://github.com/pmd/pmd/pull/1584): \[core] Fixes 1196: inconsistencies of clones returned by different CPD executions for the same files - [Bruno Ferreira](https://github.com/bmbferreira)
|
|
||||||
|
|
||||||
{% endtocmaker %}
|
{% endtocmaker %}
|
||||||
|
|
||||||
|
@ -5,6 +5,131 @@ permalink: pmd_release_notes_old.html
|
|||||||
|
|
||||||
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
|
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
|
||||||
|
|
||||||
|
## 27-January-2019 - 6.11.0
|
||||||
|
|
||||||
|
The PMD team is pleased to announce PMD 6.11.0.
|
||||||
|
|
||||||
|
This is a minor release.
|
||||||
|
|
||||||
|
### Table Of Contents
|
||||||
|
|
||||||
|
* [New and noteworthy](#new-and-noteworthy)
|
||||||
|
* [Updated Apex Support](#updated-apex-support)
|
||||||
|
* [PL/SQL Grammar improvements](#pl/sql-grammar-improvements)
|
||||||
|
* [New Rules](#new-rules)
|
||||||
|
* [Modified Rules](#modified-rules)
|
||||||
|
* [Deprecated Rules](#deprecated-rules)
|
||||||
|
* [Fixed Issues](#fixed-issues)
|
||||||
|
* [API Changes](#api-changes)
|
||||||
|
* [External Contributions](#external-contributions)
|
||||||
|
|
||||||
|
### New and noteworthy
|
||||||
|
|
||||||
|
#### Updated Apex Support
|
||||||
|
|
||||||
|
* The Apex language support has been bumped to version 45 (Spring '19). All new language features are now properly
|
||||||
|
parsed and processed.
|
||||||
|
* Many nodes now expose more informations, such as the operator for BooleanExpressions. This makes these operators
|
||||||
|
consumable by XPath rules, e.g. `//BooleanExpression[@Operator='&&']`.
|
||||||
|
|
||||||
|
#### PL/SQL Grammar improvements
|
||||||
|
|
||||||
|
* In this release, many parser bugs in our PL/SQL support have been fixed. This adds e.g. support for
|
||||||
|
table collection expressions (`SELECT * FROM TABLE(expr)`).
|
||||||
|
* Support for parsing insert statements has been added.
|
||||||
|
* More improvements are planned for the next release of PMD.
|
||||||
|
|
||||||
|
#### New Rules
|
||||||
|
|
||||||
|
* The new Java rule [`UnsynchronizedStaticFormatter`](https://pmd.github.io/pmd-6.11.0/pmd_rules_java_multithreading.html#unsynchronizedstaticformatter) (`java-multithreading`) detects
|
||||||
|
unsynchronized usages of static `java.text.Format` instances. This rule is a more generic replacement of the
|
||||||
|
rule [`UnsynchronizedStaticDateFormatter`](https://pmd.github.io/pmd-6.11.0/pmd_rules_java_multithreading.html#unsynchronizedstaticdateformatter) which focused just on `DateFormat`.
|
||||||
|
|
||||||
|
* The new Java rule [`ForLoopVariableCount`](https://pmd.github.io/pmd-6.11.0/pmd_rules_java_bestpractices.html#forloopvariablecount) (`java-bestpractices`) checks for
|
||||||
|
the number of control variables in a for-loop. Having a lot of control variables makes it harder to understand
|
||||||
|
what the loop does. The maximum allowed number of variables is by default 1 and can be configured by a
|
||||||
|
property.
|
||||||
|
|
||||||
|
* The new Java rule [`AvoidReassigningLoopVariables`](https://pmd.github.io/pmd-6.11.0/pmd_rules_java_bestpractices.html#avoidreassigningloopvariables) (`java-bestpractices`) searches
|
||||||
|
for loop variables that are reassigned. Changing the loop variables additionally to the loop itself can lead to
|
||||||
|
hard-to-find bugs.
|
||||||
|
|
||||||
|
* The new Java rule [`UseDiamondOperator`](https://pmd.github.io/pmd-6.11.0/pmd_rules_java_codestyle.html#usediamondoperator) (`java-codestyle`) looks for constructor
|
||||||
|
calls with explicit type parameters. Since Java 1.7, these type parameters are not necessary anymore, as they
|
||||||
|
can be inferred now.
|
||||||
|
|
||||||
|
#### Modified Rules
|
||||||
|
|
||||||
|
* The Java rule [`LocalVariableCouldBeFinal`](https://pmd.github.io/pmd-6.11.0/pmd_rules_java_codestyle.html#localvariablecouldbefinal) (`java-codestyle`) has a new
|
||||||
|
property `ignoreForEachDecl`, which is by default disabled. The new property allows for ignoring
|
||||||
|
non-final loop variables in a for-each statement.
|
||||||
|
|
||||||
|
#### Deprecated Rules
|
||||||
|
|
||||||
|
* The Java rule [`UnsynchronizedStaticDateFormatter`](https://pmd.github.io/pmd-6.11.0/pmd_rules_java_multithreading.html#unsynchronizedstaticdateformatter) has been deprecated and
|
||||||
|
will be removed with PMD 7.0.0. The rule is replaced by the more general
|
||||||
|
[`UnsynchronizedStaticFormatter`](https://pmd.github.io/pmd-6.11.0/pmd_rules_java_multithreading.html#unsynchronizedstaticformatter).
|
||||||
|
|
||||||
|
### Fixed Issues
|
||||||
|
|
||||||
|
* core
|
||||||
|
* [#1196](https://github.com/pmd/pmd/issues/1196): \[core] CPD results not consistent between runs
|
||||||
|
* [#1496](https://github.com/pmd/pmd/issues/1496) \[core] Refactor metrics to be dealt with generically from pmd-core
|
||||||
|
* apex
|
||||||
|
* [#1542](https://github.com/pmd/pmd/pull/1542): \[apex] Include the documentation category
|
||||||
|
* [#1546](https://github.com/pmd/pmd/issues/1546): \[apex] PMD parsing exception for Apex classes using 'inherited sharing' keyword
|
||||||
|
* [#1568](https://github.com/pmd/pmd/pull/1568): \[apex] AST node attribute @Image not usable / always null in XPath rule / Designer
|
||||||
|
* java
|
||||||
|
* [#1556](https://github.com/pmd/pmd/issues/1556): \[java] Default methods should not be considered abstract
|
||||||
|
* [#1578](https://github.com/pmd/pmd/issues/1578): \[java] Private field is detected as public inside nested classes in interfaces
|
||||||
|
* java-bestpractices
|
||||||
|
* [#658](https://github.com/pmd/pmd/issues/658): \[java] OneDeclarationPerLine: False positive for loops
|
||||||
|
* [#1518](https://github.com/pmd/pmd/issues/1518): \[java] New rule: AvoidReassigningLoopVariable
|
||||||
|
* [#1519](https://github.com/pmd/pmd/issues/1519): \[java] New rule: ForLoopVariableCount
|
||||||
|
* java-codestyle
|
||||||
|
* [#1513](https://github.com/pmd/pmd/issues/1513): \[java] LocalVariableCouldBeFinal: allow excluding the variable in a for-each loop
|
||||||
|
* [#1517](https://github.com/pmd/pmd/issues/1517): \[java] New Rule: UseDiamondOperator
|
||||||
|
* java-errorprone
|
||||||
|
* [#1035](https://github.com/pmd/pmd/issues/1035): \[java] ReturnFromFinallyBlock: False positive on lambda expression in finally block
|
||||||
|
* [#1549](https://github.com/pmd/pmd/issues/1549): \[java] NPE in PMD 6.8.0 InvalidSlf4jMessageFormat
|
||||||
|
* java-multithreading
|
||||||
|
* [#1533](https://github.com/pmd/pmd/issues/1533): \[java] New rule: UnsynchronizedStaticFormatter
|
||||||
|
* plsql
|
||||||
|
* [#1507](https://github.com/pmd/pmd/issues/1507): \[plsql] Parse Exception when using '||' operator in where clause
|
||||||
|
* [#1508](https://github.com/pmd/pmd/issues/1508): \[plsql] Parse Exception when using SELECT COUNT(\*)
|
||||||
|
* [#1509](https://github.com/pmd/pmd/issues/1509): \[plsql] Parse Exception with OUTER/INNER Joins
|
||||||
|
* [#1511](https://github.com/pmd/pmd/issues/1511): \[plsql] Parse Exception with IS NOT NULL
|
||||||
|
* [#1526](https://github.com/pmd/pmd/issues/1526): \[plsql] ParseException when using TableCollectionExpression
|
||||||
|
* [#1583](https://github.com/pmd/pmd/issues/1583): \[plsql] Update Set Clause should allow multiple columns
|
||||||
|
* [#1586](https://github.com/pmd/pmd/issues/1586): \[plsql] Parse Exception when functions are used with LIKE
|
||||||
|
* [#1588](https://github.com/pmd/pmd/issues/1588): \[plsql] Parse Exception with function calls in WHERE clause
|
||||||
|
|
||||||
|
### API Changes
|
||||||
|
|
||||||
|
* [`StatisticalRule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.11.0/net/sourceforge/pmd/lang/rule/stat/StatisticalRule.html#) and the related helper classes and base rule classes
|
||||||
|
are deprecated for removal in 7.0.0. This includes all of [`net.sourceforge.pmd.stat`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.11.0/net/sourceforge/pmd/stat/package-summary.html#) and [`net.sourceforge.pmd.lang.rule.stat`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.11.0/net/sourceforge/pmd/lang/rule/stat/package-summary.html#),
|
||||||
|
and also [`AbstractStatisticalJavaRule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-java/6.11.0/net/sourceforge/pmd/lang/java/rule/AbstractStatisticalJavaRule.html#), [`AbstractStatisticalApexRule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-apex/6.11.0/net/sourceforge/pmd/lang/apex/rule/AbstractStatisticalApexRule.html#) and the like.
|
||||||
|
The methods [`Report#addMetric`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.11.0/net/sourceforge/pmd/Report.html#addMetric(net.sourceforge.pmd.stat.Metric)) and [`metricAdded`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.11.0/net/sourceforge/pmd/ThreadSafeReportListener.html#metricAdded(net.sourceforge.pmd.stat.Metric))
|
||||||
|
will also be removed.
|
||||||
|
* [`setProperty`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.11.0/net/sourceforge/pmd/properties/PropertySource.html#setProperty(net.sourceforge.pmd.properties.MultiValuePropertyDescriptor,Object[])) is deprecated,
|
||||||
|
because [`MultiValuePropertyDescriptor`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.11.0/net/sourceforge/pmd/properties/MultiValuePropertyDescriptor.html#) is deprecated as well
|
||||||
|
|
||||||
|
### External Contributions
|
||||||
|
|
||||||
|
* [#1503](https://github.com/pmd/pmd/pull/1503): \[java] Fix for ReturnFromFinallyBlock false-positives - [RishabhDeep Singh](https://github.com/rishabhdeepsingh)
|
||||||
|
* [#1514](https://github.com/pmd/pmd/pull/1514): \[java] LocalVariableCouldBeFinal: allow excluding the variable in a for-each loop - [Kris Scheibe](https://github.com/kris-scheibe)
|
||||||
|
* [#1516](https://github.com/pmd/pmd/pull/1516): \[java] OneDeclarationPerLine: Don't report multiple variables in a for statement. - [Kris Scheibe](https://github.com/kris-scheibe)
|
||||||
|
* [#1520](https://github.com/pmd/pmd/pull/1520): \[java] New rule: ForLoopVariableCount: check the number of control variables in a for loop - [Kris Scheibe](https://github.com/kris-scheibe)
|
||||||
|
* [#1521](https://github.com/pmd/pmd/pull/1521): \[java] Upgrade to ASM7 for JDK 11 support - [Mark Pritchard](https://github.com/markpritchard)
|
||||||
|
* [#1530](https://github.com/pmd/pmd/pull/1530): \[java] New rule: AvoidReassigningLoopVariables - [Kris Scheibe](https://github.com/kris-scheibe)
|
||||||
|
* [#1534](https://github.com/pmd/pmd/pull/1534): \[java] This is the change regarding the usediamondoperator #1517 - [hemanshu070](https://github.com/hemanshu070)
|
||||||
|
* [#1545](https://github.com/pmd/pmd/pull/1545): \[doc] fixing dead links + tool to check for dead links automatically - [Kris Scheibe](https://github.com/kris-scheibe)
|
||||||
|
* [#1551](https://github.com/pmd/pmd/pull/1551): \[java] InvalidSlf4jMessageFormatRule should not throw NPE for enums - [Robbie Martinus](https://github.com/rmartinus)
|
||||||
|
* [#1552](https://github.com/pmd/pmd/pull/1552): \[core] Upgrading Google Gson from 2.5 to 2.8.5 - [Thunderforge](https://github.com/Thunderforge)
|
||||||
|
* [#1553](https://github.com/pmd/pmd/pull/1553): \[core] Upgrading System Rules dependency from 1.8.0 to 1.19.0 - [Thunderforge](https://github.com/Thunderforge)
|
||||||
|
* [#1554](https://github.com/pmd/pmd/pull/1554): \[plsql] updates should allow for multiple statements - [tashiscool](https://github.com/tashiscool)
|
||||||
|
* [#1584](https://github.com/pmd/pmd/pull/1584): \[core] Fixes 1196: inconsistencies of clones returned by different CPD executions for the same files - [Bruno Ferreira](https://github.com/bmbferreira)
|
||||||
|
|
||||||
## 09-December-2018 - 6.10.0
|
## 09-December-2018 - 6.10.0
|
||||||
|
|
||||||
The PMD team is pleased to announce PMD 6.10.0.
|
The PMD team is pleased to announce PMD 6.10.0.
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.sourceforge.pmd</groupId>
|
<groupId>net.sourceforge.pmd</groupId>
|
||||||
<artifactId>pmd</artifactId>
|
<artifactId>pmd</artifactId>
|
||||||
<version>6.11.0-SNAPSHOT</version>
|
<version>6.12.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.sourceforge.pmd</groupId>
|
<groupId>net.sourceforge.pmd</groupId>
|
||||||
<artifactId>pmd</artifactId>
|
<artifactId>pmd</artifactId>
|
||||||
<version>6.11.0-SNAPSHOT</version>
|
<version>6.12.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -5,21 +5,34 @@
|
|||||||
package net.sourceforge.pmd.lang.apex;
|
package net.sourceforge.pmd.lang.apex;
|
||||||
|
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
|
import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler;
|
||||||
import net.sourceforge.pmd.lang.Parser;
|
import net.sourceforge.pmd.lang.Parser;
|
||||||
import net.sourceforge.pmd.lang.ParserOptions;
|
import net.sourceforge.pmd.lang.ParserOptions;
|
||||||
import net.sourceforge.pmd.lang.VisitorStarter;
|
import net.sourceforge.pmd.lang.VisitorStarter;
|
||||||
import net.sourceforge.pmd.lang.XPathHandler;
|
import net.sourceforge.pmd.lang.XPathHandler;
|
||||||
|
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
||||||
|
import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface;
|
||||||
import net.sourceforge.pmd.lang.apex.ast.ApexNode;
|
import net.sourceforge.pmd.lang.apex.ast.ApexNode;
|
||||||
import net.sourceforge.pmd.lang.apex.ast.DumpFacade;
|
import net.sourceforge.pmd.lang.apex.ast.DumpFacade;
|
||||||
|
import net.sourceforge.pmd.lang.apex.metrics.ApexMetricsComputer;
|
||||||
|
import net.sourceforge.pmd.lang.apex.metrics.api.ApexClassMetricKey;
|
||||||
|
import net.sourceforge.pmd.lang.apex.metrics.api.ApexOperationMetricKey;
|
||||||
import net.sourceforge.pmd.lang.apex.multifile.ApexMultifileVisitorFacade;
|
import net.sourceforge.pmd.lang.apex.multifile.ApexMultifileVisitorFacade;
|
||||||
import net.sourceforge.pmd.lang.apex.rule.ApexRuleViolationFactory;
|
import net.sourceforge.pmd.lang.apex.rule.ApexRuleViolationFactory;
|
||||||
import net.sourceforge.pmd.lang.ast.xpath.DefaultASTXPathHandler;
|
import net.sourceforge.pmd.lang.ast.xpath.DefaultASTXPathHandler;
|
||||||
|
import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider;
|
||||||
|
import net.sourceforge.pmd.lang.metrics.internal.AbstractLanguageMetricsProvider;
|
||||||
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
|
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
|
||||||
|
|
||||||
|
|
||||||
public class ApexHandler extends AbstractLanguageVersionHandler {
|
public class ApexHandler extends AbstractLanguageVersionHandler {
|
||||||
|
|
||||||
|
private final ApexMetricsProvider myMetricsProvider = new ApexMetricsProvider();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VisitorStarter getMultifileFacade() {
|
public VisitorStarter getMultifileFacade() {
|
||||||
return rootNode -> new ApexMultifileVisitorFacade().initializeWith((ApexNode<?>) rootNode);
|
return rootNode -> new ApexMultifileVisitorFacade().initializeWith((ApexNode<?>) rootNode);
|
||||||
@ -51,4 +64,31 @@ public class ApexHandler extends AbstractLanguageVersionHandler {
|
|||||||
return rootNode -> new DumpFacade().initializeWith(writer, prefix, recurse, (ApexNode<?>) rootNode);
|
return rootNode -> new DumpFacade().initializeWith(writer, prefix, recurse, (ApexNode<?>) rootNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LanguageMetricsProvider<ASTUserClassOrInterface<?>, ASTMethod> getLanguageMetricsProvider() {
|
||||||
|
return myMetricsProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class ApexMetricsProvider extends AbstractLanguageMetricsProvider<ASTUserClassOrInterface<?>, ASTMethod> {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
ApexMetricsProvider() {
|
||||||
|
// a wild double cast
|
||||||
|
super((Class<ASTUserClassOrInterface<?>>) (Object) ASTUserClassOrInterface.class, ASTMethod.class, ApexMetricsComputer.getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ApexClassMetricKey> getAvailableTypeMetrics() {
|
||||||
|
return Arrays.asList(ApexClassMetricKey.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ApexOperationMetricKey> getAvailableOperationMetrics() {
|
||||||
|
return Arrays.asList(ApexOperationMetricKey.values());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.lang.apex.ast;
|
package net.sourceforge.pmd.lang.apex.ast;
|
||||||
|
|
||||||
|
import apex.jorje.data.ast.AssignmentOp;
|
||||||
import apex.jorje.semantic.ast.expression.AssignmentExpression;
|
import apex.jorje.semantic.ast.expression.AssignmentExpression;
|
||||||
|
|
||||||
public class ASTAssignmentExpression extends AbstractApexNode<AssignmentExpression> {
|
public class ASTAssignmentExpression extends AbstractApexNode<AssignmentExpression> {
|
||||||
@ -16,4 +17,8 @@ public class ASTAssignmentExpression extends AbstractApexNode<AssignmentExpressi
|
|||||||
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
||||||
return visitor.visit(this, data);
|
return visitor.visit(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AssignmentOp getOperator() {
|
||||||
|
return node.getOp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.lang.apex.ast;
|
package net.sourceforge.pmd.lang.apex.ast;
|
||||||
|
|
||||||
|
import apex.jorje.data.ast.BinaryOp;
|
||||||
import apex.jorje.semantic.ast.expression.BinaryExpression;
|
import apex.jorje.semantic.ast.expression.BinaryExpression;
|
||||||
|
|
||||||
public class ASTBinaryExpression extends AbstractApexNode<BinaryExpression> {
|
public class ASTBinaryExpression extends AbstractApexNode<BinaryExpression> {
|
||||||
@ -16,4 +17,8 @@ public class ASTBinaryExpression extends AbstractApexNode<BinaryExpression> {
|
|||||||
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
||||||
return visitor.visit(this, data);
|
return visitor.visit(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BinaryOp getOperator() {
|
||||||
|
return node.getOp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,25 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.lang.apex.ast;
|
package net.sourceforge.pmd.lang.apex.ast;
|
||||||
|
|
||||||
|
import apex.jorje.data.ast.BooleanOp;
|
||||||
import apex.jorje.semantic.ast.expression.BooleanExpression;
|
import apex.jorje.semantic.ast.expression.BooleanExpression;
|
||||||
|
|
||||||
|
|
||||||
public class ASTBooleanExpression extends AbstractApexNode<BooleanExpression> {
|
public class ASTBooleanExpression extends AbstractApexNode<BooleanExpression> {
|
||||||
|
|
||||||
public ASTBooleanExpression(BooleanExpression booleanExpression) {
|
public ASTBooleanExpression(BooleanExpression booleanExpression) {
|
||||||
super(booleanExpression);
|
super(booleanExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
||||||
return visitor.visit(this, data);
|
return visitor.visit(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BooleanOp getOperator() {
|
||||||
|
return this.node.getOp();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,24 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.lang.apex.ast;
|
package net.sourceforge.pmd.lang.apex.ast;
|
||||||
|
|
||||||
|
import apex.jorje.data.ast.LiteralType;
|
||||||
import apex.jorje.semantic.ast.expression.LiteralExpression;
|
import apex.jorje.semantic.ast.expression.LiteralExpression;
|
||||||
|
|
||||||
|
|
||||||
public class ASTLiteralExpression extends AbstractApexNode<LiteralExpression> {
|
public class ASTLiteralExpression extends AbstractApexNode<LiteralExpression> {
|
||||||
|
|
||||||
public ASTLiteralExpression(LiteralExpression literalExpression) {
|
public ASTLiteralExpression(LiteralExpression literalExpression) {
|
||||||
super(literalExpression);
|
super(literalExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
||||||
return visitor.visit(this, data);
|
return visitor.visit(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public LiteralType getLiteralType() {
|
||||||
|
return node.getLiteralType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,24 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.lang.apex.ast;
|
package net.sourceforge.pmd.lang.apex.ast;
|
||||||
|
|
||||||
|
import apex.jorje.data.ast.PostfixOp;
|
||||||
import apex.jorje.semantic.ast.expression.PostfixExpression;
|
import apex.jorje.semantic.ast.expression.PostfixExpression;
|
||||||
|
|
||||||
|
|
||||||
public class ASTPostfixExpression extends AbstractApexNode<PostfixExpression> {
|
public class ASTPostfixExpression extends AbstractApexNode<PostfixExpression> {
|
||||||
|
|
||||||
public ASTPostfixExpression(PostfixExpression postfixExpression) {
|
public ASTPostfixExpression(PostfixExpression postfixExpression) {
|
||||||
super(postfixExpression);
|
super(postfixExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
||||||
return visitor.visit(this, data);
|
return visitor.visit(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PostfixOp getOperator() {
|
||||||
|
return node.getOp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.lang.apex.ast;
|
package net.sourceforge.pmd.lang.apex.ast;
|
||||||
|
|
||||||
|
import apex.jorje.data.ast.PrefixOp;
|
||||||
import apex.jorje.semantic.ast.expression.PrefixExpression;
|
import apex.jorje.semantic.ast.expression.PrefixExpression;
|
||||||
|
|
||||||
public class ASTPrefixExpression extends AbstractApexNode<PrefixExpression> {
|
public class ASTPrefixExpression extends AbstractApexNode<PrefixExpression> {
|
||||||
@ -16,4 +17,10 @@ public class ASTPrefixExpression extends AbstractApexNode<PrefixExpression> {
|
|||||||
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
||||||
return visitor.visit(this, data);
|
return visitor.visit(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PrefixOp getOperator() {
|
||||||
|
return node.getOp();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
package net.sourceforge.pmd.lang.apex.ast;
|
package net.sourceforge.pmd.lang.apex.ast;
|
||||||
|
|
||||||
|
import apex.jorje.semantic.ast.expression.IdentifierContext;
|
||||||
import apex.jorje.semantic.ast.expression.ReferenceExpression;
|
import apex.jorje.semantic.ast.expression.ReferenceExpression;
|
||||||
|
import apex.jorje.semantic.ast.expression.ReferenceType;
|
||||||
|
|
||||||
|
|
||||||
public class ASTReferenceExpression extends AbstractApexNode<ReferenceExpression> {
|
public class ASTReferenceExpression extends AbstractApexNode<ReferenceExpression> {
|
||||||
|
|
||||||
@ -12,8 +15,19 @@ public class ASTReferenceExpression extends AbstractApexNode<ReferenceExpression
|
|||||||
super(referenceExpression);
|
super(referenceExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
public Object jjtAccept(ApexParserVisitor visitor, Object data) {
|
||||||
return visitor.visit(this, data);
|
return visitor.visit(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IdentifierContext getContext() {
|
||||||
|
return node.getContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ReferenceType getReferenceType() {
|
||||||
|
return node.getReferenceType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ public abstract class AbstractApexNode<T extends AstNode> extends AbstractApexNo
|
|||||||
|
|
||||||
protected final T node;
|
protected final T node;
|
||||||
|
|
||||||
public AbstractApexNode(T node) {
|
protected AbstractApexNode(T node) {
|
||||||
super(node.getClass());
|
super(node.getClass());
|
||||||
this.node = node;
|
this.node = node;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.apex.metrics;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.sourceforge.pmd.annotation.InternalApi;
|
||||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
||||||
import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface;
|
import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface;
|
||||||
import net.sourceforge.pmd.lang.metrics.AbstractMetricsComputer;
|
import net.sourceforge.pmd.lang.metrics.AbstractMetricsComputer;
|
||||||
@ -18,7 +19,13 @@ import net.sourceforge.pmd.lang.metrics.AbstractMetricsComputer;
|
|||||||
*/
|
*/
|
||||||
public class ApexMetricsComputer extends AbstractMetricsComputer<ASTUserClassOrInterface<?>, ASTMethod> {
|
public class ApexMetricsComputer extends AbstractMetricsComputer<ASTUserClassOrInterface<?>, ASTMethod> {
|
||||||
|
|
||||||
static final ApexMetricsComputer INSTANCE = new ApexMetricsComputer();
|
private static final ApexMetricsComputer INSTANCE = new ApexMetricsComputer();
|
||||||
|
|
||||||
|
|
||||||
|
@InternalApi
|
||||||
|
public static ApexMetricsComputer getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,7 +27,7 @@ public class ApexMetricsFacade extends AbstractMetricsFacade<ASTUserClassOrInter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MetricsComputer<ASTUserClassOrInterface<?>, ASTMethod> getLanguageSpecificComputer() {
|
protected MetricsComputer<ASTUserClassOrInterface<?>, ASTMethod> getLanguageSpecificComputer() {
|
||||||
return ApexMetricsComputer.INSTANCE;
|
return ApexMetricsComputer.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sourceforge.pmd.lang.apex.ast;
|
||||||
|
|
||||||
|
import static net.sourceforge.pmd.lang.apex.ast.ApexParserTestHelpers.parse;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import net.sourceforge.pmd.lang.ast.Node;
|
||||||
|
|
||||||
|
import apex.jorje.semantic.ast.compilation.Compilation;
|
||||||
|
|
||||||
|
public class ApexParserXPathTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBooleanExpressions() throws Exception {
|
||||||
|
ApexNode<Compilation> node = parse(IOUtils.toString(ApexParserXPathTest.class.getResourceAsStream("BooleanExpressions.cls"),
|
||||||
|
StandardCharsets.UTF_8));
|
||||||
|
List<ASTBooleanExpression> booleanExpressions = node.findDescendantsOfType(ASTBooleanExpression.class);
|
||||||
|
Assert.assertEquals(2, booleanExpressions.size());
|
||||||
|
Assert.assertEquals("&&", booleanExpressions.get(0).getOperator().toString());
|
||||||
|
Assert.assertEquals("!=", booleanExpressions.get(1).getOperator().toString());
|
||||||
|
|
||||||
|
List<? extends Node> xpathResult = node.findChildNodesWithXPath("//BooleanExpression[@Operator='&&']");
|
||||||
|
Assert.assertEquals(1, xpathResult.size());
|
||||||
|
Assert.assertSame(booleanExpressions.get(0), xpathResult.get(0));
|
||||||
|
}
|
||||||
|
}
|
@ -91,7 +91,7 @@ public class ApexProjectMirrorTest {
|
|||||||
@Override
|
@Override
|
||||||
public Object visit(ASTMethod node, Object data) {
|
public Object visit(ASTMethod node, Object data) {
|
||||||
MetricMemoizer<ASTMethod> op = toplevel.getOperationMemoizer(node.getQualifiedName());
|
MetricMemoizer<ASTMethod> op = toplevel.getOperationMemoizer(node.getQualifiedName());
|
||||||
result.add((int) ApexMetricsComputer.INSTANCE.computeForOperation(opMetricKey, node, force,
|
result.add((int) ApexMetricsComputer.getInstance().computeForOperation(opMetricKey, node, force,
|
||||||
MetricOptions.emptyOptions(), op));
|
MetricOptions.emptyOptions(), op));
|
||||||
return super.visit(node, data);
|
return super.visit(node, data);
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ public class ApexProjectMirrorTest {
|
|||||||
@Override
|
@Override
|
||||||
public Object visit(ASTUserClass node, Object data) {
|
public Object visit(ASTUserClass node, Object data) {
|
||||||
MetricMemoizer<ASTUserClassOrInterface<?>> clazz = toplevel.getClassMemoizer(node.getQualifiedName());
|
MetricMemoizer<ASTUserClassOrInterface<?>> clazz = toplevel.getClassMemoizer(node.getQualifiedName());
|
||||||
result.add((int) ApexMetricsComputer.INSTANCE.computeForType(classMetricKey, node, force,
|
result.add((int) ApexMetricsComputer.getInstance().computeForType(classMetricKey, node, force,
|
||||||
MetricOptions.emptyOptions(), clazz));
|
MetricOptions.emptyOptions(), clazz));
|
||||||
return super.visit(node, data);
|
return super.visit(node, data);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
// See https://github.com/pmd/pmd/issues/1568
|
||||||
|
|
||||||
|
class MyApexClass {
|
||||||
|
void bar(){
|
||||||
|
if(!alist.isEmpty() && alist != null) {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.sourceforge.pmd</groupId>
|
<groupId>net.sourceforge.pmd</groupId>
|
||||||
<artifactId>pmd</artifactId>
|
<artifactId>pmd</artifactId>
|
||||||
<version>6.11.0-SNAPSHOT</version>
|
<version>6.12.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sourceforge.pmd.internal.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Clément Fournier
|
||||||
|
* @since 6.11.0
|
||||||
|
*/
|
||||||
|
public final class IteratorUtil {
|
||||||
|
|
||||||
|
private IteratorUtil() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static <T> Iterator<T> reverse(Iterator<T> it) {
|
||||||
|
List<T> tmp = toList(it);
|
||||||
|
Collections.reverse(tmp);
|
||||||
|
return tmp.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static <T> List<T> toList(Iterator<T> it) {
|
||||||
|
List<T> list = new ArrayList<>();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
list.add(it.next());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static <T> Iterable<T> toIterable(final Iterator<T> it) {
|
||||||
|
return new Iterable<T>() {
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -7,6 +7,8 @@ package net.sourceforge.pmd.lang;
|
|||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
|
||||||
import net.sourceforge.pmd.lang.dfa.DFAGraphRule;
|
import net.sourceforge.pmd.lang.dfa.DFAGraphRule;
|
||||||
|
import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a generic implementation of the LanguageVersionHandler interface.
|
* This is a generic implementation of the LanguageVersionHandler interface.
|
||||||
@ -71,4 +73,10 @@ public abstract class AbstractLanguageVersionHandler implements LanguageVersionH
|
|||||||
public DFAGraphRule getDFAGraphRule() {
|
public DFAGraphRule getDFAGraphRule() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LanguageMetricsProvider<?, ?> getLanguageMetricsProvider() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,10 @@ package net.sourceforge.pmd.lang;
|
|||||||
|
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
|
||||||
|
import net.sourceforge.pmd.annotation.Experimental;
|
||||||
import net.sourceforge.pmd.annotation.InternalApi;
|
import net.sourceforge.pmd.annotation.InternalApi;
|
||||||
import net.sourceforge.pmd.lang.dfa.DFAGraphRule;
|
import net.sourceforge.pmd.lang.dfa.DFAGraphRule;
|
||||||
|
import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider;
|
||||||
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
|
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,4 +137,17 @@ public interface LanguageVersionHandler {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
@InternalApi
|
@InternalApi
|
||||||
DFAGraphRule getDFAGraphRule();
|
DFAGraphRule getDFAGraphRule();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the metrics provider for this language version,
|
||||||
|
* or null if it has none.
|
||||||
|
*
|
||||||
|
* Note: this is experimental, ie unstable until 7.0.0, after
|
||||||
|
* which it will probably be promoted to a stable API. For
|
||||||
|
* instance the return type will probably be changed to an Optional.
|
||||||
|
*/
|
||||||
|
@Experimental
|
||||||
|
LanguageMetricsProvider<?, ?> getLanguageMetricsProvider();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.ast.xpath;
|
|||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -18,6 +19,9 @@ import net.sourceforge.pmd.lang.ast.Node;
|
|||||||
* Attributes know their name, the node they wrap,
|
* Attributes know their name, the node they wrap,
|
||||||
* and have access to their value.
|
* and have access to their value.
|
||||||
*
|
*
|
||||||
|
* <p>Two attributes are equal if they have the same name
|
||||||
|
* and their parent nodes are equal.
|
||||||
|
*
|
||||||
* @author daniels
|
* @author daniels
|
||||||
*/
|
*/
|
||||||
public class Attribute {
|
public class Attribute {
|
||||||
@ -28,8 +32,8 @@ public class Attribute {
|
|||||||
|
|
||||||
private static final Object[] EMPTY_OBJ_ARRAY = new Object[0];
|
private static final Object[] EMPTY_OBJ_ARRAY = new Object[0];
|
||||||
|
|
||||||
private Node parent;
|
private final Node parent;
|
||||||
private String name;
|
private final String name;
|
||||||
private Method method;
|
private Method method;
|
||||||
private Object value;
|
private Object value;
|
||||||
private String stringValue;
|
private String stringValue;
|
||||||
@ -41,7 +45,6 @@ public class Attribute {
|
|||||||
this.method = m;
|
this.method = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Creates a new attribute belonging to the given node using its string value. */
|
/** Creates a new attribute belonging to the given node using its string value. */
|
||||||
public Attribute(Node parent, String name, String value) {
|
public Attribute(Node parent, String name, String value) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
@ -93,12 +96,33 @@ public class Attribute {
|
|||||||
return stringValue;
|
return stringValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Attribute attribute = (Attribute) o;
|
||||||
|
return Objects.equals(parent, attribute.parent)
|
||||||
|
&& Objects.equals(name, attribute.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(parent, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private String getLoggableAttributeName() {
|
private String getLoggableAttributeName() {
|
||||||
return parent.getXPathNodeName() + "/@" + name;
|
return parent.getXPathNodeName() + "/@" + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name + ':' + getValue() + ':' + parent;
|
return name + ':' + getValue() + ':' + parent.getXPathNodeName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,6 @@ public class AttributeAxisIterator implements Iterator<Attribute> {
|
|||||||
this.currObj = getNextAttribute();
|
this.currObj = getNextAttribute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given method is an attribute accessor,
|
* Returns whether the given method is an attribute accessor,
|
||||||
* in which case a corresponding Attribute will be added to
|
* in which case a corresponding Attribute will be added to
|
||||||
@ -80,12 +79,16 @@ public class AttributeAxisIterator implements Iterator<Attribute> {
|
|||||||
protected boolean isAttributeAccessor(Method method) {
|
protected boolean isAttributeAccessor(Method method) {
|
||||||
String methodName = method.getName();
|
String methodName = method.getName();
|
||||||
|
|
||||||
return CONSIDERED_RETURN_TYPES.contains(method.getReturnType())
|
return isConsideredReturnType(method.getReturnType())
|
||||||
&& method.getParameterTypes().length == 0
|
&& method.getParameterTypes().length == 0
|
||||||
&& !methodName.startsWith("jjt")
|
&& !methodName.startsWith("jjt")
|
||||||
&& !FILTERED_OUT_NAMES.contains(methodName);
|
&& !FILTERED_OUT_NAMES.contains(methodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isConsideredReturnType(Class<?> klass) {
|
||||||
|
return CONSIDERED_RETURN_TYPES.contains(klass) || klass.isEnum();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Attribute next() {
|
public Attribute next() {
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sourceforge.pmd.lang.metrics;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sourceforge.pmd.annotation.Experimental;
|
||||||
|
import net.sourceforge.pmd.lang.LanguageVersionHandler;
|
||||||
|
import net.sourceforge.pmd.lang.ast.Node;
|
||||||
|
import net.sourceforge.pmd.lang.ast.QualifiableNode;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Language-specific provider for metrics. Knows about all the metrics
|
||||||
|
* defined for a language. Can be used e.g. to build GUI applications
|
||||||
|
* like the designer, in a language independent way. Accessible through
|
||||||
|
* {@link LanguageVersionHandler#getLanguageMetricsProvider()}.
|
||||||
|
*
|
||||||
|
* Note: this is experimental, ie unstable until 7.0.0, after which it will probably
|
||||||
|
* be promoted to a real API.
|
||||||
|
*
|
||||||
|
* @param <T> Type of type declaration nodes of the language
|
||||||
|
* @param <O> Type of operation declaration nodes of the language
|
||||||
|
*
|
||||||
|
* @author Clément Fournier
|
||||||
|
* @since 6.11.0
|
||||||
|
*/
|
||||||
|
@Experimental
|
||||||
|
public interface LanguageMetricsProvider<T extends QualifiableNode, O extends QualifiableNode> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all supported type metric keys
|
||||||
|
* for the language.
|
||||||
|
*/
|
||||||
|
List<? extends MetricKey<T>> getAvailableTypeMetrics();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all supported operation metric keys
|
||||||
|
* for the language.
|
||||||
|
*/
|
||||||
|
List<? extends MetricKey<O>> getAvailableOperationMetrics();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given node casted to {@link T} if it's of the correct
|
||||||
|
* type, otherwise returns null.
|
||||||
|
*/
|
||||||
|
T asTypeNode(Node anyNode);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given node casted to {@link O} if it's of the correct
|
||||||
|
* type, otherwise returns null.
|
||||||
|
*/
|
||||||
|
O asOperationNode(Node anyNode);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like {@link MetricsComputer#computeForType(MetricKey, QualifiableNode, boolean, MetricOptions, MetricMemoizer)},
|
||||||
|
* but performs no memoisation.
|
||||||
|
*/
|
||||||
|
double computeForType(MetricKey<T> key, T node, MetricOptions options);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like {@link MetricsComputer#computeForOperation(MetricKey, QualifiableNode, boolean, MetricOptions, MetricMemoizer)}
|
||||||
|
* but performs no memoisation.
|
||||||
|
*/
|
||||||
|
double computeForOperation(MetricKey<O> key, O node, MetricOptions options);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like {@link MetricsComputer#computeWithResultOption(MetricKey, QualifiableNode, boolean, MetricOptions, ResultOption, ProjectMemoizer)}
|
||||||
|
* but performs no memoisation.
|
||||||
|
*/
|
||||||
|
double computeWithResultOption(MetricKey<O> key, T node, MetricOptions options, ResultOption option);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes all metrics available on the given node.
|
||||||
|
* The returned results may contain Double.NaN as a value.
|
||||||
|
*
|
||||||
|
* @param node Node to inspect
|
||||||
|
*
|
||||||
|
* @return A map of metric key to their result, possibly empty, but with no null value
|
||||||
|
*/
|
||||||
|
Map<MetricKey<?>, Double> computeAllMetricsFor(Node node);
|
||||||
|
}
|
@ -41,5 +41,6 @@ public interface MetricKey<N extends Node> {
|
|||||||
*/
|
*/
|
||||||
boolean supports(N node);
|
boolean supports(N node);
|
||||||
|
|
||||||
|
// TODO the metric key should know about supported options
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sourceforge.pmd.lang.metrics.internal;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sourceforge.pmd.lang.ast.Node;
|
||||||
|
import net.sourceforge.pmd.lang.ast.QualifiableNode;
|
||||||
|
import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider;
|
||||||
|
import net.sourceforge.pmd.lang.metrics.MetricKey;
|
||||||
|
import net.sourceforge.pmd.lang.metrics.MetricOptions;
|
||||||
|
import net.sourceforge.pmd.lang.metrics.MetricsComputer;
|
||||||
|
import net.sourceforge.pmd.lang.metrics.ResultOption;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base implementation for {@link LanguageMetricsProvider}.
|
||||||
|
*
|
||||||
|
* @author Clément Fournier
|
||||||
|
* @since 6.11.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractLanguageMetricsProvider<T extends QualifiableNode, O extends QualifiableNode> implements LanguageMetricsProvider<T, O> {
|
||||||
|
|
||||||
|
private final Class<T> tClass;
|
||||||
|
private final Class<O> oClass;
|
||||||
|
private final MetricsComputer<T, O> myComputer;
|
||||||
|
|
||||||
|
|
||||||
|
protected AbstractLanguageMetricsProvider(Class<T> tClass,
|
||||||
|
Class<O> oClass,
|
||||||
|
MetricsComputer<T, O> computer) {
|
||||||
|
this.tClass = tClass;
|
||||||
|
this.oClass = oClass;
|
||||||
|
this.myComputer = computer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T asTypeNode(Node anyNode) {
|
||||||
|
return tClass.isInstance(anyNode) ? tClass.cast(anyNode) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public O asOperationNode(Node anyNode) {
|
||||||
|
return oClass.isInstance(anyNode) ? oClass.cast(anyNode) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double computeForType(MetricKey<T> key, T node, MetricOptions options) {
|
||||||
|
return myComputer.computeForType(key, node, true, options, DummyMetricMemoizer.<T>getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double computeForOperation(MetricKey<O> key, O node, MetricOptions options) {
|
||||||
|
return myComputer.computeForOperation(key, node, true, options, DummyMetricMemoizer.<O>getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double computeWithResultOption(MetricKey<O> key, T node, MetricOptions options, ResultOption option) {
|
||||||
|
return myComputer.computeWithResultOption(key, node, true, options, option, DummyProjectMemoizer.<T, O>getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<MetricKey<?>, Double> computeAllMetricsFor(Node node) {
|
||||||
|
Map<MetricKey<?>, Double> results = new HashMap<>();
|
||||||
|
T t = asTypeNode(node);
|
||||||
|
if (t != null) {
|
||||||
|
for (MetricKey<T> tkey : getAvailableTypeMetrics()) {
|
||||||
|
results.put(tkey, computeForType(tkey, t, MetricOptions.emptyOptions()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
O o = asOperationNode(node);
|
||||||
|
if (o != null) {
|
||||||
|
for (MetricKey<O> okey : getAvailableOperationMetrics()) {
|
||||||
|
results.put(okey, computeForOperation(okey, o, MetricOptions.emptyOptions()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user