Merge branch 'pmd/7.0.x' into pmd7-replace-commons-io
This commit is contained in:
@@ -6639,6 +6639,42 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lukelukes",
|
||||
"name": "lukelukes",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/45536418?v=4",
|
||||
"profile": "https://github.com/lukelukes",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "vibhory2j",
|
||||
"name": "Vibhor Goyal",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15845016?v=4",
|
||||
"profile": "https://github.com/vibhory2j",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Ramel0921",
|
||||
"name": "Ramel0921",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/104978096?v=4",
|
||||
"profile": "https://github.com/Ramel0921",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "flyhard",
|
||||
"name": "Per Abich",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/409466?v=4",
|
||||
"profile": "https://github.com/flyhard",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
@@ -14,5 +14,11 @@ last_updated: April 2022 (6.45.0)
|
||||
|
||||
The HTML language module uses [jsoup](https://jsoup.org/) for parsing.
|
||||
|
||||
XPath rules are supported, but the DOM is not a typical XML/XPath DOM. E.g.
|
||||
text nodes are normal nodes. This might change in the future.
|
||||
XPath 2.0 rules are supported, but the DOM is not always a typical XML/XPath DOM.
|
||||
In the Designer, text nodes appear as nodes with name "#text", but they can
|
||||
be selected as usual using `text()`.
|
||||
|
||||
XML Namespaces are not supported. The local name of attributes include the prefix,
|
||||
so that you have to select attributes by e.g. `//*[@*[local-name() = 'if:true']]`.
|
||||
|
||||
Only XPath 1.0 rules are not supported.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -76,14 +76,14 @@ The tool comes with a rather extensive help text, simply running with `--help`!
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--file-list"
|
||||
option_arg="filepath"
|
||||
description="Path to file containing a comma delimited list of files to analyze.
|
||||
description="Path to file containing a list of files to analyze, one path per line.
|
||||
If this is given, then you don't need to provide `--dir`."
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--force-language"
|
||||
option_arg="lang"
|
||||
description="Force a language to be used for all input files, irrespective of
|
||||
filenames. When using this option, the automatic language selection
|
||||
by extension is disabled and all files are tried to be parsed with
|
||||
file names. When using this option, the automatic language selection
|
||||
by extension is disabled and PMD tries to parse all files with
|
||||
the given language `<lang>`. Parsing errors are ignored and unparsable files
|
||||
are skipped.
|
||||
|
||||
@@ -92,9 +92,9 @@ The tool comes with a rather extensive help text, simply running with `--help`!
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--ignore-list"
|
||||
option_arg="filepath"
|
||||
description="Path to file containing a comma delimited list of files to ignore.
|
||||
description="Path to file containing a list of files to ignore, one path per line.
|
||||
This option can be combined with `--dir` and `--file-list`.
|
||||
This ignore list takes precedence over any files in the filelist."
|
||||
This ignore list takes precedence over any files in the file-list."
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--help,-h,-H"
|
||||
description="Display help on usage."
|
||||
|
||||
@@ -112,9 +112,9 @@ Novice as much as advanced readers may want to [read on on Refactoring Guru](htt
|
||||
languages="Java"
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--ignore-annotations"
|
||||
description="Ignore language annotations when comparing text"
|
||||
description="Ignore language annotations (Java) or attributes (C#) when comparing text"
|
||||
default="false"
|
||||
languages="Java"
|
||||
languages="C#, Java"
|
||||
%}
|
||||
{% include custom/cli_option_row.html options="--ignore-literal-sequences"
|
||||
description="Ignore sequences of literals (common e.g. in list initializers)"
|
||||
|
||||
@@ -19,15 +19,63 @@ This is a {{ site.pmd.release_type }} release.
|
||||
|
||||
### New and noteworthy
|
||||
|
||||
#### CLI improvements
|
||||
|
||||
The PMD CLI now allows repeating the `--dir` (`-d`) and `--rulesets` (`-R`) options,
|
||||
as well as providing several space-separated arguments to either of them. For instance:
|
||||
```shell
|
||||
pmd -d src/main/java src/test/java -R rset1.xml -R rset2.xml
|
||||
```
|
||||
This also allows globs to be used on the CLI if your shell supports shell expansion.
|
||||
For instance, the above can be written
|
||||
```shell
|
||||
pmd -d src/*/java -R rset*.xml
|
||||
```
|
||||
Please use theses new forms instead of using comma-separated lists as argument to these options.
|
||||
|
||||
#### C# Improvements
|
||||
|
||||
When executing CPD on C# sources, the option `--ignore-annotations` is now supported as well.
|
||||
It ignores C# attributes when detecting duplicated code. This option can also be enabled via
|
||||
the CPD GUI. See [#3974](https://github.com/pmd/pmd/pull/3974) for details.
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* core
|
||||
* [#3942](https://github.com/pmd/pmd/issues/3942): \[core] common-io path traversal vulnerability (CVE-2021-29425)
|
||||
* cli
|
||||
* [#1445](https://github.com/pmd/pmd/issues/1445): \[core] Allow CLI to take globs as parameters
|
||||
* cs (c#)
|
||||
* [#3974](https://github.com/pmd/pmd/pull/3974): \[cs] Add option to ignore C# attributes (annotations)
|
||||
* go
|
||||
* [#2752](https://github.com/pmd/pmd/issues/2752): \[go] Error parsing unicode values
|
||||
* html
|
||||
* [#3955](https://github.com/pmd/pmd/pull/3955): \[html] Improvements for handling text and comment nodes
|
||||
* java
|
||||
* [#3423](https://github.com/pmd/pmd/issues/3423): \[java] Error processing identifiers with Unicode
|
||||
* java-bestpractices
|
||||
* [#3954](https://github.com/pmd/pmd/issues/3954): \[java] NPE in UseCollectionIsEmptyRule when .size() is called in a record
|
||||
* java-design
|
||||
* [#3874](https://github.com/pmd/pmd/issues/3874): \[java] ImmutableField reports fields annotated with @Autowired (Spring) and @Mock (Mockito)
|
||||
* javascript
|
||||
* [#3948](https://github.com/pmd/pmd/issues/3948): \[js] Invalid operator error for method property in object literal
|
||||
* [#2605](https://github.com/pmd/pmd/issues/2605): \[js] Support unicode characters
|
||||
* [#3948](https://github.com/pmd/pmd/issues/3948): \[js] Invalid operator error for method property in object literal
|
||||
* python
|
||||
* [#2604](https://github.com/pmd/pmd/issues/2604): \[python] Support unicode identifiers
|
||||
|
||||
### API Changes
|
||||
|
||||
#### Deprecated API
|
||||
|
||||
- {% jdoc core::PMDConfiguration#getInputPaths() %} and
|
||||
{% jdoc core::PMDConfiguration#setInputPaths(java.lang.String) %} are now deprecated.
|
||||
A new set of methods have been added, which use lists and do not rely on comma splitting.
|
||||
|
||||
### External Contributions
|
||||
|
||||
* [#3961](https://github.com/pmd/pmd/pull/3961): \[java] Fix #3954 - NPE in UseCollectionIsEmptyRule with record - [@flyhard](https://github.com/flyhard)
|
||||
* [#3964](https://github.com/pmd/pmd/pull/3964): \[java] Fix #3874 - ImmutableField: fix mockito/spring false positives - [@lukelukes](https://github.com/lukelukes)
|
||||
* [#3974](https://github.com/pmd/pmd/pull/3974): \[cs] Add option to ignore C# attributes (annotations) - [@maikelsteneker](https://github.com/maikelsteneker)
|
||||
|
||||
{% endtocmaker %}
|
||||
|
||||
|
||||
@@ -8,10 +8,12 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
@@ -104,7 +106,7 @@ public class PMDConfiguration extends AbstractConfiguration {
|
||||
// Rule and source file options
|
||||
private List<String> ruleSets = new ArrayList<>();
|
||||
private RulePriority minimumPriority = RulePriority.LOW;
|
||||
private String inputPaths;
|
||||
private List<String> inputPaths = new ArrayList<>();
|
||||
private String inputUri;
|
||||
private String inputFilePath;
|
||||
private String ignoreFilePath;
|
||||
@@ -435,19 +437,54 @@ public class PMDConfiguration extends AbstractConfiguration {
|
||||
* Get the comma separated list of input paths to process for source files.
|
||||
*
|
||||
* @return A comma separated list.
|
||||
*
|
||||
* @deprecated Use {@link #getAllInputPaths()}
|
||||
*/
|
||||
@Deprecated
|
||||
public String getInputPaths() {
|
||||
return inputPaths;
|
||||
return inputPaths.isEmpty() ? null : StringUtils.join(inputPaths, ",");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable list.
|
||||
*
|
||||
* @throws NullPointerException If the parameter is null
|
||||
*/
|
||||
public List<String> getAllInputPaths() {
|
||||
return Collections.unmodifiableList(inputPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the comma separated list of input paths to process for source files.
|
||||
*
|
||||
* @param inputPaths
|
||||
* The comma separated list.
|
||||
* @param inputPaths The comma separated list.
|
||||
*
|
||||
* @throws NullPointerException If the parameter is null
|
||||
* @deprecated Use {@link #setInputPaths(List)} or {@link #addInputPath(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setInputPaths(String inputPaths) {
|
||||
this.inputPaths = inputPaths;
|
||||
List<String> paths = new ArrayList<>();
|
||||
Collections.addAll(paths, inputPaths.split(","));
|
||||
this.inputPaths = paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the input paths to the given list of paths.
|
||||
* @throws NullPointerException If the parameter is null
|
||||
*/
|
||||
public void setInputPaths(List<String> inputPaths) {
|
||||
this.inputPaths = new ArrayList<>(inputPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an input path. It is not split on commas.
|
||||
*
|
||||
* @throws NullPointerException If the parameter is null
|
||||
*/
|
||||
public void addInputPath(String inputPath) {
|
||||
Objects.requireNonNull(inputPath);
|
||||
this.inputPaths.add(inputPath);
|
||||
}
|
||||
|
||||
public String getInputFilePath() {
|
||||
@@ -541,7 +578,7 @@ public class PMDConfiguration extends AbstractConfiguration {
|
||||
Renderer renderer = RendererFactory.createRenderer(reportFormat, reportProperties);
|
||||
renderer.setShowSuppressedViolations(showSuppressedViolations);
|
||||
if (reportShortNames && inputPaths != null) {
|
||||
renderer.setUseShortNames(Arrays.asList(inputPaths.split(",")));
|
||||
renderer.setUseShortNames(Collections.unmodifiableList(new ArrayList<>(inputPaths)));
|
||||
}
|
||||
if (withReportWriter) {
|
||||
renderer.setReportFile(reportFile);
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import net.sourceforge.pmd.PMD;
|
||||
@@ -32,20 +33,44 @@ import com.beust.jcommander.validators.PositiveInteger;
|
||||
@InternalApi
|
||||
public class PMDParameters {
|
||||
|
||||
@Parameter(names = { "--rulesets", "-rulesets", "-R" }, description = "Comma separated list of ruleset names to use.",
|
||||
required = true)
|
||||
private String rulesets;
|
||||
@Parameter(names = { "--rulesets", "-rulesets", "-R" },
|
||||
description = "Path to a ruleset xml file. "
|
||||
+ "The path may reference a resource on the classpath of the application, be a local file system path, or a URL. "
|
||||
+ "The option can be repeated, and multiple arguments can be provided to a single occurrence of the option.",
|
||||
required = true,
|
||||
variableArity = true)
|
||||
private List<String> rulesets;
|
||||
|
||||
@Parameter(names = { "--uri", "-uri", "-u" }, description = "Database URI for sources.")
|
||||
@Parameter(names = { "--uri", "-uri", "-u" },
|
||||
description = "Database URI for sources. "
|
||||
+ "One of --dir, --file-list or --uri must be provided. "
|
||||
)
|
||||
private String uri;
|
||||
|
||||
@Parameter(names = { "--dir", "-dir", "-d" }, description = "Root directory for sources.")
|
||||
private String sourceDir;
|
||||
@Parameter(names = { "--dir", "-dir", "-d" },
|
||||
description = "Path to a source file, or directory containing source files to analyze. "
|
||||
// About the following line:
|
||||
// In PMD 6, this is only the case for files found in directories. If you
|
||||
// specify a file directly, and it is unknown, then the Java parser is used.
|
||||
+ "Note that a file is only effectively added if it matches a language known by PMD. "
|
||||
+ "Zip and Jar files are also supported, if they are specified directly "
|
||||
+ "(archive files found while exploring a directory are not recursively expanded). "
|
||||
+ "This option can be repeated, and multiple arguments can be provided to a single occurrence of the option. "
|
||||
+ "One of --dir, --file-list or --uri must be provided. ",
|
||||
variableArity = true)
|
||||
private List<String> inputPaths = new ArrayList<>();
|
||||
|
||||
@Parameter(names = { "--file-list", "-filelist" }, description = "Path to a file containing a list of files to analyze.")
|
||||
@Parameter(names = { "--file-list", "-filelist" },
|
||||
description =
|
||||
"Path to a file containing a list of files to analyze, one path per line. "
|
||||
+ "One of --dir, --file-list or --uri must be provided. "
|
||||
)
|
||||
private String fileListPath;
|
||||
|
||||
@Parameter(names = { "--ignore-list", "-ignorelist" }, description = "Path to a file containing a list of files to ignore.")
|
||||
@Parameter(names = { "--ignore-list", "-ignorelist" },
|
||||
description = "Path to a file containing a list of files to exclude from the analysis, one path per line. "
|
||||
+ "This option can be combined with --dir and --file-list. "
|
||||
)
|
||||
private String ignoreListPath;
|
||||
|
||||
@Parameter(names = { "--format", "-format", "-f" }, description = "Report format type.")
|
||||
@@ -107,12 +132,17 @@ public class PMDParameters {
|
||||
@Parameter(names = { "-language", "-l" }, description = "Specify a language PMD should use.")
|
||||
private String language = null;
|
||||
|
||||
@Parameter(names = { "--force-language", "-force-language" }, description = "Force a language to be used for all input files, irrespective of filenames.")
|
||||
@Parameter(names = { "--force-language", "-force-language" },
|
||||
description = "Force a language to be used for all input files, irrespective of file names. "
|
||||
+ "When using this option, the automatic language selection by extension is disabled, and PMD "
|
||||
+ "tries to parse all input files with the given language's parser. "
|
||||
+ "Parsing errors are ignored."
|
||||
)
|
||||
private String forceLanguage = null;
|
||||
|
||||
@Parameter(names = { "--aux-classpath", "-auxclasspath" },
|
||||
description = "Specifies the classpath for libraries used by the source code. "
|
||||
+ "This is used by the type resolution. The platform specific path delimiter "
|
||||
+ "This is used to resolve types in Java source files. The platform specific path delimiter "
|
||||
+ "(\":\" on Linux, \";\" on Windows) is used to separate the entries. "
|
||||
+ "Alternatively, a single 'file:' URL to a text file containing path elements on consecutive lines "
|
||||
+ "can be specified.")
|
||||
@@ -199,10 +229,6 @@ public class PMDParameters {
|
||||
* @throws IllegalArgumentException if the parameters are inconsistent or incomplete
|
||||
*/
|
||||
public PMDConfiguration toConfiguration() {
|
||||
if (null == this.getSourceDir() && null == this.getUri() && null == this.getFileListPath()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Please provide a parameter for source root directory (-dir or -d), database URI (-uri or -u), or file list path (-filelist).");
|
||||
}
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
configuration.setInputPaths(this.getSourceDir());
|
||||
configuration.setInputFilePath(this.getFileListPath());
|
||||
@@ -348,12 +374,22 @@ public class PMDParameters {
|
||||
return auxclasspath;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getRulesets() {
|
||||
return StringUtils.join(rulesets, ",");
|
||||
}
|
||||
|
||||
public List<String> getRulesetRefs() {
|
||||
return rulesets;
|
||||
}
|
||||
|
||||
public List<String> getInputPaths() {
|
||||
return inputPaths;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getSourceDir() {
|
||||
return sourceDir;
|
||||
return StringUtils.join(inputPaths, ",");
|
||||
}
|
||||
|
||||
public String getFileListPath() {
|
||||
|
||||
@@ -105,13 +105,29 @@ public final class PmdParametersParseResult {
|
||||
jcommander.setProgramName("pmd");
|
||||
|
||||
try {
|
||||
jcommander.parse(args);
|
||||
parseAndValidate(jcommander, result, args);
|
||||
return new PmdParametersParseResult(result, filterDeprecatedOptions(args));
|
||||
} catch (ParameterException e) {
|
||||
return new PmdParametersParseResult(e, filterDeprecatedOptions(args));
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseAndValidate(JCommander jcommander, PMDParameters result, String[] args) {
|
||||
jcommander.parse(args);
|
||||
if (result.isHelp() || result.isVersion()) {
|
||||
return;
|
||||
}
|
||||
// jcommander has no special support for global parameter validation like this
|
||||
// For consistency we report this with a ParameterException
|
||||
if (result.getInputPaths().isEmpty()
|
||||
&& null == result.getUri()
|
||||
&& null == result.getFileListPath()) {
|
||||
throw new ParameterException(
|
||||
"Please provide a parameter for source root directory (--dir or -d), database URI (--uri or -u), or file list path (--file-list).");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Map<String, String> filterDeprecatedOptions(String... args) {
|
||||
Map<String, String> argSet = new LinkedHashMap<>(SUGGESTED_REPLACEMENT);
|
||||
argSet.keySet().retainAll(new HashSet<>(Arrays.asList(args)));
|
||||
|
||||
@@ -147,7 +147,16 @@ public class GUI implements CPDListener {
|
||||
|
||||
@Override
|
||||
public boolean canIgnoreAnnotations() {
|
||||
return "java".equals(terseName);
|
||||
if (terseName == null) {
|
||||
return false;
|
||||
}
|
||||
switch (terseName) {
|
||||
case "cs":
|
||||
case "java":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+19
-1
@@ -52,7 +52,7 @@ public final class AstElementNode extends BaseNodeInfo implements SiblingCountin
|
||||
BaseNodeInfo parent,
|
||||
Node wrappedNode,
|
||||
Configuration configuration) {
|
||||
super(Type.ELEMENT, configuration.getNamePool(), wrappedNode.getXPathNodeName(), parent);
|
||||
super(determineType(wrappedNode), configuration.getNamePool(), wrappedNode.getXPathNodeName(), parent);
|
||||
|
||||
this.treeInfo = document;
|
||||
this.wrappedNode = wrappedNode;
|
||||
@@ -65,6 +65,19 @@ public final class AstElementNode extends BaseNodeInfo implements SiblingCountin
|
||||
}
|
||||
}
|
||||
|
||||
private static int determineType(Node node) {
|
||||
// As of PMD 6.48.0, only the experimental HTML module uses this naming
|
||||
// convention to identify non-element nodes.
|
||||
// TODO PMD 7: maybe generalize this to other languages
|
||||
String name = node.getXPathNodeName();
|
||||
if ("#text".equals(name)) {
|
||||
return Type.TEXT;
|
||||
} else if ("#comment".equals(name)) {
|
||||
return Type.COMMENT;
|
||||
}
|
||||
return Type.ELEMENT;
|
||||
}
|
||||
|
||||
public Map<String, AstAttributeNode> makeAttributes(Node wrappedNode) {
|
||||
Map<String, AstAttributeNode> atts = new HashMap<>();
|
||||
Iterator<Attribute> it = wrappedNode.getXPathAttributesIterator();
|
||||
@@ -179,6 +192,10 @@ public final class AstElementNode extends BaseNodeInfo implements SiblingCountin
|
||||
|
||||
@Override
|
||||
public CharSequence getStringValueCS() {
|
||||
if (getNodeKind() == Type.TEXT || getNodeKind() == Type.COMMENT) {
|
||||
return getUnderlyingNode().getImage();
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/xpath-datamodel-31/#ElementNode
|
||||
// The string-value property of an Element Node must be the
|
||||
// concatenation of the string-values of all its Text Node
|
||||
@@ -187,6 +204,7 @@ public final class AstElementNode extends BaseNodeInfo implements SiblingCountin
|
||||
|
||||
// Since we represent all our Nodes as elements, there are no
|
||||
// text nodes
|
||||
// TODO: for some languages like html we have text nodes
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,17 @@
|
||||
|
||||
package net.sourceforge.pmd.cli;
|
||||
|
||||
import static net.sourceforge.pmd.util.CollectionUtil.listOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.PMDConfiguration;
|
||||
|
||||
public class PMDParametersTest {
|
||||
|
||||
@Test
|
||||
@@ -20,4 +27,60 @@ public class PMDParametersTest {
|
||||
FieldUtils.writeDeclaredField(parameters, "language", "dummy2", true);
|
||||
Assert.assertEquals("1.0", parameters.getVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleDirsAndRuleSets() {
|
||||
PmdParametersParseResult result = PmdParametersParseResult.extractParameters(
|
||||
"-d", "a", "b", "-R", "x.xml", "y.xml"
|
||||
);
|
||||
assertMultipleDirsAndRulesets(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleDirsAndRuleSetsWithCommas() {
|
||||
PmdParametersParseResult result = PmdParametersParseResult.extractParameters(
|
||||
"-d", "a,b", "-R", "x.xml,y.xml"
|
||||
);
|
||||
assertMultipleDirsAndRulesets(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleDirsAndRuleSetsWithRepeatedOption() {
|
||||
PmdParametersParseResult result = PmdParametersParseResult.extractParameters(
|
||||
"-d", "a", "-d", "b", "-R", "x.xml", "-R", "y.xml"
|
||||
);
|
||||
assertMultipleDirsAndRulesets(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoPositionalParametersAllowed() {
|
||||
assertError(
|
||||
// vvvv
|
||||
"-R", "x.xml", "-d", "a", "--", "-d", "b"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private void assertMultipleDirsAndRulesets(PmdParametersParseResult result) {
|
||||
assertFalse(result.isError());
|
||||
PMDConfiguration config = result.toConfiguration();
|
||||
assertEquals(config.getAllInputPaths(), listOf("a", "b"));
|
||||
assertEquals(config.getRuleSetPaths(), listOf("x.xml", "y.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyDirOption() {
|
||||
assertError("-d", "-R", "y.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyRulesetOption() {
|
||||
assertError("-R", "-d", "something");
|
||||
}
|
||||
|
||||
private void assertError(String... params) {
|
||||
PmdParametersParseResult result = PmdParametersParseResult.extractParameters(params);
|
||||
assertTrue(result.isError());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+50
@@ -57,4 +57,54 @@ public class ElementNodeTest {
|
||||
Assert.assertEquals(0, elementFoo1.compareOrder(elementFoo1));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyTextNodeType() {
|
||||
DummyRootNode root = new DummyRootNode();
|
||||
|
||||
DummyNode c0 = new DummyNode(false, "foo");
|
||||
c0.setCoords(1, 1, 2, 2);
|
||||
root.addChild(c0, 0);
|
||||
|
||||
DummyNode c1 = new DummyNode(false, "#text");
|
||||
c1.setCoords(2, 1, 2, 2);
|
||||
root.addChild(c1, 1);
|
||||
|
||||
Configuration configuration = Configuration.newConfiguration();
|
||||
AstTreeInfo treeInfo = new AstTreeInfo(root, configuration);
|
||||
|
||||
AstElementNode rootElt = treeInfo.getRootNode().getRootElement();
|
||||
Assert.assertSame(root, rootElt.getUnderlyingNode());
|
||||
Assert.assertEquals(Type.ELEMENT, rootElt.getNodeKind());
|
||||
Assert.assertSame(rootElt, treeInfo.findWrapperFor(root));
|
||||
|
||||
AstElementNode elementFoo0 = rootElt.getChildren().get(0);
|
||||
Assert.assertEquals(Type.ELEMENT, elementFoo0.getNodeKind());
|
||||
Assert.assertSame(c0, elementFoo0.getUnderlyingNode());
|
||||
Assert.assertSame(elementFoo0, treeInfo.findWrapperFor(c0));
|
||||
|
||||
AstElementNode elementText1 = rootElt.getChildren().get(1);
|
||||
Assert.assertEquals(Type.TEXT, elementText1.getNodeKind());
|
||||
Assert.assertSame(c1, elementText1.getUnderlyingNode());
|
||||
Assert.assertSame(elementText1, treeInfo.findWrapperFor(c1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyCommentNodeType() {
|
||||
DummyRootNode root = new DummyRootNode();
|
||||
|
||||
DummyNode c1 = new DummyNode(false, "#comment");
|
||||
c1.setCoords(2, 1, 2, 2);
|
||||
root.addChild(c1, 0);
|
||||
|
||||
Configuration configuration = Configuration.newConfiguration();
|
||||
AstTreeInfo treeInfo = new AstTreeInfo(root, configuration);
|
||||
AstElementNode rootElt = treeInfo.getRootNode().getRootElement();
|
||||
|
||||
AstElementNode elementComment = rootElt.getChildren().get(0);
|
||||
Assert.assertEquals(Type.COMMENT, elementComment.getNodeKind());
|
||||
Assert.assertSame(c1, elementComment.getUnderlyingNode());
|
||||
Assert.assertSame(elementComment, treeInfo.findWrapperFor(c1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public class CsTokenizer extends AntlrTokenizer {
|
||||
|
||||
private boolean ignoreUsings = false;
|
||||
private boolean ignoreLiteralSequences = false;
|
||||
private boolean ignoreAttributes = false;
|
||||
|
||||
/**
|
||||
* Sets the possible options for the C# tokenizer.
|
||||
@@ -28,19 +29,16 @@ public class CsTokenizer extends AntlrTokenizer {
|
||||
* @param properties the properties
|
||||
* @see #IGNORE_USINGS
|
||||
* @see #OPTION_IGNORE_LITERAL_SEQUENCES
|
||||
* @see #IGNORE_ANNOTATIONS
|
||||
*/
|
||||
public void setProperties(Properties properties) {
|
||||
ignoreUsings = Boolean.parseBoolean(properties.getProperty(IGNORE_USINGS, Boolean.FALSE.toString()));
|
||||
ignoreLiteralSequences = Boolean.parseBoolean(properties.getProperty(OPTION_IGNORE_LITERAL_SEQUENCES,
|
||||
Boolean.FALSE.toString()));
|
||||
ignoreUsings = getBooleanProperty(properties, IGNORE_USINGS);
|
||||
ignoreLiteralSequences = getBooleanProperty(properties, OPTION_IGNORE_LITERAL_SEQUENCES);
|
||||
ignoreAttributes = getBooleanProperty(properties, IGNORE_ANNOTATIONS);
|
||||
}
|
||||
|
||||
public void setIgnoreUsings(boolean ignoreUsings) {
|
||||
this.ignoreUsings = ignoreUsings;
|
||||
}
|
||||
|
||||
public void setIgnoreLiteralSequences(boolean ignoreLiteralSequences) {
|
||||
this.ignoreLiteralSequences = ignoreLiteralSequences;
|
||||
private boolean getBooleanProperty(final Properties properties, final String property) {
|
||||
return Boolean.parseBoolean(properties.getProperty(property, Boolean.FALSE.toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,7 +49,7 @@ public class CsTokenizer extends AntlrTokenizer {
|
||||
|
||||
@Override
|
||||
protected AntlrTokenFilter getTokenFilter(final AntlrTokenManager tokenManager) {
|
||||
return new CsTokenFilter(tokenManager, ignoreUsings, ignoreLiteralSequences);
|
||||
return new CsTokenFilter(tokenManager, ignoreUsings, ignoreLiteralSequences, ignoreAttributes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,15 +68,18 @@ public class CsTokenizer extends AntlrTokenizer {
|
||||
|
||||
private final boolean ignoreUsings;
|
||||
private final boolean ignoreLiteralSequences;
|
||||
private final boolean ignoreAttributes;
|
||||
private boolean discardingUsings = false;
|
||||
private boolean discardingNL = false;
|
||||
private boolean isDiscardingAttribute = false;
|
||||
private AntlrToken discardingLiteralsUntil = null;
|
||||
private boolean discardCurrent = false;
|
||||
|
||||
CsTokenFilter(final AntlrTokenManager tokenManager, boolean ignoreUsings, boolean ignoreLiteralSequences) {
|
||||
CsTokenFilter(final AntlrTokenManager tokenManager, boolean ignoreUsings, boolean ignoreLiteralSequences, boolean ignoreAttributes) {
|
||||
super(tokenManager);
|
||||
this.ignoreUsings = ignoreUsings;
|
||||
this.ignoreLiteralSequences = ignoreLiteralSequences;
|
||||
this.ignoreAttributes = ignoreAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,6 +92,7 @@ public class CsTokenizer extends AntlrTokenizer {
|
||||
discardCurrent = false;
|
||||
skipUsingDirectives(currentToken, remainingTokens);
|
||||
skipLiteralSequences(currentToken, remainingTokens);
|
||||
skipAttributes(currentToken);
|
||||
}
|
||||
|
||||
private void skipUsingDirectives(final AntlrToken currentToken, final Iterable<AntlrToken> remainingTokens) {
|
||||
@@ -167,6 +169,25 @@ public class CsTokenizer extends AntlrTokenizer {
|
||||
discardingNL = currentToken.getKind() == CSharpLexer.NL;
|
||||
}
|
||||
|
||||
private void skipAttributes(final AntlrToken currentToken) {
|
||||
if (ignoreAttributes) {
|
||||
switch (currentToken.getKind()) {
|
||||
case CSharpLexer.OPEN_BRACKET:
|
||||
// Start of an attribute.
|
||||
isDiscardingAttribute = true;
|
||||
break;
|
||||
case CSharpLexer.CLOSE_BRACKET:
|
||||
// End of an attribute.
|
||||
isDiscardingAttribute = false;
|
||||
discardCurrent = true;
|
||||
break;
|
||||
default:
|
||||
// Skip any other token.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void skipLiteralSequences(final AntlrToken currentToken, final Iterable<AntlrToken> remainingTokens) {
|
||||
if (ignoreLiteralSequences) {
|
||||
final int type = currentToken.getKind();
|
||||
@@ -222,7 +243,7 @@ public class CsTokenizer extends AntlrTokenizer {
|
||||
|
||||
@Override
|
||||
protected boolean isLanguageSpecificDiscarding() {
|
||||
return discardingUsings || discardingNL || isDiscardingLiterals() || discardCurrent;
|
||||
return discardingUsings || discardingNL || isDiscardingAttribute || isDiscardingLiterals() || discardCurrent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,18 +105,33 @@ public class CsTokenizerTest extends CpdTextComparisonTest {
|
||||
doTest("csharp7And8Additions");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttributesAreNotIgnored() {
|
||||
doTest("attributes");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttributesAreIgnored() {
|
||||
doTest("attributes", "_ignored", skipAttributes());
|
||||
}
|
||||
|
||||
private Properties ignoreUsings() {
|
||||
return properties(true, false);
|
||||
return properties(true, false, false);
|
||||
}
|
||||
|
||||
private Properties skipLiteralSequences() {
|
||||
return properties(false, true);
|
||||
return properties(false, true, false);
|
||||
}
|
||||
|
||||
private Properties properties(boolean ignoreUsings, boolean ignoreLiteralSequences) {
|
||||
private Properties skipAttributes() {
|
||||
return properties(false, false, true);
|
||||
}
|
||||
|
||||
private Properties properties(boolean ignoreUsings, boolean ignoreLiteralSequences, boolean ignoreAttributes) {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(Tokenizer.IGNORE_USINGS, Boolean.toString(ignoreUsings));
|
||||
properties.setProperty(Tokenizer.OPTION_IGNORE_LITERAL_SEQUENCES, Boolean.toString(ignoreLiteralSequences));
|
||||
properties.setProperty(Tokenizer.IGNORE_ANNOTATIONS, Boolean.toString(ignoreAttributes));
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
[Serializable]
|
||||
public class SampleClass
|
||||
{
|
||||
// Objects of this type can be serialized.
|
||||
}
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("user32.dll")]
|
||||
extern static void SampleMethod();
|
||||
|
||||
void MethodA([In][Out] ref double x) { }
|
||||
void MethodB([Out][In] ref double x) { }
|
||||
void MethodC([In, Out] ref double x) { }
|
||||
|
||||
[Conditional("DEBUG"), Conditional("TEST1")]
|
||||
void TraceMethod()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
|
||||
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: AssemblyTitleAttribute("Production assembly 4")]
|
||||
[module: CLSCompliant(true)]
|
||||
|
||||
// default: applies to method
|
||||
[ValidatedContract]
|
||||
int Method1() { return 0; }
|
||||
|
||||
// applies to method
|
||||
[method: ValidatedContract]
|
||||
int Method2() { return 0; }
|
||||
|
||||
// applies to parameter
|
||||
int Method3([ValidatedContract] string contract) { return 0; }
|
||||
|
||||
// applies to return value
|
||||
[return: ValidatedContract]
|
||||
int Method4() { return 0; }
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
[Image] or [Truncated image[ Bcol Ecol
|
||||
L1
|
||||
[\[] 1 2
|
||||
[Serializable] 2 14
|
||||
[\]] 14 15
|
||||
L2
|
||||
[public] 1 7
|
||||
[class] 8 13
|
||||
[SampleClass] 14 25
|
||||
L3
|
||||
[{] 1 2
|
||||
L5
|
||||
[}] 1 2
|
||||
L7
|
||||
[\[] 1 2
|
||||
[System] 2 8
|
||||
[.] 8 9
|
||||
[Runtime] 9 16
|
||||
[.] 16 17
|
||||
[InteropServices] 17 32
|
||||
[.] 32 33
|
||||
[DllImport] 33 42
|
||||
[(] 42 43
|
||||
["user32.dll"] 43 55
|
||||
[)] 55 56
|
||||
[\]] 56 57
|
||||
L8
|
||||
[extern] 1 7
|
||||
[static] 8 14
|
||||
[void] 15 19
|
||||
[SampleMethod] 20 32
|
||||
[(] 32 33
|
||||
[)] 33 34
|
||||
[;] 34 35
|
||||
L10
|
||||
[void] 1 5
|
||||
[MethodA] 6 13
|
||||
[(] 13 14
|
||||
[\[] 14 15
|
||||
[In] 15 17
|
||||
[\]] 17 18
|
||||
[\[] 18 19
|
||||
[Out] 19 22
|
||||
[\]] 22 23
|
||||
[ref] 24 27
|
||||
[double] 28 34
|
||||
[x] 35 36
|
||||
[)] 36 37
|
||||
[{] 38 39
|
||||
[}] 40 41
|
||||
L11
|
||||
[void] 1 5
|
||||
[MethodB] 6 13
|
||||
[(] 13 14
|
||||
[\[] 14 15
|
||||
[Out] 15 18
|
||||
[\]] 18 19
|
||||
[\[] 19 20
|
||||
[In] 20 22
|
||||
[\]] 22 23
|
||||
[ref] 24 27
|
||||
[double] 28 34
|
||||
[x] 35 36
|
||||
[)] 36 37
|
||||
[{] 38 39
|
||||
[}] 40 41
|
||||
L12
|
||||
[void] 1 5
|
||||
[MethodC] 6 13
|
||||
[(] 13 14
|
||||
[\[] 14 15
|
||||
[In] 15 17
|
||||
[,] 17 18
|
||||
[Out] 19 22
|
||||
[\]] 22 23
|
||||
[ref] 24 27
|
||||
[double] 28 34
|
||||
[x] 35 36
|
||||
[)] 36 37
|
||||
[{] 38 39
|
||||
[}] 40 41
|
||||
L14
|
||||
[\[] 1 2
|
||||
[Conditional] 2 13
|
||||
[(] 13 14
|
||||
["DEBUG"] 14 21
|
||||
[)] 21 22
|
||||
[,] 22 23
|
||||
[Conditional] 24 35
|
||||
[(] 35 36
|
||||
["TEST1"] 36 43
|
||||
[)] 43 44
|
||||
[\]] 44 45
|
||||
L15
|
||||
[void] 1 5
|
||||
[TraceMethod] 6 17
|
||||
[(] 17 18
|
||||
[)] 18 19
|
||||
L16
|
||||
[{] 1 2
|
||||
L18
|
||||
[}] 1 2
|
||||
L20
|
||||
[\[] 1 2
|
||||
[DllImport] 2 11
|
||||
[(] 11 12
|
||||
["user32.dll"] 12 24
|
||||
[)] 24 25
|
||||
[\]] 25 26
|
||||
L21
|
||||
[\[] 1 2
|
||||
[DllImport] 2 11
|
||||
[(] 11 12
|
||||
["user32.dll"] 12 24
|
||||
[,] 24 25
|
||||
[SetLastError] 26 38
|
||||
[=] 38 39
|
||||
[false] 39 44
|
||||
[,] 44 45
|
||||
[ExactSpelling] 46 59
|
||||
[=] 59 60
|
||||
[false] 60 65
|
||||
[)] 65 66
|
||||
[\]] 66 67
|
||||
L22
|
||||
[\[] 1 2
|
||||
[DllImport] 2 11
|
||||
[(] 11 12
|
||||
["user32.dll"] 12 24
|
||||
[,] 24 25
|
||||
[ExactSpelling] 26 39
|
||||
[=] 39 40
|
||||
[false] 40 45
|
||||
[,] 45 46
|
||||
[SetLastError] 47 59
|
||||
[=] 59 60
|
||||
[false] 60 65
|
||||
[)] 65 66
|
||||
[\]] 66 67
|
||||
L24
|
||||
[using] 1 6
|
||||
[System] 7 13
|
||||
[;] 13 14
|
||||
L25
|
||||
[using] 1 6
|
||||
[System] 7 13
|
||||
[.] 13 14
|
||||
[Reflection] 14 24
|
||||
[;] 24 25
|
||||
L26
|
||||
[\[] 1 2
|
||||
[assembly] 2 10
|
||||
[:] 10 11
|
||||
[AssemblyTitleAttribute] 12 34
|
||||
[(] 34 35
|
||||
["Production assembly 4"] 35 58
|
||||
[)] 58 59
|
||||
[\]] 59 60
|
||||
L27
|
||||
[\[] 1 2
|
||||
[module] 2 8
|
||||
[:] 8 9
|
||||
[CLSCompliant] 10 22
|
||||
[(] 22 23
|
||||
[true] 23 27
|
||||
[)] 27 28
|
||||
[\]] 28 29
|
||||
L30
|
||||
[\[] 1 2
|
||||
[ValidatedContract] 2 19
|
||||
[\]] 19 20
|
||||
L31
|
||||
[int] 1 4
|
||||
[Method1] 5 12
|
||||
[(] 12 13
|
||||
[)] 13 14
|
||||
[{] 15 16
|
||||
[return] 17 23
|
||||
[0] 24 25
|
||||
[;] 25 26
|
||||
[}] 27 28
|
||||
L34
|
||||
[\[] 1 2
|
||||
[method] 2 8
|
||||
[:] 8 9
|
||||
[ValidatedContract] 10 27
|
||||
[\]] 27 28
|
||||
L35
|
||||
[int] 1 4
|
||||
[Method2] 5 12
|
||||
[(] 12 13
|
||||
[)] 13 14
|
||||
[{] 15 16
|
||||
[return] 17 23
|
||||
[0] 24 25
|
||||
[;] 25 26
|
||||
[}] 27 28
|
||||
L38
|
||||
[int] 1 4
|
||||
[Method3] 5 12
|
||||
[(] 12 13
|
||||
[\[] 13 14
|
||||
[ValidatedContract] 14 31
|
||||
[\]] 31 32
|
||||
[string] 33 39
|
||||
[contract] 40 48
|
||||
[)] 48 49
|
||||
[{] 50 51
|
||||
[return] 52 58
|
||||
[0] 59 60
|
||||
[;] 60 61
|
||||
[}] 62 63
|
||||
L41
|
||||
[\[] 1 2
|
||||
[return] 2 8
|
||||
[:] 8 9
|
||||
[ValidatedContract] 10 27
|
||||
[\]] 27 28
|
||||
L42
|
||||
[int] 1 4
|
||||
[Method4] 5 12
|
||||
[(] 12 13
|
||||
[)] 13 14
|
||||
[{] 15 16
|
||||
[return] 17 23
|
||||
[0] 24 25
|
||||
[;] 25 26
|
||||
[}] 27 28
|
||||
EOF
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
[Image] or [Truncated image[ Bcol Ecol
|
||||
L2
|
||||
[public] 1 7
|
||||
[class] 8 13
|
||||
[SampleClass] 14 25
|
||||
L3
|
||||
[{] 1 2
|
||||
L5
|
||||
[}] 1 2
|
||||
L8
|
||||
[extern] 1 7
|
||||
[static] 8 14
|
||||
[void] 15 19
|
||||
[SampleMethod] 20 32
|
||||
[(] 32 33
|
||||
[)] 33 34
|
||||
[;] 34 35
|
||||
L10
|
||||
[void] 1 5
|
||||
[MethodA] 6 13
|
||||
[(] 13 14
|
||||
[ref] 24 27
|
||||
[double] 28 34
|
||||
[x] 35 36
|
||||
[)] 36 37
|
||||
[{] 38 39
|
||||
[}] 40 41
|
||||
L11
|
||||
[void] 1 5
|
||||
[MethodB] 6 13
|
||||
[(] 13 14
|
||||
[ref] 24 27
|
||||
[double] 28 34
|
||||
[x] 35 36
|
||||
[)] 36 37
|
||||
[{] 38 39
|
||||
[}] 40 41
|
||||
L12
|
||||
[void] 1 5
|
||||
[MethodC] 6 13
|
||||
[(] 13 14
|
||||
[ref] 24 27
|
||||
[double] 28 34
|
||||
[x] 35 36
|
||||
[)] 36 37
|
||||
[{] 38 39
|
||||
[}] 40 41
|
||||
L15
|
||||
[void] 1 5
|
||||
[TraceMethod] 6 17
|
||||
[(] 17 18
|
||||
[)] 18 19
|
||||
L16
|
||||
[{] 1 2
|
||||
L18
|
||||
[}] 1 2
|
||||
L24
|
||||
[using] 1 6
|
||||
[System] 7 13
|
||||
[;] 13 14
|
||||
L25
|
||||
[using] 1 6
|
||||
[System] 7 13
|
||||
[.] 13 14
|
||||
[Reflection] 14 24
|
||||
[;] 24 25
|
||||
L31
|
||||
[int] 1 4
|
||||
[Method1] 5 12
|
||||
[(] 12 13
|
||||
[)] 13 14
|
||||
[{] 15 16
|
||||
[return] 17 23
|
||||
[0] 24 25
|
||||
[;] 25 26
|
||||
[}] 27 28
|
||||
L35
|
||||
[int] 1 4
|
||||
[Method2] 5 12
|
||||
[(] 12 13
|
||||
[)] 13 14
|
||||
[{] 15 16
|
||||
[return] 17 23
|
||||
[0] 24 25
|
||||
[;] 25 26
|
||||
[}] 27 28
|
||||
L38
|
||||
[int] 1 4
|
||||
[Method3] 5 12
|
||||
[(] 12 13
|
||||
[string] 33 39
|
||||
[contract] 40 48
|
||||
[)] 48 49
|
||||
[{] 50 51
|
||||
[return] 52 58
|
||||
[0] 59 60
|
||||
[;] 60 61
|
||||
[}] 62 63
|
||||
L42
|
||||
[int] 1 4
|
||||
[Method4] 5 12
|
||||
[(] 12 13
|
||||
[)] 13 14
|
||||
[{] 15 16
|
||||
[return] 17 23
|
||||
[0] 24 25
|
||||
[;] 25 26
|
||||
[}] 27 28
|
||||
EOF
|
||||
@@ -30,6 +30,8 @@ public class BinaryDistributionIT extends AbstractBinaryDistributionTest {
|
||||
SUPPORTED_LANGUAGES_PMD = "apex, ecmascript, html, java, jsp, modelica, plsql, pom, scala, swift, vf, vm, wsdl, xml, xsl";
|
||||
}
|
||||
|
||||
private final String srcDir = new File(".", "src/test/resources/sample-source/java/").getAbsolutePath();
|
||||
|
||||
@Test
|
||||
public void testFileExistence() {
|
||||
assertTrue(getBinaryDistribution().exists());
|
||||
@@ -69,27 +71,34 @@ public class BinaryDistributionIT extends AbstractBinaryDistributionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runPMD() throws Exception {
|
||||
String srcDir = new File(".", "src/test/resources/sample-source/java/").getAbsolutePath();
|
||||
public void testPmdJavaQuickstart() throws Exception {
|
||||
ExecutionResult result = PMDExecutor.runPMDRules(folder.newFile().toPath(), tempDir, srcDir, "rulesets/java/quickstart.xml");
|
||||
result.assertExecutionResult(4, "");
|
||||
}
|
||||
|
||||
ExecutionResult result;
|
||||
|
||||
result = PMDExecutor.runPMD(tempDir); // without any argument, display usage help and error
|
||||
result.assertExecutionResultErrOutput(1, CliMessages.runWithHelpFlagMessage());
|
||||
|
||||
result = PMDExecutor.runPMD(tempDir, "-h");
|
||||
result.assertExecutionResult(0, SUPPORTED_LANGUAGES_PMD);
|
||||
|
||||
result = PMDExecutor.runPMDRules(folder.newFile().toPath(), tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml");
|
||||
result.assertExecutionResult(4, "", "JumbledIncrementer.java:8:");
|
||||
|
||||
// also test XML format
|
||||
result = PMDExecutor.runPMDRules(folder.newFile().toPath(), tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml", "xml");
|
||||
@Test
|
||||
public void testPmdXmlFormat() throws Exception {
|
||||
ExecutionResult result = PMDExecutor.runPMDRules(folder.newFile().toPath(), tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml", "xml");
|
||||
result.assertExecutionResult(4, "", "JumbledIncrementer.java\">");
|
||||
result.assertExecutionResult(4, "", "<violation beginline=\"8\" endline=\"10\" begincolumn=\"13\" endcolumn=\"14\" rule=\"JumbledIncrementer\"");
|
||||
}
|
||||
|
||||
result = PMDExecutor.runPMDRules(folder.newFile().toPath(), tempDir, srcDir, "rulesets/java/quickstart.xml");
|
||||
result.assertExecutionResult(4, "");
|
||||
@Test
|
||||
public void testPmdSample() throws Exception {
|
||||
ExecutionResult result = PMDExecutor.runPMDRules(folder.newFile().toPath(), tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml");
|
||||
result.assertExecutionResult(4, "", "JumbledIncrementer.java:8:");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPmdHelp() throws Exception {
|
||||
ExecutionResult result = PMDExecutor.runPMD(tempDir, "-h");
|
||||
result.assertExecutionResult(0, SUPPORTED_LANGUAGES_PMD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPmdNoArgs() throws Exception {
|
||||
ExecutionResult result = PMDExecutor.runPMD(tempDir); // without any argument, display usage help and error
|
||||
result.assertExecutionResultErrOutput(1, CliMessages.runWithHelpFlagMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1215,6 +1215,7 @@ fragment UNICODE_LETTER
|
||||
| [\u1780-\u17B3]
|
||||
| [\u1820-\u1877]
|
||||
| [\u1880-\u18A8]
|
||||
| [\u1D00-\u1DFF]
|
||||
| [\u1E00-\u1E9B]
|
||||
| [\u1EA0-\u1EE0]
|
||||
| [\u1EE1-\u1EF9]
|
||||
@@ -1264,11 +1265,10 @@ fragment UNICODE_LETTER
|
||||
| [\u31A0-\u31B7]
|
||||
| [\u3400]
|
||||
| [\u4DB5]
|
||||
| [\u4E00]
|
||||
| [\u9FA5]
|
||||
| [\u4E00-\u9EA5]
|
||||
| [\uA000-\uA48C]
|
||||
| [\uAC00]
|
||||
| [\uD7A3]
|
||||
| [\uA490-\uABFF]
|
||||
| [\uAC00-\uD7AF]
|
||||
| [\uF900-\uFA2D]
|
||||
| [\uFB00-\uFB06]
|
||||
| [\uFB13-\uFB17]
|
||||
|
||||
@@ -40,4 +40,11 @@ public class GoTokenizerTest extends CpdTextComparisonTest {
|
||||
public void testIssue1751() {
|
||||
doTest("issue-1751");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnicode() {
|
||||
// https://github.com/pmd/pmd/issues/2752
|
||||
doTest("sample_unicode");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
func main() {
|
||||
//string底层是一个byte数组,因此string也可以进行切片操作
|
||||
str := "hello world"//string是不可变的
|
||||
slice := str[4:]
|
||||
fmt.Println(slice)
|
||||
|
||||
//若要对string进行修改需要将string修改为byte或rune的切片在操作
|
||||
//但是转为byte无法进行中文操作
|
||||
bytes := []byte(str)
|
||||
bytes[2] = 'x'
|
||||
str = string(bytes)
|
||||
fmt.Println(str)
|
||||
|
||||
//转换成rune可以对中文进行操作
|
||||
runes := []rune(str)
|
||||
runes[0] = '哈'
|
||||
str = string(runes)
|
||||
fmt.Println(str)
|
||||
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
[Image] or [Truncated image[ Bcol Ecol
|
||||
L1
|
||||
[func] 1 5
|
||||
[main] 6 10
|
||||
[(] 10 11
|
||||
[)] 11 12
|
||||
[{] 13 14
|
||||
L3
|
||||
[str] 2 5
|
||||
[:=] 6 8
|
||||
["hello world"] 9 22
|
||||
L4
|
||||
[slice] 2 7
|
||||
[:=] 8 10
|
||||
[str] 11 14
|
||||
[\[] 14 15
|
||||
[4] 15 16
|
||||
[:] 16 17
|
||||
[\]] 17 18
|
||||
L5
|
||||
[fmt] 2 5
|
||||
[.] 5 6
|
||||
[Println] 6 13
|
||||
[(] 13 14
|
||||
[slice] 14 19
|
||||
[)] 19 20
|
||||
L9
|
||||
[bytes] 2 7
|
||||
[:=] 8 10
|
||||
[\[] 11 12
|
||||
[\]] 12 13
|
||||
[byte] 13 17
|
||||
[(] 17 18
|
||||
[str] 18 21
|
||||
[)] 21 22
|
||||
L10
|
||||
[bytes] 2 7
|
||||
[\[] 7 8
|
||||
[2] 8 9
|
||||
[\]] 9 10
|
||||
[=] 11 12
|
||||
['x'] 13 16
|
||||
L11
|
||||
[str] 2 5
|
||||
[=] 6 7
|
||||
[string] 8 14
|
||||
[(] 14 15
|
||||
[bytes] 15 20
|
||||
[)] 20 21
|
||||
L12
|
||||
[fmt] 2 5
|
||||
[.] 5 6
|
||||
[Println] 6 13
|
||||
[(] 13 14
|
||||
[str] 14 17
|
||||
[)] 17 18
|
||||
L15
|
||||
[runes] 2 7
|
||||
[:=] 8 10
|
||||
[\[] 11 12
|
||||
[\]] 12 13
|
||||
[rune] 13 17
|
||||
[(] 17 18
|
||||
[str] 18 21
|
||||
[)] 21 22
|
||||
L16
|
||||
[runes] 2 7
|
||||
[\[] 7 8
|
||||
[0] 8 9
|
||||
[\]] 9 10
|
||||
[=] 11 12
|
||||
['哈'] 13 16
|
||||
L17
|
||||
[str] 2 5
|
||||
[=] 6 7
|
||||
[string] 8 14
|
||||
[(] 14 15
|
||||
[runes] 15 20
|
||||
[)] 20 21
|
||||
L18
|
||||
[fmt] 2 5
|
||||
[.] 5 6
|
||||
[Println] 6 13
|
||||
[(] 13 14
|
||||
[str] 14 17
|
||||
[)] 17 18
|
||||
L20
|
||||
[}] 1 2
|
||||
EOF
|
||||
@@ -18,6 +18,10 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.ast.Parser;
|
||||
import net.sourceforge.pmd.lang.ast.Parser.ParserTask;
|
||||
import net.sourceforge.pmd.lang.ast.SemanticErrorReporter;
|
||||
import net.sourceforge.pmd.lang.html.ast.ASTHtmlComment;
|
||||
import net.sourceforge.pmd.lang.html.ast.ASTHtmlDocument;
|
||||
import net.sourceforge.pmd.lang.html.ast.ASTHtmlTextNode;
|
||||
import net.sourceforge.pmd.lang.html.ast.HtmlParsingHelper;
|
||||
import net.sourceforge.pmd.lang.rule.XPathRule;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.XPathVersion;
|
||||
|
||||
@@ -26,25 +30,49 @@ public class HtmlXPathRuleTest {
|
||||
private static final String LIGHTNING_WEB_COMPONENT = "<!-- helloExpressions.html -->\n"
|
||||
+ "<template>\n"
|
||||
+ " <p>Hello, { greeting}!</p>\n"
|
||||
+ " <lightning-input label=\"Name\" value={ greeting} onchange={handleChange}></lightning-input>"
|
||||
+ " <lightning-input label=\"Name\" value={ greeting} onchange={handleChange}></lightning-input>\n"
|
||||
+ " <div class=\"slds-m-around_medium\">\n"
|
||||
+ " <lightning-input name='firstName' label=\"First Name\" onchange={handleChange}></lightning-input>\n"
|
||||
+ " <lightning-input name='firstName' label=\"First Name\" onchange={ handleChange}></lightning-input>\n"
|
||||
+ " <lightning-input name='lastName' label=\"Last Name\" onchange={handleChange}></lightning-input>\n"
|
||||
+ " <p class=\"slds-m-top_medium\">Uppercased Full Name: {uppercasedFullName}</p>\n"
|
||||
+ " </div>\n"
|
||||
+ " <template if:true={visible}>\n"
|
||||
+ " <p>Test</p>\n"
|
||||
+ " </template>\n"
|
||||
+ "</template>";
|
||||
|
||||
@Test
|
||||
public void selectTextNode() {
|
||||
// from https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.js_props_getter
|
||||
// "Don’t add spaces around the property, for example, { data } is not valid HTML."
|
||||
String xpath = "//*[local-name() = '#text'][contains(@Text, '{ ')]";
|
||||
String xpath = "//text()[contains(., '{ ')]";
|
||||
|
||||
List<RuleViolation> violations = runXPath(LIGHTNING_WEB_COMPONENT, xpath);
|
||||
Assert.assertEquals(1, violations.size());
|
||||
Assert.assertEquals(3, violations.get(0).getBeginLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectTextNodeByNodeNameShouldNotWork() {
|
||||
String xpath = "//*[local-name() = '#text']";
|
||||
List<RuleViolation> violations = runXPath(LIGHTNING_WEB_COMPONENT, xpath);
|
||||
Assert.assertEquals(0, violations.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyTextNodeName() {
|
||||
ASTHtmlDocument document = HtmlParsingHelper.DEFAULT.parse("<p>foobar</p>");
|
||||
ASTHtmlTextNode textNode = document.getFirstDescendantOfType(ASTHtmlTextNode.class);
|
||||
Assert.assertEquals("#text", textNode.getXPathNodeName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyCommentNodeName() {
|
||||
ASTHtmlDocument document = HtmlParsingHelper.DEFAULT.parse("<p><!-- a comment --></p>");
|
||||
ASTHtmlComment comment = document.getFirstDescendantOfType(ASTHtmlComment.class);
|
||||
Assert.assertEquals("#comment", comment.getXPathNodeName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectAttributes() {
|
||||
// from https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.js_props_getter
|
||||
@@ -56,6 +84,27 @@ public class HtmlXPathRuleTest {
|
||||
Assert.assertEquals(4, violations.get(0).getBeginLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectAttributesMultiple() {
|
||||
// from https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.js_props_getter
|
||||
// "Don’t add spaces around the property, for example, { data } is not valid HTML."
|
||||
String xpath = "//*[@*[local-name() = ('value', 'onchange')] = '{']";
|
||||
|
||||
List<RuleViolation> violations = runXPath(LIGHTNING_WEB_COMPONENT, xpath);
|
||||
Assert.assertEquals(2, violations.size());
|
||||
Assert.assertEquals(4, violations.get(0).getBeginLine());
|
||||
Assert.assertEquals(6, violations.get(1).getBeginLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectAttributeByName() {
|
||||
String xpath = "//*[@*[local-name() = 'if:true']]";
|
||||
|
||||
List<RuleViolation> violations = runXPath(LIGHTNING_WEB_COMPONENT, xpath);
|
||||
Assert.assertEquals(1, violations.size());
|
||||
Assert.assertEquals(10, violations.get(0).getBeginLine());
|
||||
}
|
||||
|
||||
private List<RuleViolation> runXPath(String html, String xpath) {
|
||||
LanguageVersion htmlLanguage = LanguageRegistry.findLanguageByTerseName(HtmlLanguageModule.TERSE_NAME).getDefaultVersion();
|
||||
Parser parser = htmlLanguage.getLanguageVersionHandler().getParser();
|
||||
|
||||
@@ -796,7 +796,7 @@ TOKEN :
|
||||
"\u1310","\u1312"-"\u1315","\u1318"-"\u131e","\u1320"-"\u1346","\u1348"-"\u135a",
|
||||
"\u13a0"-"\u13f4","\u1401"-"\u166c","\u166f"-"\u1676","\u1681"-"\u169a","\u16a0"-"\u16ea",
|
||||
"\u1780"-"\u17b3","\u17db","\u1820"-"\u1877","\u1880"-"\u18a8","\u1e00"-"\u1e9b",
|
||||
"\u1ea0"-"\u1ef9","\u1f00"-"\u1f15","\u1f18"-"\u1f1d","\u1f20"-"\u1f45","\u1f48"-"\u1f4d",
|
||||
"\u1ea0"-"\u1ef9","\u1d00"-"\u1eef","\u1f00"-"\u1f15","\u1f18"-"\u1f1d","\u1f20"-"\u1f45","\u1f48"-"\u1f4d",
|
||||
"\u1f50"-"\u1f57","\u1f59","\u1f5b","\u1f5d","\u1f5f"-"\u1f7d","\u1f80"-"\u1fb4",
|
||||
"\u1fb6"-"\u1fbc","\u1fbe","\u1fc2"-"\u1fc4","\u1fc6"-"\u1fcc","\u1fd0"-"\u1fd3",
|
||||
"\u1fd6"-"\u1fdb","\u1fe0"-"\u1fec","\u1ff2"-"\u1ff4","\u1ff6"-"\u1ffc","\u203f"-"\u2040",
|
||||
@@ -804,7 +804,7 @@ TOKEN :
|
||||
"\u2124","\u2126","\u2128","\u212a"-"\u212d","\u212f"-"\u2131","\u2133"-"\u2139",
|
||||
"\u2160"-"\u2183","\u3005"-"\u3007","\u3021"-"\u3029","\u3031"-"\u3035","\u3038"-"\u303a",
|
||||
"\u3041"-"\u3094","\u309d"-"\u309e","\u30a1"-"\u30fe","\u3105"-"\u312c","\u3131"-"\u318e",
|
||||
"\u31a0"-"\u31b7","\u3400"-"\u4db5","\u4e00"-"\u9fa5","\ua000"-"\ua48c","\uac00"-"\ud7a3",
|
||||
"\u31a0"-"\u31b7","\u3400"-"\u4db5","\u4e00"-"\u9fa5","\ua000"-"\ua48c","\ua490"-"\uabff","\uac00"-"\ud7a3",
|
||||
"\uf900"-"\ufa2d","\ufb00"-"\ufb06","\ufb13"-"\ufb17","\ufb1d","\ufb1f"-"\ufb28",
|
||||
"\ufb2a"-"\ufb36","\ufb38"-"\ufb3c","\ufb3e","\ufb40"-"\ufb41","\ufb43"-"\ufb44",
|
||||
"\ufb46"-"\ufbb1","\ufbd3"-"\ufd3d","\ufd50"-"\ufd8f","\ufd92"-"\ufdc7","\ufdf0"-"\ufdfb",
|
||||
@@ -865,7 +865,7 @@ TOKEN :
|
||||
"\u12f0"-"\u130e","\u1310","\u1312"-"\u1315","\u1318"-"\u131e","\u1320"-"\u1346",
|
||||
"\u1348"-"\u135a","\u1369"-"\u1371","\u13a0"-"\u13f4","\u1401"-"\u166c","\u166f"-"\u1676",
|
||||
"\u1681"-"\u169a","\u16a0"-"\u16ea","\u1780"-"\u17d3","\u17db","\u17e0"-"\u17e9",
|
||||
"\u180b"-"\u180e","\u1810"-"\u1819","\u1820"-"\u1877","\u1880"-"\u18a9","\u1e00"-"\u1e9b",
|
||||
"\u180b"-"\u180e","\u1810"-"\u1819","\u1820"-"\u1877","\u1880"-"\u18a9","\u1d00"-"\u1d7f","\u1e00"-"\u1e9b",
|
||||
"\u1ea0"-"\u1ef9","\u1f00"-"\u1f15","\u1f18"-"\u1f1d","\u1f20"-"\u1f45","\u1f48"-"\u1f4d",
|
||||
"\u1f50"-"\u1f57","\u1f59","\u1f5b","\u1f5d","\u1f5f"-"\u1f7d","\u1f80"-"\u1fb4",
|
||||
"\u1fb6"-"\u1fbc","\u1fbe","\u1fc2"-"\u1fc4","\u1fc6"-"\u1fcc","\u1fd0"-"\u1fd3",
|
||||
@@ -876,6 +876,7 @@ TOKEN :
|
||||
"\u2160"-"\u2183","\u3005"-"\u3007","\u3021"-"\u302f","\u3031"-"\u3035","\u3038"-"\u303a",
|
||||
"\u3041"-"\u3094","\u3099"-"\u309a","\u309d"-"\u309e","\u30a1"-"\u30fe","\u3105"-"\u312c",
|
||||
"\u3131"-"\u318e","\u31a0"-"\u31b7","\u3400"-"\u4db5","\u4e00"-"\u9fa5","\ua000"-"\ua48c",
|
||||
"\ua490"-"\uabff",
|
||||
"\uac00"-"\ud7a3","\uf900"-"\ufa2d","\ufb00"-"\ufb06","\ufb13"-"\ufb17","\ufb1d"-"\ufb28",
|
||||
"\ufb2a"-"\ufb36","\ufb38"-"\ufb3c","\ufb3e","\ufb40"-"\ufb41","\ufb43"-"\ufb44",
|
||||
"\ufb46"-"\ufbb1","\ufbd3"-"\ufd3d","\ufd50"-"\ufd8f","\ufd92"-"\ufdc7","\ufdf0"-"\ufdfb",
|
||||
|
||||
+7
-2
@@ -44,7 +44,13 @@ public class ImmutableFieldRule extends AbstractJavaRulechainRule {
|
||||
);
|
||||
|
||||
private static final Set<String> INVALIDATING_FIELD_ANNOTS =
|
||||
setOf("lombok.Setter");
|
||||
setOf(
|
||||
"lombok.Setter",
|
||||
"org.mockito.Mock",
|
||||
"org.mockito.InjectMocks",
|
||||
"org.springframework.beans.factory.annotation.Autowired",
|
||||
"org.springframework.boot.test.mock.mockito.MockBean"
|
||||
);
|
||||
|
||||
public ImmutableFieldRule() {
|
||||
super(ASTFieldDeclaration.class);
|
||||
@@ -54,7 +60,6 @@ public class ImmutableFieldRule extends AbstractJavaRulechainRule {
|
||||
|
||||
@Override
|
||||
public Object visit(ASTFieldDeclaration field, Object data) {
|
||||
|
||||
ASTAnyTypeDeclaration enclosingType = field.getEnclosingType();
|
||||
if (field.getEffectiveVisibility().isAtMost(Visibility.V_PRIVATE)
|
||||
&& !field.getModifiers().hasAny(JModifier.VOLATILE, JModifier.STATIC, JModifier.FINAL)
|
||||
|
||||
@@ -145,6 +145,12 @@ public class ParserCornersTest extends BaseJavaTreeDumpTest {
|
||||
java7.parse(code);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnicodeIndent() {
|
||||
// https://github.com/pmd/pmd/issues/3423
|
||||
java7.parseResource("UnicodeIdentifier.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsersCases15() {
|
||||
doTest("ParserCornerCases", java5);
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
// https://github.com/pmd/pmd/issues/3423
|
||||
|
||||
package com.example.pmdtest;
|
||||
|
||||
public class PmdTest {
|
||||
|
||||
private static final int lᵤ = 1;
|
||||
private static final int μᵤ = 2;
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(lᵤ + μᵤ);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum CodeSet {
|
||||
|
||||
START_CODE_A('Ë'),
|
||||
START_CODE_B('Ì'),
|
||||
START_CODE_C('Í'),
|
||||
A_TILDE('\u00c3'),
|
||||
STOP_CODE('Î');
|
||||
|
||||
private final char encoding;
|
||||
|
||||
CodeSet(final char encoding) {
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
public char getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
}
|
||||
+27
@@ -516,4 +516,31 @@ public class Foo {
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description>With records</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
import java.util.Set;
|
||||
|
||||
public record Record(Set<String> stringSet) {
|
||||
|
||||
public boolean hasMoreThanOneItem() {
|
||||
return this.stringSet.size() > 1;
|
||||
}
|
||||
} ]]></code>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description>With records and size check</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-linenumbers>6</expected-linenumbers>
|
||||
<code><![CDATA[
|
||||
import java.util.Set;
|
||||
|
||||
public record Record(Set<String> stringSet) {
|
||||
|
||||
public boolean hasMoreThanOneItem() {
|
||||
return this.stringSet.size() == 0;
|
||||
}
|
||||
} ]]></code>
|
||||
</test-code>
|
||||
</test-data>
|
||||
|
||||
+31
@@ -657,4 +657,35 @@ public class ExampleImmutableField {
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#3874 [java] ImmutableField reports fields annotated with @Autowired (Spring) and @Mock (Mockito)</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class ExampleImmutableField {
|
||||
|
||||
@Mock
|
||||
private Foo foo;
|
||||
|
||||
@InjectMocks
|
||||
private Bar bar;
|
||||
|
||||
@MockBean
|
||||
private Baz Baz;
|
||||
|
||||
@Autowired
|
||||
private Foo2 foo2;
|
||||
}
|
||||
|
||||
class Foo {}
|
||||
class Bar {}
|
||||
class Baz {}
|
||||
class Foo2 {}
|
||||
]]></code>
|
||||
</test-code>
|
||||
</test-data>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user