Merge branch 'main' into issue-4813

This commit is contained in:
Andreas Dangel 2024-10-22 20:55:38 +02:00
commit c95817a75d
No known key found for this signature in database
GPG Key ID: 93450DF2DF9A3FA3
27 changed files with 587 additions and 308 deletions

View File

@ -7820,6 +7820,33 @@
"contributions": [
"bug"
]
},
{
"login": "gudzpoz",
"name": "gudzpoz",
"avatar_url": "https://avatars.githubusercontent.com/u/14026120?v=4",
"profile": "https://kyo.iroiro.party/",
"contributions": [
"bug"
]
},
{
"login": "phansys",
"name": "Javier Spagnoletti",
"avatar_url": "https://avatars.githubusercontent.com/u/1231441?v=4",
"profile": "https://github.com/phansys",
"contributions": [
"bug"
]
},
{
"login": "Aryant-Tripathi",
"name": "Aryant Tripathi",
"avatar_url": "https://avatars.githubusercontent.com/u/60316716?v=4",
"profile": "https://github.com/Aryant-Tripathi",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,

View File

@ -3,6 +3,7 @@ GEM
specs:
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
base64 (0.2.0)
bigdecimal (3.1.8)
claide (1.1.0)
claide-plugins (0.9.2)
@ -13,7 +14,8 @@ GEM
concurrent-ruby (1.3.4)
cork (0.3.0)
colored2 (~> 3.1)
danger (9.5.0)
danger (9.5.1)
base64 (~> 0.2)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
colored2 (~> 3.1)
@ -24,12 +26,14 @@ GEM
kramdown (~> 2.3)
kramdown-parser-gfm (~> 1.0)
octokit (>= 4.0)
pstore (~> 0.1)
terminal-table (>= 1, < 4)
differ (0.1.2)
et-orbi (1.2.11)
tzinfo
faraday (2.11.0)
faraday (2.12.0)
faraday-net_http (>= 2.0, < 3.4)
json
logger
faraday-http-cache (2.5.1)
faraday (>= 0.8)
@ -41,19 +45,20 @@ GEM
git (1.19.1)
addressable (~> 2.8)
rchardet (~> 1.8)
json (2.7.2)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (5.5.1)
logger (1.6.0)
logger (1.6.1)
logger-colors (1.0.0)
nap (1.1.0)
net-http (0.4.1)
uri
nokogiri (1.16.7-x86_64-linux)
racc (~> 1.4)
octokit (9.1.0)
octokit (9.2.0)
faraday (>= 1, < 3)
sawyer (~> 0.9)
open4 (1.3.4)
@ -64,12 +69,12 @@ GEM
nokogiri (~> 1.13)
rufus-scheduler (~> 3.8)
slop (~> 4.9)
pstore (0.1.3)
public_suffix (6.0.1)
raabro (1.4.0)
racc (1.8.1)
rchardet (1.8.0)
rexml (3.3.6)
strscan
rexml (3.3.8)
rouge (4.4.0)
rufus-scheduler (3.9.1)
fugit (~> 1.1, >= 1.1.6)
@ -78,12 +83,11 @@ GEM
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
slop (4.10.1)
strscan (3.1.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
unicode-display_width (2.6.0)
uri (0.13.1)
PLATFORMS

View File

@ -11,10 +11,11 @@
- root-node-name: name of the root node without prefix (eg "TopLevel"), will be made to implement RootNode
See AntlrGeneratedParserBase
-->
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<property name="target-package-dir" value="${antlr4.outputDirectory}/net/sourceforge/pmd/lang/${lang-id}/ast"/>
<property name="stamp-file" value="${project.build.directory}/last-generated-timestamp" />
<property name="lang-ast-package" value="net.sourceforge.pmd.lang.${lang-id}.ast" />
@ -32,14 +33,100 @@
<property name="base-visitor-file" value="${target-package-dir}/${base-visitor-name}.java"/>
<property name="listener-name" value="${lang-name}Listener"/>
<property name="listener-file" value="${target-package-dir}/${visitor-name}.java"/>
<property name="listener-file" value="${target-package-dir}/${listener-name}.java"/>
<property name="base-listener-name" value="${lang-name}BaseListener"/>
<property name="base-listener-file" value="${target-package-dir}/${base-visitor-name}.java"/>
<property name="base-listener-file" value="${target-package-dir}/${base-listener-name}.java"/>
<property name="node-itf-name" value="${lang-name}Node"/>
<property name="base-class-name" value="Abstract${lang-name}Node"/>
<property name="lexer-name" value="${lang-name}Lexer"/>
<property name="lexer-file" value="${target-package-dir}/${lexer-name}.java"/>
<target name="check-up-to-date"
description="Checks the input files are up to date">
<uptodate property="processing-not-required" targetfile="${stamp-file}">
<srcfiles dir="${target-package-dir}" includes="*.java" />
<srcfiles file="${ant.file}" />
</uptodate>
<echo message="Up-to-date check: processing-not-required=${processing-not-required}" />
</target>
<target name="update-stamp-file" unless="processing-not-required">
<touch file="${stamp-file}" />
</target>
<target name="annotate-classes" description="Adds the @Generated annotation to all classes"
unless="processing-not-required">
<if>
<available file="${parser-file}"/>
<then>
<replace file="${parser-file}"
token="public class ${parser-name}"
value='@net.sourceforge.pmd.annotation.Generated("org.antlr.v4.Tool")${line.separator}
public class ${parser-name}'/>
<!-- Parse tree classes for each element -->
<replace file="${parser-file}"
token="public static class "
value='@net.sourceforge.pmd.annotation.Generated("org.antlr.v4.Tool")${line.separator}
public static class '/>
</then>
</if>
<if>
<available file="${visitor-file}"/>
<then>
<replace file="${visitor-file}"
token="public interface ${visitor-name}"
value='@net.sourceforge.pmd.annotation.Generated("org.antlr.v4.Tool")${line.separator}
public interface ${visitor-name}'/>
</then>
</if>
<if>
<available file="${base-visitor-file}"/>
<then>
<replace file="${base-visitor-file}"
token="public class ${base-visitor-name}"
value='@net.sourceforge.pmd.annotation.Generated("org.antlr.v4.Tool")${line.separator}
public class ${base-visitor-name}'/>
</then>
</if>
<if>
<available file="${listener-file}"/>
<then>
<replace file="${listener-file}"
token="public interface ${listener-name}"
value='@net.sourceforge.pmd.annotation.Generated("org.antlr.v4.Tool")${line.separator}
public interface ${listener-name}'/>
</then>
</if>
<if>
<available file="${base-listener-file}"/>
<then>
<replace file="${base-listener-file}"
token="public class ${base-listener-name}"
value='@net.sourceforge.pmd.annotation.Generated("org.antlr.v4.Tool")${line.separator}
public class ${base-listener-name}'/>
</then>
</if>
<if>
<available file="${lexer-file}"/>
<then>
<replace file="${lexer-file}"
token="public class ${lexer-name}"
value='@net.sourceforge.pmd.annotation.Generated("org.antlr.v4.Tool")${line.separator}
public class ${lexer-name}'/>
</then>
</if>
</target>
<condition property="rename-parser">
<and>
<not>
@ -72,7 +159,9 @@
tofile="${parser-file}"/>
</target>
<target name="cpd-language" description="Adapt Antlr sources for CPD-only languages">
<target name="cpd-language" depends="check-up-to-date, annotate-classes, cpd-language-processing, update-stamp-file"/>
<target name="cpd-language-processing" description="Adapt Antlr sources for CPD-only languages"
unless="processing-not-required">
<!-- We only need the Lexer file. -->
<delete file="${parser-file}"/>
<delete>
@ -83,7 +172,9 @@
</delete>
</target>
<target name="pmd-language" description="Adapt Antlr sources for PMD languages" depends="rename-parser">
<target name="pmd-language" depends="check-up-to-date, annotate-classes, pmd-language-processing, update-stamp-file"/>
<target name="pmd-language-processing" description="Adapt Antlr sources for PMD languages" depends="rename-parser"
unless="processing-not-required">
<!-- Adapt parser. -->
<replace file="${parser-file}">

File diff suppressed because it is too large Load Diff

View File

@ -17,23 +17,25 @@ This is a {{ site.pmd.release_type }} release.
### 🌟 Rule Changes
#### Renamed Rules
Several rules for unit testing have been renamed to better reflect their actual scope. Lots of them were called
after JUnit / JUnit 4, even when they applied to JUnit 5 and / or TestNG.
* {% rule java/bestpractices/UnitTestAssertionsShouldIncludeMessage %} (Java Best Practices) has been renamed from `JUnitAssertionsShouldIncludeMessage`.
* {% rule java/bestpractices/UnitTestContainsTooManyAsserts %} (Java Best Practices) has been renamed from `JUnitTestContainsTooManyAsserts`.
* {% rule java/bestpractices/UnitTestShouldIncludeAssert %} (Java Best Practices) has been renamed from `JUnitTestsShouldIncludeAssert`.
* {% rule java/bestpractices/UnitTestShouldUseAfterAnnotation %} (Java Best Practices) has been renamed from `JUnit4TestShouldUseAfterAnnotation`.
* {% rule java/bestpractices/UnitTestShouldUseBeforeAnnotation %} (Java Best Practices) has been renamed from `JUnit4TestShouldUseBeforeAnnotation`.
* {% rule java/bestpractices/UnitTestShouldUseTestAnnotation %} (Java Best Practices) has been renamed from `JUnit4TestShouldUseTestAnnotation`.
* Several rules for unit testing have been renamed to better reflect their actual scope. Lots of them were called
after JUnit / JUnit 4, even when they applied to JUnit 5 and / or TestNG.
* {% rule java/bestpractices/UnitTestAssertionsShouldIncludeMessage %} (Java Best Practices) has been renamed from `JUnitAssertionsShouldIncludeMessage`.
* {% rule java/bestpractices/UnitTestContainsTooManyAsserts %} (Java Best Practices) has been renamed from `JUnitTestContainsTooManyAsserts`.
* {% rule java/bestpractices/UnitTestShouldIncludeAssert %} (Java Best Practices) has been renamed from `JUnitTestsShouldIncludeAssert`.
* {% rule java/bestpractices/UnitTestShouldUseAfterAnnotation %} (Java Best Practices) has been renamed from `JUnit4TestShouldUseAfterAnnotation`.
* {% rule java/bestpractices/UnitTestShouldUseBeforeAnnotation %} (Java Best Practices) has been renamed from `JUnit4TestShouldUseBeforeAnnotation`.
* {% rule java/bestpractices/UnitTestShouldUseTestAnnotation %} (Java Best Practices) has been renamed from `JUnit4TestShouldUseTestAnnotation`.
The old rule names still work but are deprecated.
### 🐛 Fixed Issues
* java
* [#4532](https://github.com/pmd/pmd/issues/4532): \[java] Rule misnomer for JUnit* rules
* [#5261](https://github.com/pmd/pmd/issues/5261): \[java] Record patterns with empty deconstructor lists lead to NPE
* java-bestpractices
* [#4813](https://github.com/pmd/pmd/issues/4813): \[java] SwitchStmtsShouldHaveDefault false positive with pattern matching
* java-codestyle
* [#5253](https://github.com/pmd/pmd/issues/5253): \[java] BooleanGetMethodName: False-negatives with `Boolean` wrapper
* java-errorprone
* [#5067](https://github.com/pmd/pmd/issues/5067): \[java] CloseResource: False positive for FileSystems.getDefault()
@ -48,9 +50,14 @@ The old rule names still work but are deprecated.
### ✨ Merged pull requests
* [#4965](https://github.com/pmd/pmd/pull/4965): \[java] Rename JUnit rules with overly restrictive names - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
* [#5225](https://github.com/pmd/pmd/pull/5225): \[java] Fix #5067: CloseResource: False positive for FileSystems.getDefault() - [Lukas Gräf](https://github.com/lukasgraef) (@lukasgraef)
* [#4965](https://github.com/pmd/pmd/pull/4965): Fix #4532: \[java] Rename JUnit rules with overly restrictive names - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
* [#5225](https://github.com/pmd/pmd/pull/5225): Fix #5067: \[java] CloseResource: False positive for FileSystems.getDefault() - [Lukas Gräf](https://github.com/lukasgraef) (@lukasgraef)
* [#5241](https://github.com/pmd/pmd/pull/5241): Ignore javacc code in coverage report - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
* [#5258](https://github.com/pmd/pmd/pull/5258): Ignore generated antlr classes in coverage reports - [Juan Martín Sotuyo Dodero](https://github.com/jsotuyod) (@jsotuyod)
* [#5264](https://github.com/pmd/pmd/pull/5264): Fix #5261: \[java] Fix NPE with empty pattern list - [Clément Fournier](https://github.com/oowekyala) (@oowekyala)
* [#5269](https://github.com/pmd/pmd/pull/5269): Fix #5253: \[java] Support Boolean wrapper class for BooleanGetMethodName rule - [Aryant Tripathi](https://github.com/Aryant-Tripathi) (@Aryant-Tripathi)
* [#5275](https://github.com/pmd/pmd/pull/5275): Use plugin-classpath to simplify javacc-wrapper.xml - [Andreas Dangel](https://github.com/adangel) (@adangel)
* [#5278](https://github.com/pmd/pmd/pull/5278): \[java] CouplingBetweenObjects: improve violation message - [Andreas Dangel](https://github.com/adangel) (@adangel)
{% endtocmaker %}

View File

@ -25,9 +25,9 @@
It also uses the following maven properties:
- javacc.outputDirectory: Directory in which to root the generated package tree
- javacc.jar: JAR of JavaCC in the local maven repository
- plugin-classpath: The classpath of maven-antrun-plugin with javacc.jar dependency
Provided by maven via "<property name="plugin-classpath" refid="maven.plugin.classpath"/>"
- some properties of project.build
-->
<condition property="lang-name-camelcase" value="${lang-name}">
@ -40,8 +40,6 @@
<property name="target-package-dir" value="${javacc.outputDirectory}/net/sourceforge/pmd/lang/${lang-id}/ast" />
<property name="stamp-file" value="${project.build.directory}/last-generated-timestamp" />
<property name="javacc-home.path" value="${project.build.directory}/lib/javacc" />
<property name="lang-ast-package" value="net.sourceforge.pmd.lang.${lang-id}.ast" />
<property name="ast-api-package" value="net.sourceforge.pmd.lang.ast" />
<property name="ast-impl-package" value="${ast-api-package}.impl.javacc" />
@ -84,7 +82,7 @@
<target name="alljavacc"
description="Generates JavaCC sources and cleans them up"
depends="checkUpToDate,init,jjtree,jjtree-ersatz,javacc,adapt-generated,default-visitor,cleanup" />
depends="checkUpToDate,init,jjtree,jjtree-ersatz,javacc,adapt-generated,default-visitor" />
<target name="checkUpToDate"
description="Checks the input files are up to date">
@ -104,9 +102,6 @@
<target name="init" unless="javaccBuildNotRequired" description="Initialize build">
<mkdir dir="${javacc-home.path}" />
<copy file="${javacc.jar}" tofile="${javacc-home.path}/javacc.jar" />
<mkdir dir="${javacc.outputDirectory}" />
<touch file="${stamp-file}" />
<delete dir="${target-package-dir}" />
@ -117,11 +112,6 @@
</condition>
</target>
<target name="cleanup" unless="javaccBuildNotRequired">
<delete dir="${javacc-home.path}" />
</target>
<target name="jjtree" unless="jjtreeBuildNotRequired" description="Runs JJTree">
<!--
@ -130,7 +120,7 @@
-->
<java fork="true"
classname="jjtree"
classpath="${javacc-home.path}/javacc.jar">
classpath="${plugin-classpath}">
<sysproperty key="file.encoding" value="UTF-8" />
<arg value="-OUTPUT_DIRECTORY:${target-package-dir}" />
<arg value="-NODE_USES_PARSER:false" />
@ -148,7 +138,7 @@
<target name="javacc" depends="jjtree" unless="javaccBuildNotRequired">
<java fork="true"
classname="javacc"
classpath="${javacc-home.path}/javacc.jar">
classpath="${plugin-classpath}">
<sysproperty key="file.encoding" value="UTF-8" />
<arg value="-STATIC:false" />
<arg value="-USER_CHAR_STREAM:true" />

View File

@ -11,7 +11,7 @@ import java.lang.annotation.RetentionPolicy;
/**
* Marks a class as generated code, and therefore to be ignored for code coverage purposes.
*
* @since 7.6.0
* @since 7.7.0
*/
@Retention(RetentionPolicy.CLASS)
@Documented

View File

@ -34,10 +34,10 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="no-jjtree" value="true" /> <!-- This is a CPD module -->
<property name="lang-name" value="Cpp" />
<property name="lang-id" value="cpp" />
<property name="javacc.jar" value="${javacc.jar}" />
</ant>
</target>
</configuration>

View File

@ -1889,13 +1889,13 @@ void RecordPattern():
(Annotation())* ReferenceType() RecordStructurePattern()
}
void RecordStructurePattern() #void:
void RecordStructurePattern() #PatternList:
{}
{
"(" [ ComponentPatternList() ] ")"
}
void ComponentPatternList() #PatternList :
void ComponentPatternList() #void :
{}
{
ComponentPattern() ( "," ComponentPattern() )*

View File

@ -105,7 +105,7 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="javacc.jar" value="${javacc.jar}" />
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="lang-name" value="Java" />
<property name="lang-id" value="java" />
</ant>

View File

@ -52,9 +52,9 @@ public class CouplingBetweenObjectsRule extends AbstractJavaRule {
public Object visit(ASTCompilationUnit cu, Object data) {
super.visit(cu, data);
if (couplingCount > getProperty(THRESHOLD_DESCRIPTOR)) {
asCtx(data).addViolation(cu,
"A value of " + couplingCount + " may denote a high amount of coupling within the class");
Integer threshold = getProperty(THRESHOLD_DESCRIPTOR);
if (couplingCount > threshold) {
asCtx(data).addViolation(cu, couplingCount, threshold);
}
couplingCount = 0;

View File

@ -172,32 +172,33 @@ public class SomeJNIClass {
<rule name="BooleanGetMethodName"
language="java"
since="4.0"
message="A 'getX()' method which returns a boolean should be named 'isX()'"
message="A 'getX()' method which returns a boolean or Boolean should be named 'isX()'"
class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#booleangetmethodname">
<description>
Methods that return boolean results should be named as predicate statements to denote this.
I.e, 'isReady()', 'hasValues()', 'canCommit()', 'willFail()', etc. Avoid the use of the 'get'
prefix for these methods.
Methods that return boolean or Boolean results should be named as predicate statements to denote this.
I.e., 'isReady()', 'hasValues()', 'canCommit()', 'willFail()', etc. Avoid the use of the 'get' prefix for these methods.
</description>
<priority>4</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
<![CDATA[
//MethodDeclaration
[starts-with(@Name, 'get')]
[@Arity = 0 or $checkParameterizedMethods = true()]
[ PrimitiveType[@Kind = 'boolean'] and @Overridden = false() ]
[ (PrimitiveType[@Kind = 'boolean'] or ClassType[pmd-java:typeIs('java.lang.Boolean')]) and @Overridden = false() ]
]]>
</value>
</property>
<property name="checkParameterizedMethods" type="Boolean" description="Check parameterized methods" value="false"/>
</properties>
<example>
<![CDATA[
<![CDATA[
public boolean getFoo(); // bad
public Boolean getFoo(); // bad
public boolean isFoo(); // ok
public Boolean isFoo(); // ok
public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true
]]>
</example>

View File

@ -377,7 +377,7 @@ class Foo {
<rule name="CouplingBetweenObjects"
language="java"
since="1.04"
message="High amount of different objects as members denotes a high coupling"
message="A value of {0} may denote a high amount of coupling within the class (threshold: {1})"
class="net.sourceforge.pmd.lang.java.rule.design.CouplingBetweenObjectsRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_design.html#couplingbetweenobjects">
<description>

View File

@ -97,4 +97,14 @@ public class RecordPatterns {
System.out.println("String " + s);
}
}
record Empty(){}
void foo(Object o) {
if (o instanceof Empty
|| o instanceof Empty())
System.out.println("Empty " + o);
}
;
}

View File

@ -1,7 +1,7 @@
+- CompilationUnit[@PackageName = ""]
+- ClassDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "RecordPatterns", @CanonicalName = "RecordPatterns", @EffectiveVisibility = Visibility.V_PUBLIC, @Enum = false, @Final = false, @Interface = false, @Local = false, @Nested = false, @PackageName = "", @Record = false, @RegularClass = true, @RegularInterface = false, @SimpleName = "RecordPatterns", @Static = false, @TopLevel = true, @UnnamedToplevelClass = false, @Visibility = Visibility.V_PUBLIC]
+- ModifierList[@EffectiveModifiers = (JModifier.PUBLIC), @ExplicitModifiers = (JModifier.PUBLIC)]
+- ClassBody[@Empty = false, @Size = 18]
+- ClassBody[@Empty = false, @Size = 21]
+- RecordDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "RecordPatterns$Point", @CanonicalName = "RecordPatterns.Point", @EffectiveVisibility = Visibility.V_PACKAGE, @Enum = false, @Final = true, @Interface = false, @Local = false, @Nested = true, @PackageName = "", @Record = true, @RegularClass = false, @RegularInterface = false, @SimpleName = "Point", @Static = true, @TopLevel = false, @UnnamedToplevelClass = false, @Visibility = Visibility.V_PACKAGE]
| +- ModifierList[@EffectiveModifiers = (JModifier.STATIC, JModifier.FINAL), @ExplicitModifiers = ()]
| +- RecordComponentList[@Empty = false, @Size = 2, @Varargs = false]
@ -512,38 +512,73 @@
| +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "String ", @Empty = false, @Image = "\"String \"", @Length = 7, @LiteralText = "\"String \"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "s", @Name = "s", @ParenthesisDepth = 0, @Parenthesized = false]
+- MethodDeclaration[@Abstract = false, @Arity = 1, @EffectiveVisibility = Visibility.V_PACKAGE, @Final = false, @Name = "test4", @Overridden = false, @Static = false, @Varargs = false, @Visibility = Visibility.V_PACKAGE, @Void = true]
+- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
+- VoidType[]
+- FormalParameters[@Empty = false, @Size = 1]
| +- FormalParameter[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @Varargs = false, @Visibility = Visibility.V_LOCAL]
| +- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
| +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Box"]
| | +- TypeArguments[@Diamond = false, @Empty = false, @Size = 1]
| | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Box"]
| | +- TypeArguments[@Diamond = false, @Empty = false, @Size = 1]
| | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "String"]
| +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = true, @LambdaParameter = false, @LocalVariable = false, @Name = "bo", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Unnamed = false, @Visibility = Visibility.V_LOCAL]
+- Block[@Empty = false, @Size = 1, @containsComment = false]
+- IfStatement[@Else = false]
+- InfixExpression[@CompileTimeConstant = false, @Operator = BinaryOp.INSTANCEOF, @ParenthesisDepth = 0, @Parenthesized = false]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "bo", @Name = "bo", @ParenthesisDepth = 0, @Parenthesized = false]
| +- PatternExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| +- RecordPattern[]
| +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Box"]
| +- PatternList[@Empty = false, @Size = 1]
| +- RecordPattern[]
| +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Box"]
| +- PatternList[@Empty = false, @Size = 1]
| +- TypePattern[@EffectiveVisibility = Visibility.V_PACKAGE, @Visibility = Visibility.V_PACKAGE]
| +- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
| +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = true, @Unnamed = false, @Visibility = Visibility.V_LOCAL]
+- Block[@Empty = false, @Size = 1, @containsComment = false]
+- ExpressionStatement[]
+- MethodCall[@CompileTimeConstant = false, @Image = "println", @MethodName = "println", @ParenthesisDepth = 0, @Parenthesized = false]
+- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "out", @Name = "out", @ParenthesisDepth = 0, @Parenthesized = false]
| +- TypeExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "System"]
+- ArgumentList[@Empty = false, @Size = 1]
+- InfixExpression[@CompileTimeConstant = false, @Operator = BinaryOp.ADD, @ParenthesisDepth = 0, @Parenthesized = false]
+- StringLiteral[@CompileTimeConstant = true, @ConstValue = "String ", @Empty = false, @Image = "\"String \"", @Length = 7, @LiteralText = "\"String \"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
+- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "s", @Name = "s", @ParenthesisDepth = 0, @Parenthesized = false]
| +- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
| +- VoidType[]
| +- FormalParameters[@Empty = false, @Size = 1]
| | +- FormalParameter[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @Varargs = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
| | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Box"]
| | | +- TypeArguments[@Diamond = false, @Empty = false, @Size = 1]
| | | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Box"]
| | | +- TypeArguments[@Diamond = false, @Empty = false, @Size = 1]
| | | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "String"]
| | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = true, @LambdaParameter = false, @LocalVariable = false, @Name = "bo", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Unnamed = false, @Visibility = Visibility.V_LOCAL]
| +- Block[@Empty = false, @Size = 1, @containsComment = false]
| +- IfStatement[@Else = false]
| +- InfixExpression[@CompileTimeConstant = false, @Operator = BinaryOp.INSTANCEOF, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "bo", @Name = "bo", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- PatternExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- RecordPattern[]
| | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Box"]
| | +- PatternList[@Empty = false, @Size = 1]
| | +- RecordPattern[]
| | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Box"]
| | +- PatternList[@Empty = false, @Size = 1]
| | +- TypePattern[@EffectiveVisibility = Visibility.V_PACKAGE, @Visibility = Visibility.V_PACKAGE]
| | +- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
| | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = false, @Name = "s", @PatternBinding = true, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = true, @Unnamed = false, @Visibility = Visibility.V_LOCAL]
| +- Block[@Empty = false, @Size = 1, @containsComment = false]
| +- ExpressionStatement[]
| +- MethodCall[@CompileTimeConstant = false, @Image = "println", @MethodName = "println", @ParenthesisDepth = 0, @Parenthesized = false]
| +- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "out", @Name = "out", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TypeExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "System"]
| +- ArgumentList[@Empty = false, @Size = 1]
| +- InfixExpression[@CompileTimeConstant = false, @Operator = BinaryOp.ADD, @ParenthesisDepth = 0, @Parenthesized = false]
| +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "String ", @Empty = false, @Image = "\"String \"", @Length = 7, @LiteralText = "\"String \"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "s", @Name = "s", @ParenthesisDepth = 0, @Parenthesized = false]
+- RecordDeclaration[@Abstract = false, @Annotation = false, @Anonymous = false, @BinaryName = "RecordPatterns$Empty", @CanonicalName = "RecordPatterns.Empty", @EffectiveVisibility = Visibility.V_PACKAGE, @Enum = false, @Final = true, @Interface = false, @Local = false, @Nested = true, @PackageName = "", @Record = true, @RegularClass = false, @RegularInterface = false, @SimpleName = "Empty", @Static = true, @TopLevel = false, @UnnamedToplevelClass = false, @Visibility = Visibility.V_PACKAGE]
| +- ModifierList[@EffectiveModifiers = (JModifier.STATIC, JModifier.FINAL), @ExplicitModifiers = ()]
| +- RecordComponentList[@Empty = true, @Size = 0, @Varargs = false]
| +- RecordBody[@Empty = true, @Size = 0]
+- MethodDeclaration[@Abstract = false, @Arity = 1, @EffectiveVisibility = Visibility.V_PACKAGE, @Final = false, @Name = "foo", @Overridden = false, @Static = false, @Varargs = false, @Visibility = Visibility.V_PACKAGE, @Void = true]
| +- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
| +- VoidType[]
| +- FormalParameters[@Empty = false, @Size = 1]
| | +- FormalParameter[@EffectiveVisibility = Visibility.V_LOCAL, @Final = false, @Varargs = false, @Visibility = Visibility.V_LOCAL]
| | +- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
| | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Object"]
| | +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_LOCAL, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = false, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = true, @LambdaParameter = false, @LocalVariable = false, @Name = "o", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Unnamed = false, @Visibility = Visibility.V_LOCAL]
| +- Block[@Empty = false, @Size = 1, @containsComment = false]
| +- IfStatement[@Else = false]
| +- InfixExpression[@CompileTimeConstant = false, @Operator = BinaryOp.CONDITIONAL_OR, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- InfixExpression[@CompileTimeConstant = false, @Operator = BinaryOp.INSTANCEOF, @ParenthesisDepth = 0, @Parenthesized = false]
| | | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "o", @Name = "o", @ParenthesisDepth = 0, @Parenthesized = false]
| | | +- TypeExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Empty"]
| | +- InfixExpression[@CompileTimeConstant = false, @Operator = BinaryOp.INSTANCEOF, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "o", @Name = "o", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- PatternExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- RecordPattern[]
| | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "Empty"]
| | +- PatternList[@Empty = true, @Size = 0]
| +- ExpressionStatement[]
| +- MethodCall[@CompileTimeConstant = false, @Image = "println", @MethodName = "println", @ParenthesisDepth = 0, @Parenthesized = false]
| +- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "out", @Name = "out", @ParenthesisDepth = 0, @Parenthesized = false]
| | +- TypeExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| | +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "System"]
| +- ArgumentList[@Empty = false, @Size = 1]
| +- InfixExpression[@CompileTimeConstant = false, @Operator = BinaryOp.ADD, @ParenthesisDepth = 0, @Parenthesized = false]
| +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Empty ", @Empty = false, @Image = "\"Empty \"", @Length = 6, @LiteralText = "\"Empty \"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
| +- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "o", @Name = "o", @ParenthesisDepth = 0, @Parenthesized = false]
+- EmptyDeclaration[]

View File

@ -34,6 +34,18 @@ public class Foo {
]]></code>
</test-code>
<test-code>
<description>Should not match for boxed Boolean on multiple parameters by default (#5253)</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public Boolean getEnabled(boolean thisIsNotABean) {
return false;
}
}
]]></code>
</test-code>
<test-code>
<description>Should not match on methods annotated with @Override</description>
<expected-problems>0</expected-problems>
@ -60,4 +72,93 @@ public class Foo {
}
]]></code>
</test-code>
<test-code>
<description>Bad name with boxed Boolean (#5253)</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Foo {
public Boolean getEnabled() {
return true;
}
}
]]></code>
</test-code>
<test-code>
<description>Good name with boxed Boolean (#5253)</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public Boolean isEnabled() {
return false;
}
}
]]></code>
</test-code>
<test-code>
<description>Should not match for boxed Boolean on methods annotated with @Override (#5253)</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo implements Toggleable {
@Override
public Boolean getEnabled() {
return true;
}
}
interface Toggleable {
Boolean getEnabled(); // NOPMD
}
]]></code>
</test-code>
<test-code>
<description>Should match for boxed Boolean on multiple parameters when checkParameterizedMethods = true (#5253)</description>
<rule-property name="checkParameterizedMethods">true</rule-property>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Foo {
public Boolean getEnabled(boolean thisIsNotABean);
}
]]></code>
</test-code>
<test-code>
<description>Should match for boxed Boolean on multiple parameters when checkParameterizedMethods = true (#5253)</description>
<rule-property name="checkParameterizedMethods">true</rule-property>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Foo {
public Boolean getEnabled(boolean thisIsNotABean) {
return false;
}
}
]]></code>
</test-code>
<test-code>
<description>Custom Boolean type (#5253)</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
class Boolean { }
public class Foo {
public Boolean getEnabled() {
return null;
}
}
]]></code>
</test-code>
<test-code>
<description>Custom Boolean type with returning value (#5253)</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
class Boolean { }
public class Foo {
public Boolean getEnabled() { return false; }
}
]]></code>
</test-code>
</test-data>

View File

@ -9,6 +9,9 @@
<rule-property name="threshold">2</rule-property>
<expected-problems>1</expected-problems>
<expected-linenumbers>1</expected-linenumbers>
<expected-messages>
<message>A value of 3 may denote a high amount of coupling within the class (threshold: 2)</message>
</expected-messages>
<code><![CDATA[
import java.util.*;
public class Foo {
@ -51,6 +54,9 @@ public interface Foo {
<rule-property name="threshold">2</rule-property>
<expected-problems>1</expected-problems>
<expected-linenumbers>1</expected-linenumbers>
<expected-messages>
<message>A value of 3 may denote a high amount of coupling within the class (threshold: 2)</message>
</expected-messages>
<code><![CDATA[
import java.util.*;
public interface Foo {

View File

@ -47,10 +47,10 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="no-jjtree" value="true" /> <!-- This is a CPD module -->
<property name="lang-name" value="Ecmascript5" />
<property name="lang-id" value="ecmascript5" />
<property name="javacc.jar" value="${javacc.jar}" />
</ant>
</target>
</configuration>

View File

@ -40,7 +40,7 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="javacc.jar" value="${javacc.jar}" />
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="lang-name" value="Jsp" />
<property name="lang-id" value="jsp" />
</ant>

View File

@ -34,10 +34,10 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="no-jjtree" value="true" /> <!-- This is a CPD module -->
<property name="lang-name" value="Matlab" />
<property name="lang-id" value="matlab" />
<property name="javacc.jar" value="${javacc.jar}" />
</ant>
</target>
</configuration>

View File

@ -64,7 +64,7 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="javacc.jar" value="${javacc.jar}" />
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="lang-name" value="Modelica" />
<property name="lang-id" value="modelica" />
</ant>

View File

@ -34,10 +34,10 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="no-jjtree" value="true" /> <!-- This is a CPD module -->
<property name="lang-name" value="ObjectiveC" />
<property name="lang-id" value="objectivec" />
<property name="javacc.jar" value="${javacc.jar}" />
</ant>
</target>
</configuration>

View File

@ -40,7 +40,7 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="javacc.jar" value="${javacc.jar}" />
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="lang-name" value="PLSQL" />
<property name="lang-name-camelcase" value="Plsql" />
<property name="lang-id" value="plsql" />

View File

@ -34,10 +34,10 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="no-jjtree" value="true" /> <!-- This is a CPD module -->
<property name="lang-name" value="Python" />
<property name="lang-id" value="python" />
<property name="javacc.jar" value="${javacc.jar}" />
</ant>
</target>
</configuration>

View File

@ -43,7 +43,7 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="javacc.jar" value="${javacc.jar}" />
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="lang-name" value="Vtl" />
<property name="lang-id" value="velocity" />
</ant>

View File

@ -47,7 +47,7 @@
<configuration>
<target>
<ant antfile="${javacc.ant.wrapper}" target="alljavacc">
<property name="javacc.jar" value="${javacc.jar}" />
<property name="plugin-classpath" refid="maven.plugin.classpath"/>
<property name="lang-name" value="Vf" />
<property name="lang-id" value="visualforce" />
</ant>

30
pom.xml
View File

@ -94,7 +94,7 @@
<kotlin.compiler.jvmTarget>${maven.compiler.test.target}</kotlin.compiler.jvmTarget>
<kotlin.version>1.9.24</kotlin.version>
<kotest.version>5.9.1</kotest.version>
<junit5.version>5.8.2</junit5.version> <!-- needed by kotest -->
<junit5.version>5.11.2</junit5.version>
<dokka.version>1.9.20</dokka.version>
<javacc.version>5.0</javacc.version>
@ -118,10 +118,12 @@
<pmd.build-tools.version>27</pmd.build-tools.version>
<pmd-designer.version>7.2.0</pmd-designer.version>
<javacc.jar>${settings.localRepository}/net/java/dev/javacc/javacc/${javacc.version}/javacc-${javacc.version}.jar</javacc.jar>
<javacc.outputDirectory>${project.build.directory}/generated-sources/javacc</javacc.outputDirectory>
<javacc.ant.wrapper>${project.basedir}/../javacc-wrapper.xml</javacc.ant.wrapper>
<ant-contrib.version>1.0b3</ant-contrib.version>
<antlr4.outputDirectory>${project.build.directory}/generated-sources/antlr4</antlr4.outputDirectory>
<antlr4.ant.wrapper>${project.basedir}/../antlr4-wrapper.xml</antlr4.ant.wrapper>
@ -167,6 +169,11 @@
<artifactId>ant</artifactId>
<version>${ant.version}</version>
</dependency>
<dependency>
<groupId>ant-contrib</groupId>
<artifactId>ant-contrib</artifactId>
<version>${ant-contrib.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
@ -846,7 +853,7 @@
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>2.11.1</version>
<version>3.48.1</version>
</dependency>
<dependency>
<groupId>net.sf.saxon</groupId>
@ -903,7 +910,7 @@
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-reflect</artifactId>
<version>2.13.13</version>
<version>2.13.15</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
@ -963,7 +970,7 @@
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.10.2</version>
<version>1.11.2</version>
<scope>test</scope>
</dependency>
@ -1080,25 +1087,20 @@
<scope>test</scope>
</dependency>
<!-- transitive dependency through org.scalameta:trees_2.13
upgrade to 3.16.1 to fix CVE-2021-22569 A potential Denial of Service issue in protobuf-java
https://github.com/protocolbuffers/protobuf/security/advisories/GHSA-wrvw-hg22-4m67
upgrade to 3.16.3 to fix CVE-2022-3171 protobuf-java has a potential Denial of Service issue
https://github.com/advisories/GHSA-h4h5-3hr4-j3g2
-->
<!-- transitive dependency through org.scalameta:trees_2.13 -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.25.5</version>
<version>4.28.2</version>
</dependency>
<!-- Make sure to use the correct version the JUnit5 needs. E.g. 5.8.2 needs 1.8.2
<!-- Make sure to use the correct version the JUnit5 needs. E.g. 5.11.2 needs 1.11.2
Kotest might bring a wrong version.
see junit5.version -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<version>1.8.2</version>
<version>1.11.2</version>
<scope>test</scope>
</dependency>
</dependencies>