forked from phoedos/pmd
Merge branch 'master' into pmd/7.0.x
This commit is contained in:
@ -9,7 +9,9 @@ author: Tom Copeland <tom@infoether.org>
|
||||
|
||||
### Salesforce / Apex Language Module
|
||||
|
||||
* July 2019 - [Apex PMD | Static code analysis - Apex Hours](https://youtu.be/34PxAHtAavU)
|
||||
* March 2020 - [Helping Salesforce developers create readable and maintainable Apex code](https://gearset.com/blog/helping-sf-developers-create-readable-and-maintainable-apex-code)
|
||||
|
||||
* July 2019 - [Apex PMD | Static code analysis - Apex Hours](https://youtu.be/34PxAHtAavU)
|
||||
|
||||
* June 2019 - [Pluralsight](https://www.pluralsight.com/authors/don-robins) Course about leveraging PMD usage for Salesforce by [Robert Sösemann](https://github.com/rsoesemann) (Apex Language Module Contributor) [Play by Play: Automated Code Analysis in Salesforce - a Tools Deep-Dive](https://www.pluralsight.com/courses/play-by-play-automated-code-analysis-in-salesforce)
|
||||
|
||||
|
@ -57,7 +57,7 @@ The examples below won't repeat this taskdef element, as this is always required
|
||||
<tr>
|
||||
<td>rulesetfiles</td>
|
||||
<td>
|
||||
A comma delimited list of ruleset files ('rulesets/java/basic.xml,rulesets/java/design.xml').
|
||||
A comma delimited list of ruleset files ('rulesets/java/quickstart.xml,config/my-ruleset.xml').
|
||||
If you write your own ruleset files, you can put them on the classpath and plug them in here.
|
||||
</td>
|
||||
<td>Yes, unless the ruleset nested element is used</td>
|
||||
@ -153,9 +153,10 @@ configure multiple formatters.
|
||||
<dt>encoding</dt>
|
||||
<dd>Specifies the encoding to be used in the generated report (only honored when used with `toFile`). When rendering `toConsole` PMD will automatically detect the terminal's encoding and use it, unless the output is being redirected / piped, in which case `file.encoding` is used. See example below.</dd>
|
||||
<dt>linkPrefix</dt>
|
||||
<dd>Used for linking to online HTMLized source (like <a href="https://maven.apache.org/plugins/maven-pmd-plugin/xref/org/apache/maven/plugins/pmd/PmdReport.html">this</a>). See example below. Note, this only works with [maven-jxr-plugin](https://maven.apache.org/jxr/maven-jxr-plugin/index.html).</dd>
|
||||
<dd>Used for linking to online HTMLized source (like <a href="https://maven.apache.org/plugins/maven-pmd-plugin/xref/org/apache/maven/plugins/pmd/PmdReport.html">this</a>). See example below. Note, this only works with
|
||||
<a href="https://maven.apache.org/jxr/maven-jxr-plugin/index.html">maven-jxr-plugin</a>.</dd>
|
||||
<dt>linePrefix</dt>
|
||||
<dd>Used for linking to online HTMLized source (like <a href="https://maven.apache.org/plugins/maven-pmd-plugin/xref/org/apache/maven/plugins/pmd/PmdReport.html#L375">this</a>). See example below. Note, this only works with [maven-jxr-plugin](https://maven.apache.org/jxr/maven-jxr-plugin/index.html).</dd>
|
||||
<dd>Used for linking to online HTMLized source (like <a href="https://maven.apache.org/plugins/maven-pmd-plugin/xref/org/apache/maven/plugins/pmd/PmdReport.html#L375">this</a>). See example below. Note, this only works with <a href="https://maven.apache.org/jxr/maven-jxr-plugin/index.html">maven-jxr-plugin</a>.</dd>
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
@ -179,8 +180,8 @@ automatically and the latest language version is used.
|
||||
<target name="pmd">
|
||||
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask"/>
|
||||
<pmd shortFilenames="true">
|
||||
<ruleset>rulesets/java/design.xml</ruleset>
|
||||
<ruleset>java-basic</ruleset>
|
||||
<ruleset>rulesets/java/quickstart.xml</ruleset>
|
||||
<ruleset>config/my-ruleset.xml</ruleset>
|
||||
<fileset dir="/usr/local/j2sdk1.4.1_01/src/">
|
||||
<include name="java/lang/*.java"/>
|
||||
</fileset>
|
||||
@ -261,7 +262,7 @@ Then, after the end of the PMD task, do this:
|
||||
Running one ruleset to produce a HTML report (and printing the report to the console as well) using a file cache
|
||||
|
||||
<target name="pmd">
|
||||
<pmd rulesetfiles="java-imports" cacheLocation="build/pmd/pmd.cache">
|
||||
<pmd rulesetfiles="rulesets/java/quickstart.xml" cacheLocation="build/pmd/pmd.cache">
|
||||
<formatter type="html" toFile="pmd_report.html" toConsole="true"/>
|
||||
<fileset dir="C:\j2sdk1.4.1_01\src\java\lang\">
|
||||
<include name="**/*.java"/>
|
||||
@ -274,7 +275,7 @@ Running one ruleset to produce a HTML report (and printing the report to the con
|
||||
Running multiple rulesets to produce an XML report with the same analysis cache
|
||||
|
||||
<target name="pmd">
|
||||
<pmd rulesetfiles="rulesets/java/imports.xml,java-unusedcode" cacheLocation="build/pmd/pmd.cache">
|
||||
<pmd rulesetfiles="rulesets/java/quickstart.xml,config/my-ruleset.xml" cacheLocation="build/pmd/pmd.cache">
|
||||
<formatter type="xml" toFile="c:\pmd_report.xml"/>
|
||||
<fileset dir="C:\j2sdk1.4.1_01\src\java\lang\">
|
||||
<include name="**/*.java"/>
|
||||
@ -297,7 +298,7 @@ need to be configured when defining the task:
|
||||
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask" classpathref="pmd.classpath" />
|
||||
|
||||
<target name="pmd">
|
||||
<pmd rulesetfiles="rulesets/java/design.xml">
|
||||
<pmd rulesetfiles="rulesets/java/quickstart.xml">
|
||||
<formatter type="com.mycompany.MyRenderer" toFile="foo.html"/>
|
||||
<fileset dir="/path/to/java/src">
|
||||
<include name="**/*.java"/>
|
||||
@ -370,11 +371,13 @@ You can run pmd then with `ant pmd`.
|
||||
|
||||
pmd:
|
||||
[pmd] Using the normal ClassLoader
|
||||
[pmd] Using these rulesets: rulesets/java/imports.xml
|
||||
[pmd] Using rule DontImportJavaLang
|
||||
[pmd] Using rule UnusedImports
|
||||
[pmd] Using rule ImportFromSamePackage
|
||||
[pmd] Using rule DuplicateImports
|
||||
[pmd] Using these rulesets: rulesets/java/quickstart.xml
|
||||
[pmd] Using rule AvoidMessageDigestField
|
||||
[pmd] Using rule AvoidStringBufferField
|
||||
[pmd] Using rule AvoidUsingHardCodedIP
|
||||
[pmd] Using rule CheckResultSet
|
||||
[pmd] Using rule ConstantsInInterface
|
||||
...
|
||||
[pmd] Processing file /usr/local/java/src/java/lang/ref/Finalizer.java
|
||||
[pmd] Processing file /usr/local/java/src/java/lang/ref/FinalReference.java
|
||||
[pmd] Processing file /usr/local/java/src/java/lang/ref/PhantomReference.java
|
||||
@ -394,7 +397,7 @@ An HTML report with the "linkPrefix" and "linePrefix" properties:
|
||||
|
||||
<target name="pmd">
|
||||
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask"/>
|
||||
<pmd rulesetfiles="java-basic" shortFilenames="true">
|
||||
<pmd rulesetfiles="rulesets/java/quickstart.xml" shortFilenames="true">
|
||||
<formatter type="html" toFile="pmd_report.html">
|
||||
<param name="linkPrefix" value="https://maven.apache.org/plugins/maven-pmd-plugin/xref/"/>
|
||||
<param name="linePrefix" value="L"/>
|
||||
|
@ -94,9 +94,8 @@ To specify a ruleset, simply edit the previous configuration:
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<configuration>
|
||||
<rulesets>
|
||||
<ruleset>/rulesets/java/braces.xml</ruleset>
|
||||
<ruleset>/rulesets/java/naming.xml</ruleset>
|
||||
<ruleset>d:\rulesets\strings.xml</ruleset>
|
||||
<ruleset>/rulesets/java/quickstart.xml</ruleset>
|
||||
<ruleset>d:\rulesets\my-ruleset.xml</ruleset>
|
||||
<ruleset>http://localhost/design.xml</ruleset>
|
||||
</rulesets>
|
||||
</configuration>
|
||||
|
@ -96,6 +96,13 @@ should give more accurate results and especially fixes the problems with the usi
|
||||
* [#2255](https://github.com/pmd/pmd/issues/2255): \[java] InvalidLogMessageFormat false-positive for a lambda argument
|
||||
* java-performance
|
||||
* [#2275](https://github.com/pmd/pmd/issues/2275): \[java] AppendCharacterWithChar flags literals in an expression
|
||||
* plsql
|
||||
* [#2325](https://github.com/pmd/pmd/issues/2325): \[plsql] NullPointerException while running parsing test for CREATE TRIGGER
|
||||
* [#2327](https://github.com/pmd/pmd/pull/2327): \[plsql] Parsing of WHERE CURRENT OF
|
||||
* [#2328](https://github.com/pmd/pmd/issues/2328): \[plsql] Support XMLROOT
|
||||
* [#2331](https://github.com/pmd/pmd/pull/2331): \[plsql] Fix in Comment statement
|
||||
* [#2332](https://github.com/pmd/pmd/pull/2332): \[plsql] Fixed Execute Immediate statement parsing
|
||||
* [#2340](https://github.com/pmd/pmd/pull/2340): \[plsql] Fixed parsing / as divide or execute
|
||||
|
||||
### API Changes
|
||||
|
||||
@ -173,6 +180,59 @@ methods on {% jdoc apex::lang.apex.ast.ApexParserVisitor %} and its implementati
|
||||
* pmd-apex
|
||||
* {% jdoc apex::lang.apex.metrics.ApexMetrics %}, {% jdoc apex::lang.apex.metrics.ApexMetricsComputer %}
|
||||
|
||||
##### In ASTs (JSP)
|
||||
|
||||
As part of the changes we'd like to do to AST classes for 7.0.0, we would like to
|
||||
hide some methods and constructors that rule writers should not have access to.
|
||||
The following usages are now deprecated **in the JSP AST** (with other languages to come):
|
||||
|
||||
* Manual instantiation of nodes. **Constructors of node classes are deprecated** and
|
||||
marked {% jdoc core::annotation.InternalApi %}. Nodes should only be obtained from the parser,
|
||||
which for rules, means that they never need to instantiate node themselves.
|
||||
Those constructors will be made package private with 7.0.0.
|
||||
* **Subclassing of abstract node classes, or usage of their type**. The base classes are internal API
|
||||
and will be hidden in version 7.0.0. You should not couple your code to them.
|
||||
* In the meantime you should use interfaces like {% jdoc jsp::lang.jsp.ast.JspNode %} or
|
||||
{% jdoc core::lang.ast.Node %}, or the other published interfaces in this package,
|
||||
to refer to nodes generically.
|
||||
* Concrete node classes will **be made final** with 7.0.0.
|
||||
* Setters found in any node class or interface. **Rules should consider the AST immutable**.
|
||||
We will make those setters package private with 7.0.0.
|
||||
* The class {% jdoc jsp::lang.jsp.JspParser %} is deprecated and should not be used directly.
|
||||
Use {% jdoc !!core::lang.LanguageVersionHandler#getParser(ParserOptions) %} instead.
|
||||
|
||||
Please look at {% jdoc_package jsp::lang.jsp.ast %} to find out the full list of deprecations.
|
||||
|
||||
##### In ASTs (Velocity)
|
||||
|
||||
As part of the changes we'd like to do to AST classes for 7.0.0, we would like to
|
||||
hide some methods and constructors that rule writers should not have access to.
|
||||
The following usages are now deprecated **in the VM AST** (with other languages to come):
|
||||
|
||||
* Manual instantiation of nodes. **Constructors of node classes are deprecated** and
|
||||
marked {% jdoc core::annotation.InternalApi %}. Nodes should only be obtained from the parser,
|
||||
which for rules, means that they never need to instantiate node themselves.
|
||||
Those constructors will be made package private with 7.0.0.
|
||||
* **Subclassing of abstract node classes, or usage of their type**. The base classes are internal API
|
||||
and will be hidden in version 7.0.0. You should not couple your code to them.
|
||||
* In the meantime you should use interfaces like {% jdoc vm::lang.vm.ast.VmNode %} or
|
||||
{% jdoc core::lang.ast.Node %}, or the other published interfaces in this package,
|
||||
to refer to nodes generically.
|
||||
* Concrete node classes will **be made final** with 7.0.0.
|
||||
* Setters found in any node class or interface. **Rules should consider the AST immutable**.
|
||||
We will make those setters package private with 7.0.0.
|
||||
* The package {% jdoc_package vm::lang.vm.directive %} as well as the classes
|
||||
{% jdoc vm::lang.vm.util.DirectiveMapper %} and {% jdoc vm::lang.vm.util.LogUtil %} are deprecated
|
||||
for removal. They were only used internally during parsing.
|
||||
* The class {% jdoc vm::lang.vm.VmParser %} is deprecated and should not be used directly.
|
||||
Use {% jdoc !!core::lang.LanguageVersionHandler#getParser(ParserOptions) %} instead.
|
||||
|
||||
Please look at {% jdoc_package vm::lang.vm.ast %} to find out the full list of deprecations.
|
||||
|
||||
#### PLSQL AST
|
||||
|
||||
The production and node `ASTCursorBody` was unnecessary, not used and has been removed. Cursors have been already
|
||||
parsed as `ASTCursorSpecification`.
|
||||
|
||||
### External Contributions
|
||||
|
||||
@ -186,6 +246,16 @@ methods on {% jdoc apex::lang.apex.ast.ApexParserVisitor %} and its implementati
|
||||
* [#2297](https://github.com/pmd/pmd/pull/2297): \[apex] Cognitive complexity metrics - [Gwilym Kuiper](https://github.com/gwilymatgearset)
|
||||
* [#2317](https://github.com/pmd/pmd/pull/2317): \[apex] New Rule - Test Methods Must Be In Test Classes - [Brian Nørremark](https://github.com/noerremark)
|
||||
* [#2321](https://github.com/pmd/pmd/pull/2321): \[apex] Support switch statements correctly in Cognitive Complexity - [Gwilym Kuiper](https://github.com/gwilymatgearset)
|
||||
* [#2326](https://github.com/pmd/pmd/pull/2326): \[plsql] Added XML functions to parser: extract(xml), xml_root and fixed xml_forest - [Piotr Szymanski](https://github.com/szyman23)
|
||||
* [#2327](https://github.com/pmd/pmd/pull/2327): \[plsql] Parsing of WHERE CURRENT OF added - [Piotr Szymanski](https://github.com/szyman23)
|
||||
* [#2331](https://github.com/pmd/pmd/pull/2331): \[plsql] Fix in Comment statement - [Piotr Szymanski](https://github.com/szyman23)
|
||||
* [#2332](https://github.com/pmd/pmd/pull/2332): \[plsql] Fixed Execute Immediate statement parsing - [Piotr Szymanski](https://github.com/szyman23)
|
||||
* [#2338](https://github.com/pmd/pmd/pull/2338): \[cs] CPD: fixes in filtering of using directives - [Maikel Steneker](https://github.com/maikelsteneker)
|
||||
* [#2339](https://github.com/pmd/pmd/pull/2339): \[cs] CPD: Fixed CPD --ignore-usings option - [Maikel Steneker](https://github.com/maikelsteneker)
|
||||
* [#2340](https://github.com/pmd/pmd/pull/2340): \[plsql] fix for parsing / as divide or execute - [Piotr Szymanski](https://github.com/szyman23)
|
||||
* [#2342](https://github.com/pmd/pmd/pull/2342): \[xml] Update property used in example - [Piotrek Żygieło](https://github.com/pzygielo)
|
||||
* [#2344](https://github.com/pmd/pmd/pull/2344): \[doc] Update ruleset examples for ant - [Piotrek Żygieło](https://github.com/pzygielo)
|
||||
* [#2343](https://github.com/pmd/pmd/pull/2343): \[ci] Disable checking for snapshots in jcenter - [Piotrek Żygieło](https://github.com/pzygielo)
|
||||
|
||||
{% endtocmaker %}
|
||||
|
||||
|
@ -41,9 +41,9 @@ public abstract class BaseTokenFilter<T extends GenericToken> implements TokenFi
|
||||
currentToken = null;
|
||||
if (!unprocessedTokens.isEmpty()) {
|
||||
currentToken = unprocessedTokens.poll();
|
||||
return currentToken;
|
||||
} else {
|
||||
currentToken = (T) tokenManager.getNextToken();
|
||||
}
|
||||
currentToken = (T) tokenManager.getNextToken();
|
||||
while (!shouldStopProcessing(currentToken)) {
|
||||
analyzeToken(currentToken);
|
||||
analyzeTokens(currentToken, remainingTokens);
|
||||
@ -53,7 +53,11 @@ public abstract class BaseTokenFilter<T extends GenericToken> implements TokenFi
|
||||
return currentToken;
|
||||
}
|
||||
|
||||
currentToken = (T) tokenManager.getNextToken();
|
||||
if (!unprocessedTokens.isEmpty()) {
|
||||
currentToken = unprocessedTokens.poll();
|
||||
} else {
|
||||
currentToken = (T) tokenManager.getNextToken();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
|
@ -59,6 +59,7 @@ public class CsTokenizer extends AntlrTokenizer {
|
||||
private final boolean ignoreUsings;
|
||||
private boolean discardingUsings = false;
|
||||
private boolean discardingNL = false;
|
||||
private boolean discardCurrent = false;
|
||||
|
||||
CsTokenFilter(final AntlrTokenManager tokenManager, boolean ignoreUsings) {
|
||||
super(tokenManager);
|
||||
@ -72,15 +73,19 @@ public class CsTokenizer extends AntlrTokenizer {
|
||||
|
||||
@Override
|
||||
protected void analyzeTokens(final AntlrToken currentToken, final Iterable<AntlrToken> remainingTokens) {
|
||||
discardCurrent = false;
|
||||
skipUsingDirectives(currentToken, remainingTokens);
|
||||
}
|
||||
|
||||
private void skipUsingDirectives(final AntlrToken currentToken, final Iterable<AntlrToken> remainingTokens) {
|
||||
final int type = currentToken.getType();
|
||||
if (type == CSharpLexer.USING && isUsingDirective(remainingTokens)) {
|
||||
discardingUsings = true;
|
||||
} else if (type == CSharpLexer.SEMICOLON) {
|
||||
discardingUsings = false;
|
||||
if (ignoreUsings) {
|
||||
final int type = currentToken.getType();
|
||||
if (type == CSharpLexer.USING && isUsingDirective(remainingTokens)) {
|
||||
discardingUsings = true;
|
||||
} else if (type == CSharpLexer.SEMICOLON && discardingUsings) {
|
||||
discardingUsings = false;
|
||||
discardCurrent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,7 +153,7 @@ public class CsTokenizer extends AntlrTokenizer {
|
||||
|
||||
@Override
|
||||
protected boolean isLanguageSpecificDiscarding() {
|
||||
return discardingUsings || discardingNL;
|
||||
return discardingUsings || discardingNL || discardCurrent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +116,14 @@ public class CsTokenizerTest {
|
||||
assertEquals(8, tokens.getTokens().get(14).getBeginLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoNotIgnoreUsingDirectives() {
|
||||
tokenizer.setIgnoreUsings(false);
|
||||
tokenizer.tokenize(toSourceCode("using System.Text;\n"), tokens);
|
||||
assertEquals(6, tokens.size());
|
||||
assertEquals("using", tokens.getTokens().get(0).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoreUsingDirectives() {
|
||||
tokenizer.setIgnoreUsings(true);
|
||||
@ -125,6 +133,17 @@ public class CsTokenizerTest {
|
||||
assertEquals(TokenEntry.EOF, tokens.getTokens().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatementsAfterUsingDirectivesAreNotIgnored() {
|
||||
tokenizer.setIgnoreUsings(true);
|
||||
tokenizer.tokenize(toSourceCode(
|
||||
"using System;\n"
|
||||
+ "public class MyClass {\n"
|
||||
+ "}\n"),
|
||||
tokens);
|
||||
assertEquals(6, tokens.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsingStatementsAreNotIgnored() {
|
||||
tokenizer.setIgnoreUsings(true);
|
||||
|
@ -59,6 +59,8 @@ public interface ASTAnyTypeBodyDeclaration extends JavaNode {
|
||||
ANNOTATION,
|
||||
/** No child, {@link #getDeclarationNode()} will return null. */
|
||||
EMPTY,
|
||||
/** See {@link ASTRecordDeclaration}. */
|
||||
RECORD,
|
||||
/** See {@link ASTRecordConstructorDeclaration}. */
|
||||
RECORD_CONSTRUCTOR
|
||||
}
|
||||
|
@ -59,6 +59,9 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode implements Dim
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Note: this might be <code>null</code> in certain cases.
|
||||
*/
|
||||
public VariableNameDeclaration getNameDeclaration() {
|
||||
return nameDeclaration;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import static net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration.Declar
|
||||
import static net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration.DeclarationKind.INITIALIZER;
|
||||
import static net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration.DeclarationKind.INTERFACE;
|
||||
import static net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration.DeclarationKind.METHOD;
|
||||
import static net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration.DeclarationKind.RECORD;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
@ -72,6 +73,8 @@ abstract class AbstractTypeBodyDeclaration extends AbstractJavaNode implements A
|
||||
return ANNOTATION;
|
||||
} else if (node instanceof ASTEnumDeclaration) {
|
||||
return ENUM;
|
||||
} else if (node instanceof ASTRecordDeclaration) {
|
||||
return RECORD;
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Declaration node types should all be known");
|
||||
|
@ -60,6 +60,7 @@ public abstract class AbstractInefficientZeroCheck extends AbstractJavaRule {
|
||||
public Object visit(ASTVariableDeclaratorId node, Object data) {
|
||||
Node nameNode = node.getTypeNameNode();
|
||||
if (nameNode == null || nameNode instanceof ASTPrimitiveType
|
||||
|| node.getNameDeclaration() == null
|
||||
|| !appliesToClassName(node.getNameDeclaration().getTypeImage())) {
|
||||
return data;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ public abstract class AbstractPoorMethodCall extends AbstractJavaRule {
|
||||
*/
|
||||
@Override
|
||||
public Object visit(ASTVariableDeclaratorId node, Object data) {
|
||||
if (!targetTypename().equals(node.getNameDeclaration().getTypeImage())) {
|
||||
if (node.getNameDeclaration() == null || !targetTypename().equals(node.getNameDeclaration().getTypeImage())) {
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ public class MissingOverrideRule extends AbstractJavaRule {
|
||||
|
||||
@Override
|
||||
public Object visit(ASTMethodDeclaration node, Object data) {
|
||||
if (currentLookup.peek() == null) {
|
||||
if (currentLookup.isEmpty() || currentLookup.peek() == null) {
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,8 @@ public class InsufficientStringBufferDeclarationRule extends AbstractJavaRule {
|
||||
|
||||
@Override
|
||||
public Object visit(ASTVariableDeclaratorId node, Object data) {
|
||||
if (!TypeHelper.isExactlyAny(node.getNameDeclaration(), StringBuffer.class, StringBuilder.class)) {
|
||||
if (node.getNameDeclaration() == null
|
||||
|| !TypeHelper.isExactlyAny(node.getNameDeclaration(), StringBuffer.class, StringBuilder.class)) {
|
||||
return data;
|
||||
}
|
||||
Node rootNode = node;
|
||||
|
@ -18,7 +18,8 @@ public class StringToStringRule extends AbstractJavaRule {
|
||||
|
||||
@Override
|
||||
public Object visit(ASTVariableDeclaratorId node, Object data) {
|
||||
if (!TypeHelper.isExactlyAny(node.getNameDeclaration(), String.class)
|
||||
if (node.getNameDeclaration() == null
|
||||
|| !TypeHelper.isExactlyAny(node.getNameDeclaration(), String.class)
|
||||
&& !TypeHelper.isExactlyAny(node.getNameDeclaration(), String[].class)) {
|
||||
return data;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.symboltable;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTRecordComponent;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
|
||||
@ -91,7 +92,15 @@ public class VariableNameDeclaration extends AbstractNameDeclaration implements
|
||||
&& getAccessNodeParent().getFirstChildOfType(ASTType.class).getChild(0) instanceof ASTReferenceType;
|
||||
}
|
||||
|
||||
private boolean isRecordComponent() {
|
||||
return node.getParent() instanceof ASTRecordComponent;
|
||||
}
|
||||
|
||||
public AccessNode getAccessNodeParent() {
|
||||
if (isRecordComponent()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (node.getParent() instanceof ASTFormalParameter || node.getParent() instanceof ASTLambdaExpression) {
|
||||
return (AccessNode) node.getParent();
|
||||
}
|
||||
@ -103,6 +112,9 @@ public class VariableNameDeclaration extends AbstractNameDeclaration implements
|
||||
}
|
||||
|
||||
private TypeNode getTypeNode() {
|
||||
if (isRecordComponent()) {
|
||||
return (TypeNode) node.getParent().getFirstChildOfType(ASTType.class).getChild(0);
|
||||
}
|
||||
if (isPrimitiveType()) {
|
||||
return (TypeNode) getAccessNodeParent().getFirstChildOfType(ASTType.class).getChild(0);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.ParseException;
|
||||
import net.sourceforge.pmd.lang.java.JavaParsingHelper;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeBodyDeclaration.DeclarationKind;
|
||||
|
||||
/**
|
||||
* Tests new java14 preview features.
|
||||
@ -83,6 +84,9 @@ public class Java14PreviewTest {
|
||||
Assert.assertEquals("s", variable.getVariableName());
|
||||
Assert.assertTrue(variable.isPatternBinding());
|
||||
Assert.assertTrue(variable.isFinal());
|
||||
// Note: these variables are not part of the symbol table
|
||||
// See ScopeAndDeclarationFinder#visit(ASTVariableDeclaratorId, Object)
|
||||
Assert.assertNull(variable.getNameDeclaration());
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,6 +106,9 @@ public class Java14PreviewTest {
|
||||
Assert.assertEquals(2, components.size());
|
||||
Assert.assertEquals("x", components.get(0).getVarId().getImage());
|
||||
Assert.assertEquals("y", components.get(1).getVarId().getImage());
|
||||
Assert.assertNull(components.get(0).getVarId().getNameDeclaration().getAccessNodeParent());
|
||||
Assert.assertEquals(Integer.TYPE, components.get(0).getVarId().getNameDeclaration().getType());
|
||||
Assert.assertEquals("int", components.get(0).getVarId().getNameDeclaration().getTypeImage());
|
||||
}
|
||||
|
||||
@Test(expected = ParseException.class)
|
||||
@ -130,6 +137,10 @@ public class Java14PreviewTest {
|
||||
Assert.assertEquals(2, complex.getDeclarations().size());
|
||||
Assert.assertTrue(complex.getDeclarations().get(0).getChild(1) instanceof ASTConstructorDeclaration);
|
||||
Assert.assertTrue(complex.getDeclarations().get(1).getChild(0) instanceof ASTRecordDeclaration);
|
||||
Assert.assertTrue(complex.getParent() instanceof ASTClassOrInterfaceBodyDeclaration);
|
||||
ASTClassOrInterfaceBodyDeclaration complexParent = complex.getFirstParentOfType(ASTClassOrInterfaceBodyDeclaration.class);
|
||||
Assert.assertEquals(DeclarationKind.RECORD, complexParent.getKind());
|
||||
Assert.assertSame(complex, complexParent.getDeclarationNode());
|
||||
|
||||
ASTRecordDeclaration nested = recordDecls.get(1);
|
||||
Assert.assertEquals("Nested", nested.getSimpleName());
|
||||
|
@ -582,5 +582,18 @@
|
||||
</code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>EmptyStackException with record top level</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public record Point(int x, int y) {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Point p = new Point(1, 2);
|
||||
System.out.println("p = " + p);
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
<source-type>java 14-preview</source-type>
|
||||
</test-code>
|
||||
</test-data>
|
||||
|
@ -196,4 +196,22 @@ public class Foo {
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>Avoid NPE for pattern matching instanceof</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class PatternMatchingInstanceof {
|
||||
private String s = "other string";
|
||||
|
||||
public void test() {
|
||||
Object obj = "abc";
|
||||
if (obj instanceof String s) {
|
||||
System.out.println("a) obj == s: " + (obj == s)); // true
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
<source-type>java 14-preview</source-type>
|
||||
</test-code>
|
||||
</test-data>
|
||||
|
@ -120,17 +120,17 @@ public class Token implements GenericToken, java.io.Serializable]]></replacevalu
|
||||
|
||||
|
||||
<replaceregexp>
|
||||
<regexp pattern="class|interface" />
|
||||
<substitution expression="@Deprecated @net.sourceforge.pmd.annotation.InternalApi \0" />
|
||||
<regexp pattern="public (?:class|interface)" />
|
||||
<substitution expression="@Deprecated${line.separator}@net.sourceforge.pmd.annotation.InternalApi${line.separator}\0" />
|
||||
<fileset dir="${target}/net/sourceforge/pmd/lang/jsp/ast">
|
||||
<exclude name="AST*.java" />
|
||||
<exclude name="ParseException.java" />
|
||||
</fileset>
|
||||
</replaceregexp>
|
||||
|
||||
<replaceregexp>
|
||||
<regexp pattern="public class ParseException " />
|
||||
<substitution expression=" /** @deprecated Use superclass {@link net.sourceforge.pmd.lang.ast.ParseException} */
|
||||
@Deprecated @net.sourceforge.pmd.annotation.InternalApi \0" />
|
||||
<regexp pattern="(?m)\*/\s+(public class ParseException )" />
|
||||
<substitution expression="*${line.separator} * @deprecated Use superclass {@link net.sourceforge.pmd.lang.ast.ParseException}${line.separator} */${line.separator}@Deprecated${line.separator}@net.sourceforge.pmd.annotation.InternalApi${line.separator}\1" />
|
||||
<fileset file="${target}/net/sourceforge/pmd/lang/jsp/ast/ParseException.java"/>
|
||||
</replaceregexp>
|
||||
</target>
|
||||
|
@ -6,7 +6,9 @@ package net.sourceforge.pmd.lang.jsp;
|
||||
|
||||
import java.io.Reader;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.AbstractParser;
|
||||
import net.sourceforge.pmd.lang.LanguageVersionHandler;
|
||||
import net.sourceforge.pmd.lang.ParserOptions;
|
||||
import net.sourceforge.pmd.lang.TokenManager;
|
||||
import net.sourceforge.pmd.lang.ast.AbstractTokenManager;
|
||||
@ -16,7 +18,11 @@ import net.sourceforge.pmd.lang.ast.impl.javacc.CharStreamFactory;
|
||||
|
||||
/**
|
||||
* Adapter for the JspParser.
|
||||
*
|
||||
* @deprecated This is internal API, use {@link LanguageVersionHandler#getParser(ParserOptions)}.
|
||||
*/
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public class JspParser extends AbstractParser {
|
||||
|
||||
public JspParser(ParserOptions parserOptions) {
|
||||
|
@ -1,33 +1,33 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
/* Generated By:JJTree: Do not edit this line. ASTAttribute.java */
|
||||
|
||||
package net.sourceforge.pmd.lang.jsp.ast;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
public class ASTAttribute extends AbstractJspNode {
|
||||
|
||||
private String name;
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTAttribute(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTAttribute(JspParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* The name to set.
|
||||
*/
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
@ -59,9 +59,6 @@ public class ASTAttribute extends AbstractJspNode {
|
||||
return colonIndex >= 0 ? name.substring(colonIndex + 1) : name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept the visitor. *
|
||||
*/
|
||||
@Override
|
||||
public Object jjtAccept(JspParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
|
@ -1,22 +1,24 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
/* Generated By:JJTree: Do not edit this line. ASTAttributeValue.java */
|
||||
|
||||
package net.sourceforge.pmd.lang.jsp.ast;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
public class ASTAttributeValue extends AbstractJspNode {
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTAttributeValue(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTAttributeValue(JspParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept the visitor. *
|
||||
*/
|
||||
@Override
|
||||
public Object jjtAccept(JspParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
|
@ -1,22 +1,24 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
/* Generated By:JJTree: Do not edit this line. ASTCData.java */
|
||||
|
||||
package net.sourceforge.pmd.lang.jsp.ast;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
public class ASTCData extends AbstractJspNode {
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTCData(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTCData(JspParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept the visitor. *
|
||||
*/
|
||||
@Override
|
||||
public Object jjtAccept(JspParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
|
@ -1,22 +1,24 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
/* Generated By:JJTree: Do not edit this line. ASTCommentTag.java */
|
||||
|
||||
package net.sourceforge.pmd.lang.jsp.ast;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
public class ASTCommentTag extends AbstractJspNode {
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTCommentTag(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTCommentTag(JspParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept the visitor. *
|
||||
*/
|
||||
@Override
|
||||
public Object jjtAccept(JspParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
|
@ -1,24 +1,25 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
/* Generated By:JJTree: Do not edit this line. ASTCompilationUnit.java */
|
||||
|
||||
package net.sourceforge.pmd.lang.jsp.ast;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.ast.RootNode;
|
||||
|
||||
public class ASTCompilationUnit extends AbstractJspNode implements RootNode {
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTCompilationUnit(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTCompilationUnit(JspParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept the visitor. *
|
||||
*/
|
||||
@Override
|
||||
public Object jjtAccept(JspParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
|
@ -1,22 +1,24 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
/* Generated By:JJTree: Do not edit this line. ASTContent.java */
|
||||
|
||||
package net.sourceforge.pmd.lang.jsp.ast;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
public class ASTContent extends AbstractJspNode {
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTContent(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTContent(JspParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept the visitor. *
|
||||
*/
|
||||
@Override
|
||||
public Object jjtAccept(JspParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
|
@ -1,40 +1,37 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
/* Generated By:JJTree: Do not edit this line. ASTDeclaration.java */
|
||||
|
||||
package net.sourceforge.pmd.lang.jsp.ast;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
public class ASTDeclaration extends AbstractJspNode {
|
||||
|
||||
private String name;
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTDeclaration(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTDeclaration(JspParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* The name to set.
|
||||
*/
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept the visitor. *
|
||||
*/
|
||||
@Override
|
||||
public Object jjtAccept(JspParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
|
@ -1,10 +1,11 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
/* Generated By:JJTree: Do not edit this line. ASTDoctypeDeclaration.java */
|
||||
|
||||
package net.sourceforge.pmd.lang.jsp.ast;
|
||||
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
|
||||
public class ASTDoctypeDeclaration extends AbstractJspNode {
|
||||
|
||||
/**
|
||||
@ -12,32 +13,28 @@ public class ASTDoctypeDeclaration extends AbstractJspNode {
|
||||
*/
|
||||
private String name;
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTDoctypeDeclaration(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public ASTDoctypeDeclaration(JspParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* The name to set.
|
||||
*/
|
||||
@InternalApi
|
||||
@Deprecated
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept the visitor. *
|
||||
*/
|
||||
@Override
|
||||
public Object jjtAccept(JspParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user