Merge branch 'master' into issue-2615

This commit is contained in:
Clément Fournier
2020-07-20 16:36:16 +02:00
133 changed files with 5633 additions and 675 deletions

View File

@ -49,7 +49,7 @@ jobs:
env: BUILD=publish
before_install:
- bash .travis/before_install.sh "11.0.7+10"
- bash .travis/before_install.sh "11.0.8+10"
- source ${HOME}/java.env
install: true
before_script: true

View File

@ -4,7 +4,7 @@ set -e
source .travis/logger.sh
source .travis/common-functions.sh
VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec)
VERSION=$(get_pom_version)
log_info "Building PMD Coveralls.io report ${VERSION} on branch ${TRAVIS_BRANCH}"
if ! travis_isPush; then

View File

@ -7,7 +7,7 @@ source .travis/github-releases-api.sh
source .travis/sourceforge-api.sh
source .travis/regression-tester.sh
VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec)
VERSION=$(get_pom_version)
log_info "Building PMD ${VERSION} on branch ${TRAVIS_BRANCH}"
MVN_BUILD_FLAGS="-B -V"

View File

@ -8,7 +8,7 @@ source .travis/sourceforge-api.sh
source .travis/pmd-code-api.sh
function main() {
VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec)
VERSION=$(get_pom_version)
log_info "Building PMD Documentation ${VERSION} on branch ${TRAVIS_BRANCH}"
#

View File

@ -6,7 +6,7 @@ source .travis/common-functions.sh
source .travis/github-releases-api.sh
source .travis/sourceforge-api.sh
VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec)
VERSION=$(get_pom_version)
log_info "PMD Release ${VERSION}"
if ! travis_isPush; then

View File

@ -4,7 +4,7 @@ set -e
source .travis/logger.sh
source .travis/common-functions.sh
VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec)
VERSION=$(get_pom_version)
log_info "Building PMD Sonar ${VERSION} on branch ${TRAVIS_BRANCH}"
if ! travis_isPush; then

View File

@ -53,3 +53,7 @@ function travis_isWindows() {
return 1
fi
}
function get_pom_version() {
echo $(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:3.0.0:exec)
}

View File

@ -25,7 +25,7 @@ echo "Releasing PMD"
echo "-------------------------------------------"
# see also https://gist.github.com/pdunnavant/4743895
CURRENT_VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec)
CURRENT_VERSION=$(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:3.0.0:exec)
RELEASE_VERSION=${CURRENT_VERSION%-SNAPSHOT}
MAJOR=$(echo $RELEASE_VERSION | cut -d . -f 1)
MINOR=$(echo $RELEASE_VERSION | cut -d . -f 2)

View File

@ -36,6 +36,7 @@ require_relative 'jdoc_namespace_tag'
# * The (erased) types of method arguments must be fully qualified. This is the same
# convention as in javadoc {@link} tags, so you can use you're IDE's javadoc auto-
# complete and copy-paste. Namespaces also can be used for method arguments if they're from PMD.
# * Use the name <init> to reference a constructor
#
#
# * Defining custom namespaces
@ -90,13 +91,15 @@ require_relative 'jdoc_namespace_tag'
# - Include spaces in any part of the reference
# - Use double or single quotes around the arguments
# - Use the "#" suffix to reference a nested type, instead, use a dot "." and reference it like a normal type name
# - Use `[]` instead of `...` for vararg parameters
# - Use the type name instead of `<init>` for a constructor
#
#
class JavadocTag < Liquid::Tag
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 + "))*" + ')\)')
@ -174,7 +177,7 @@ class JavadocTag < Liquid::Tag
def self.get_visible_name(opts, type_fqcn, member_suffix, is_package_ref, resolved_type)
# method or field
if member_suffix && Regexp.new('(\w+)(' + ARGUMENTS_REGEX.source + ")?") =~ member_suffix
if member_suffix && Regexp.new('(\w+|<init>)(' + ARGUMENTS_REGEX.source + ")?") =~ member_suffix
suffix = $1 # method or field name

View File

@ -14,16 +14,53 @@ This is a {{ site.pmd.release_type }} release.
### New and noteworthy
### Fixed Issues
#### New Rules
* The new Java rule {% rule "java/bestpractices/UnusedAssignment" %} (`java-bestpractices`) finds assignments
to variables, that are never used and are useless. The new rule is supposed to entirely replace
{% rule "java/errorprone/DataflowAnomalyAnalysis" %}.
### Fixed Issues
* apex
* [#2610](https://github.com/pmd/pmd/pull/2610): \[apex] Support top-level enums in rules
* apex-bestpractices
* [#2626](https://github.com/pmd/pmd/issues/2626): \[apex] UnusedLocalVariable - false positive on case insensitivity allowed in Apex
* apex-security
* [#2620](https://github.com/pmd/pmd/issues/2620): \[visualforce] False positive on VfUnescapeEl with new Message Channel feature
* core
* [#710](https://github.com/pmd/pmd/issues/710): \[core] Review used dependencies
* [#2594](https://github.com/pmd/pmd/issues/2594): \[core] Update exec-maven-plugin and align it in all project
* [#2615](https://github.com/pmd/pmd/issues/2615): \[core] PMD/CPD produces invalid XML (insufficient escaping/wrong encoding)
* java-design
* [#2174](https://github.com/pmd/pmd/issues/2174): \[java] LawOfDemeter: False positive with 'this' pointer
* [#2189](https://github.com/pmd/pmd/issues/2189): \[java] LawOfDemeter: False positive when casting to derived class
* java-errorprone
* [#2578](https://github.com/pmd/pmd/issues/2578): \[java] AvoidCallingFinalize detects some false positives
* [#2634](https://github.com/pmd/pmd/issues/2634): \[java] NullPointerException in rule ProperCloneImplementation
* java-performance
* [#1736](https://github.com/pmd/pmd/issues/1736): \[java] UseStringBufferForStringAppends: False positive if only one concatenation
* [#2207](https://github.com/pmd/pmd/issues/2207): \[java] AvoidInstantiatingObjectsInLoops: False positive - should not flag objects when assigned to lists/arrays
### API Changes
#### Deprecated API
##### For removal
* {% jdoc core::lang.rule.RuleChainVisitor %} and all implementations in language modules
* {% jdoc core::lang.rule.AbstractRuleChainVisitor %}
* {% jdoc core::lang.Language#getRuleChainVisitorClass() %}
* {% jdoc core::lang.BaseLanguageModule#<init>(java.lang.String,java.lang.String,java.lang.String,java.lang.Class,java.lang.String...) %}
### External Contributions
* [#2558](https://github.com/pmd/pmd/pull/2558): \[java] Fix issue #1736 and issue #2207 - [Young Chan](https://github.com/YYoungC)
* [#2560](https://github.com/pmd/pmd/pull/2560): \[java] Fix false positives of LawOfDemeter: this and cast expressions - [xioayuge](https://github.com/xioayuge)
* [#2590](https://github.com/pmd/pmd/pull/2590): Update libraries snyk is referring to as `unsafe` - [Artem Krosheninnikov](https://github.com/KroArtem)
* [#2597](https://github.com/pmd/pmd/pull/2597): \[dependencies] Fix issue #2594, update exec-maven-plugin everywhere - [Artem Krosheninnikov](https://github.com/KroArtem)
* [#2621](https://github.com/pmd/pmd/pull/2621): \[visualforce] add new safe resource for VfUnescapeEl - [Peter Chittum](https://github.com/pchittum)
* [#2640](https://github.com/pmd/pmd/pull/2640): \[java] NullPointerException in rule ProperCloneImplementation - [Mykhailo Palahuta](https://github.com/Drofff)
* [#2643](https://github.com/pmd/pmd/pull/2643): \[java] AvoidCallingFinalize detects some false positives (2578) - [Mykhailo Palahuta](https://github.com/Drofff)
{% endtocmaker %}

View File

@ -54,12 +54,12 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.7</version>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
@ -89,7 +89,6 @@
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr-runtime</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
@ -119,7 +118,7 @@
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.17</version>
<version>1.26</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>

View File

@ -1,125 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>pmd-apex</artifactId>
<name>PMD Apex</name>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>pmd-apex</artifactId>
<name>PMD Apex</name>
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>6.26.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>6.26.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<properties>
<java.version>8</java.version>
</properties>
<properties>
<java.version>8</java.version>
</properties>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<useDefaultDelimiters>false</useDefaultDelimiters>
<delimiters>
<delimiter>${*}</delimiter>
</delimiters>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-core</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>pmd-apex-jorje</artifactId>
<version>${project.version}</version>
<classifier>lib</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>pmd-apex-jorje</artifactId>
<version>${project.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>net.sourceforge.saxon</groupId>
<artifactId>saxon</artifactId>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-lang-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>designer</id>
<build>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<mainClass>net.sourceforge.pmd.util.designer.Designer</mainClass>
<includePluginDependencies>true</includePluginDependencies>
</configuration>
<dependencies>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-java</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<useDefaultDelimiters>false</useDefaultDelimiters>
<delimiters>
<delimiter>${*}</delimiter>
</delimiters>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</build>
<dependencies>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-core</artifactId>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr-runtime</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>pmd-apex-jorje</artifactId>
<version>${project.version}</version>
<classifier>lib</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>pmd-apex-jorje</artifactId>
<version>${project.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd-lang-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -5,18 +5,20 @@
package net.sourceforge.pmd.lang.apex;
import net.sourceforge.pmd.lang.BaseLanguageModule;
import net.sourceforge.pmd.lang.apex.rule.ApexRuleChainVisitor;
import net.sourceforge.pmd.util.CollectionUtil;
import apex.jorje.services.Version;
public class ApexLanguageModule extends BaseLanguageModule {
private static final String FIRST_EXTENSION = "cls";
private static final String[] REMAINING_EXTENSIONS = {"trigger"};
public static final String NAME = "Apex";
public static final String TERSE_NAME = "apex";
public static final String[] EXTENSIONS = { "cls", "trigger" };
public static final String[] EXTENSIONS = CollectionUtil.listOf(FIRST_EXTENSION, REMAINING_EXTENSIONS).toArray(new String[0]);
public ApexLanguageModule() {
super(NAME, null, TERSE_NAME, ApexRuleChainVisitor.class, EXTENSIONS);
super(NAME, null, TERSE_NAME, FIRST_EXTENSION, REMAINING_EXTENSIONS);
addVersion(String.valueOf((int) Version.CURRENT.getExternal()), new ApexHandler(), true);
}
}

View File

@ -7,8 +7,6 @@ package net.sourceforge.pmd.lang.apex.metrics;
import java.util.ArrayList;
import java.util.List;
import org.checkerframework.checker.nullness.qual.NonNull;
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
import net.sourceforge.pmd.lang.apex.ast.ASTUserClass;
import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface;
@ -136,7 +134,6 @@ public final class ApexMetrics {
}
@NonNull
public static List<ASTMethod> findOps(ASTUserClassOrInterface<?> node) {
List<ASTMethod> candidates = node.findChildrenOfType(ASTMethod.class);
List<ASTMethod> result = new ArrayList<>(candidates);

View File

@ -8,6 +8,7 @@ import java.util.Stack;
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
import net.sourceforge.pmd.lang.apex.ast.ASTUserClassOrInterface;
import net.sourceforge.pmd.lang.apex.ast.ASTUserEnum;
import net.sourceforge.pmd.lang.apex.ast.ASTUserTrigger;
import net.sourceforge.pmd.lang.apex.ast.ApexParserVisitorReducedAdapter;
@ -41,6 +42,12 @@ public class ApexMultifileVisitor extends ApexParserVisitorReducedAdapter {
}
@Override
public Object visit(ASTUserEnum node, Object data) {
return data; // ignore
}
@Override
public Object visit(ASTMethod node, Object data) {
stack.peek().addOperation(node.getQualifiedName().getOperation(), node.getSignature());

View File

@ -137,12 +137,8 @@ public abstract class AbstractApexRule extends AbstractRule
protected void visitAll(List<? extends Node> nodes, RuleContext ctx) {
for (Object element : nodes) {
if (element instanceof ASTUserClass) {
visit((ASTUserClass) element, ctx);
} else if (element instanceof ASTUserInterface) {
visit((ASTUserInterface) element, ctx);
} else if (element instanceof ASTUserTrigger) {
visit((ASTUserTrigger) element, ctx);
if (element instanceof ApexNode<?>) {
((ApexNode<?>) element).jjtAccept(this, ctx);
}
}
}

View File

@ -14,8 +14,14 @@ import net.sourceforge.pmd.lang.apex.ast.ApexNode;
import net.sourceforge.pmd.lang.apex.ast.ApexParserVisitor;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.rule.AbstractRuleChainVisitor;
import net.sourceforge.pmd.lang.rule.RuleChainVisitor;
import net.sourceforge.pmd.lang.rule.XPathRule;
/**
* @deprecated for removal with PMD 7. A language dependent rule chain visitor is not needed anymore.
* See {@link RuleChainVisitor}.
*/
@Deprecated
public class ApexRuleChainVisitor extends AbstractRuleChainVisitor {
@Override

View File

@ -129,13 +129,6 @@ public class StdCyclomaticComplexityRule extends AbstractApexRule {
@Override
public Object visit(ASTUserEnum node, Object data) {
entryStack.push(new Entry());
super.visit(node, data);
Entry classEntry = entryStack.pop();
if (classEntry.getComplexityAverage() >= reportLevel || classEntry.highestDecisionPoints >= reportLevel) {
addViolation(data, node, new String[] { "class", node.getImage(),
classEntry.getComplexityAverage() + "(Highest = " + classEntry.highestDecisionPoints + ')', });
}
return data;
}

View File

@ -0,0 +1,86 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.apex.rule;
import static org.junit.Assert.assertEquals;
import java.util.Collections;
import org.junit.Test;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.lang.apex.ast.ASTAnonymousClass;
import net.sourceforge.pmd.lang.apex.ast.ASTUserClass;
import net.sourceforge.pmd.lang.apex.ast.ASTUserEnum;
import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface;
import net.sourceforge.pmd.lang.apex.ast.ASTUserTrigger;
import net.sourceforge.pmd.lang.apex.ast.ApexNode;
import net.sourceforge.pmd.lang.apex.ast.ApexParserTestBase;
import apex.jorje.semantic.ast.compilation.Compilation;
public class AbstractApexRuleTest extends ApexParserTestBase {
@Test
public void shouldVisitTopLevelClass() {
run("class Foo { }");
}
@Test
public void shouldVisitTopLevelInterface() {
run("interface Foo { }");
}
@Test
public void shouldVisitTopLevelTrigger() {
run("trigger Foo on Account (before insert, before update) { }");
}
@Test
public void shouldVisitTopLevelEnum() {
run("enum Foo { }");
}
private void run(String code) {
ApexNode<Compilation> node = parse(code);
RuleContext ctx = new RuleContext();
ctx.setLanguageVersion(apex.getDefaultVersion());
TopLevelRule rule = new TopLevelRule();
rule.apply(Collections.singletonList(node), ctx);
assertEquals(1, ctx.getReport().size());
}
private static class TopLevelRule extends AbstractApexRule {
@Override
public Object visit(ASTUserClass node, Object data) {
addViolation(data, node);
return data;
}
@Override
public Object visit(ASTUserInterface node, Object data) {
addViolation(data, node);
return data;
}
@Override
public Object visit(ASTUserTrigger node, Object data) {
addViolation(data, node);
return data;
}
@Override
public Object visit(ASTUserEnum node, Object data) {
addViolation(data, node);
return data;
}
@Override
public Object visit(ASTAnonymousClass node, Object data) {
addViolation(data, node);
return data;
}
}
}

View File

@ -63,6 +63,14 @@ public class Foo {
]]></code>
</test-code>
<test-code>
<description>top-level enum all is well</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public enum FooEnum { }
]]></code>
</test-code>
<test-code>
<description>test class default is title case</description>
<expected-problems>1</expected-problems>
@ -121,6 +129,17 @@ public class Foo {
]]></code>
</test-code>
<test-code>
<description>top-level enum default is title case</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>The enum name 'fooEnum' doesn't match '[A-Z][a-zA-Z0-9_]*'</message>
</expected-messages>
<code><![CDATA[
public enum fooEnum { }
]]></code>
</test-code>
<test-code>
<description>custom test class pattern</description>
<rule-property name="testClassPattern">[a-zA-Z0-9_]+</rule-property>
@ -157,4 +176,22 @@ public class FOO_CLASS { }
public interface FOO_INTERFACE { }
]]></code>
</test-code>
<test-code>
<description>custom enum pattern</description>
<rule-property name="enumPattern">E[a-zA-Z0-9_]+</rule-property>
<expected-problems>0</expected-problems>
<code><![CDATA[
public enum EFOO_ENUM { }
]]></code>
</test-code>
<test-code>
<description>custom enum pattern</description>
<rule-property name="enumPattern">E[a-zA-Z0-9_]+</rule-property>
<expected-problems>1</expected-problems>
<code><![CDATA[
public enum FooEnum { }
]]></code>
</test-code>
</test-data>

View File

@ -97,6 +97,12 @@
<artifactId>ant</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.java.dev.javacc</groupId>
<artifactId>javacc</artifactId>
<scope>provided</scope> <!-- only needed for generating the parser via ant -->
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
@ -122,10 +128,7 @@
-->
<optional>true</optional>
</dependency>
<dependency>
<groupId>net.java.dev.javacc</groupId>
<artifactId>javacc</artifactId>
</dependency>
<dependency>
<groupId>net.sourceforge.saxon</groupId>
<artifactId>saxon</artifactId>

View File

@ -11,6 +11,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sourceforge.pmd.lang.internal.DefaultRulechainVisitor;
import net.sourceforge.pmd.util.CollectionUtil;
/**
* Created by christoferdutz on 21.09.14.
*/
@ -25,6 +28,12 @@ public abstract class BaseLanguageModule implements Language {
protected Map<String, LanguageVersion> versions;
protected LanguageVersion defaultVersion;
/**
* @deprecated Use the other constructor. It doesn't require a
* rulechain visitor class, but forces you to mention at least
* one file extension.
*/
@Deprecated
public BaseLanguageModule(String name, String shortName, String terseName, Class<?> ruleChainVisitorClass,
String... extensions) {
this.name = name;
@ -34,6 +43,18 @@ public abstract class BaseLanguageModule implements Language {
this.extensions = Arrays.asList(extensions);
}
public BaseLanguageModule(String name,
String shortName,
String terseName,
String firstExtension,
String... otherExtensions) {
this.name = name;
this.shortName = shortName;
this.terseName = terseName;
this.ruleChainVisitorClass = DefaultRulechainVisitor.class;
this.extensions = CollectionUtil.listOf(firstExtension, otherExtensions);
}
private void addVersion(String version, LanguageVersionHandler languageVersionHandler, boolean isDefault, String... versionAliases) {
if (versions == null) {
versions = new HashMap<>();
@ -177,4 +198,6 @@ public abstract class BaseLanguageModule implements Language {
public int compareTo(Language o) {
return getName().compareTo(o.getName());
}
}

View File

@ -77,7 +77,10 @@ public interface Language extends Comparable<Language> {
*
* @return The RuleChainVisitor class.
* @see net.sourceforge.pmd.lang.rule.RuleChainVisitor
*
* @deprecated Will be removed in PMD 7, avoid using this
*/
@Deprecated
Class<?> getRuleChainVisitorClass();
/**

View File

@ -71,7 +71,16 @@ public final class LanguageRegistry {
// TODO This is unnecessary, if the incomplete language modules have been removed.
List<Language> languages = new ArrayList<>();
for (Language language : getInstance().languages.values()) {
if (language.getRuleChainVisitorClass() != null) {
LanguageVersionHandler languageVersionHandler = language.getDefaultVersion().getLanguageVersionHandler();
boolean pmdSupported = false;
if (languageVersionHandler != null) {
ParserOptions defaultParserOptions = languageVersionHandler.getDefaultParserOptions();
Parser parser = languageVersionHandler.getParser(defaultParserOptions);
pmdSupported = parser.canParse();
}
if (pmdSupported) {
languages.add(language);
}
}

View File

@ -0,0 +1,42 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.internal;
import java.util.Collections;
import java.util.List;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.rule.AbstractRuleChainVisitor;
import net.sourceforge.pmd.lang.rule.RuleChainVisitor;
/**
* @deprecated See {@link RuleChainVisitor}
*/
@Deprecated
@InternalApi
public class DefaultRulechainVisitor extends AbstractRuleChainVisitor {
@Override
protected void visit(Rule rule, Node node, RuleContext ctx) {
rule.apply(Collections.singletonList(node), ctx);
}
@Override
protected void indexNodes(List<Node> nodes, RuleContext ctx) {
for (Node node : nodes) {
indexNodeRec(node);
}
}
protected void indexNodeRec(Node top) {
indexNode(top);
for (Node child : top.children()) {
indexNodeRec(child);
}
}
}

View File

@ -28,7 +28,10 @@ import net.sourceforge.pmd.lang.ast.Node;
* This is a base class for RuleChainVisitor implementations which extracts
* interesting nodes from an AST, and lets each Rule visit the nodes it has
* expressed interest in.
*
* @deprecated See {@link RuleChainVisitor}
*/
@Deprecated
public abstract class AbstractRuleChainVisitor implements RuleChainVisitor {
private static final Logger LOG = Logger.getLogger(AbstractRuleChainVisitor.class.getName());

View File

@ -9,12 +9,18 @@ import java.util.List;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.lang.BaseLanguageModule;
import net.sourceforge.pmd.lang.ast.Node;
/**
* The RuleChainVisitor understands how to visit an AST for a particular
* Language.
*
* @deprecated This interface will be removed. It's only used in internal
* code. Language implementors no longer need to register a rulechain
* visitor implementation in the {@link BaseLanguageModule} constructor.
*/
@Deprecated
public interface RuleChainVisitor {
/**
* Add the given rule to the visitor.

View File

@ -8,6 +8,7 @@ import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -187,6 +188,15 @@ public final class CollectionUtil {
return list;
}
@SafeVarargs
public static <T> List<T> listOf(T first, T... rest) {
// note: 7.0.x already has a better version of that
ArrayList<T> result = new ArrayList<>(rest.length + 1);
result.add(first);
Collections.addAll(result, rest);
return result;
}
/**
* Returns true if the objects are array instances and each of their

View File

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<ruleset name="6260"
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
<description>
This ruleset contains links to rules that are new in PMD v6.26.0
</description>
<rule ref="category/java/bestpractices.xml/UnusedAssignment" />
</ruleset>

View File

@ -13,7 +13,7 @@ public class Dummy2LanguageModule extends BaseLanguageModule {
public static final String TERSE_NAME = "dummy2";
public Dummy2LanguageModule() {
super(NAME, null, TERSE_NAME, null, "dummy2");
super(NAME, null, TERSE_NAME, "dummy2");
addVersion("1.0", new DummyLanguageModule.Handler(), true);
}
}

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