Merge branch 'master' into designer-breadcrumbbar

This commit is contained in:
Clément Fournier
2019-01-27 16:51:58 +01:00
111 changed files with 1651 additions and 517 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 %}

View File

@ -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.

View File

@ -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>

View File

@ -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>

View File

@ -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());
}
}
} }

View File

@ -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();
}
} }

View File

@ -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();
}
} }

View File

@ -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();
}
} }

View File

@ -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();
}
} }

View File

@ -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();
}
} }

View File

@ -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();
}
} }

View File

@ -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();
}
} }

View File

@ -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;
} }

View File

@ -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

View File

@ -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();
} }

View File

@ -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));
}
}

View File

@ -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);
} }

View File

@ -0,0 +1,9 @@
// See https://github.com/pmd/pmd/issues/1568
class MyApexClass {
void bar(){
if(!alist.isEmpty() && alist != null) {
foo();
}
}
}

View File

@ -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>

View File

@ -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;
}
};
}
}

View File

@ -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;
}
} }

View File

@ -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();
} }

View File

@ -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();
} }
} }

View File

@ -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() {

View File

@ -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);
}

View File

@ -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
} }

View File

@ -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