From de1368275381c8a1511574759113d5813990ba64 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 28 Apr 2022 12:53:28 +0200 Subject: [PATCH 01/18] [core] Support #text and #comment nodes --- .../pmd/lang/ast/xpath/saxon/ElementNode.java | 22 ++++++++++++-- .../pmd/lang/html/HtmlXPathRuleTest.java | 30 +++++++++++++++++-- 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java index e9341542ea..ce9604fe79 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java @@ -61,7 +61,7 @@ public class ElementNode extends BaseNodeInfo implements AstNodeOwner { Node node, int siblingPosition, NamePool namePool) { - super(Type.ELEMENT, namePool, node.getXPathNodeName(), parent); + super(determineType(node), namePool, node.getXPathNodeName(), parent); this.document = document; this.parent = parent; @@ -80,6 +80,16 @@ public class ElementNode extends BaseNodeInfo implements AstNodeOwner { document.nodeToElementNode.put(node, this); } + private static short determineType(Node node) { + String name = node.getXPathNodeName(); + if ("#text".equals(name)) { + return Type.TEXT; + } else if ("#comment".equals(name)) { + return Type.COMMENT; + } + return Type.ELEMENT; + } + private Map getAttributes() { if (attributes == null) { attributes = new HashMap<>(); @@ -147,10 +157,18 @@ public class ElementNode extends BaseNodeInfo implements AstNodeOwner { } @Override - public CharSequence getStringValueCS() { + public String getStringValue() { + if (determineType(getUnderlyingNode()) == Type.TEXT) { + return getUnderlyingNode().getImage(); + } return ""; } + @Override + public CharSequence getStringValueCS() { + return getStringValue(); + } + @Override public int compareOrder(NodeInfo other) { int result; diff --git a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java index 6c2c53e2f9..1a70e5c0fc 100644 --- a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java +++ b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java @@ -24,19 +24,22 @@ public class HtmlXPathRuleTest { private static final String LIGHTNING_WEB_COMPONENT = "\n" + ""; @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(., '{ ')]"; Report report = runXPath(LIGHTNING_WEB_COMPONENT, xpath); Assert.assertEquals(1, report.getViolations().size()); @@ -54,6 +57,27 @@ public class HtmlXPathRuleTest { Assert.assertEquals(4, report.getViolations().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')] = '{']"; + + Report report = runXPath(LIGHTNING_WEB_COMPONENT, xpath); + Assert.assertEquals(2, report.getViolations().size()); + Assert.assertEquals(4, report.getViolations().get(0).getBeginLine()); + Assert.assertEquals(6, report.getViolations().get(1).getBeginLine()); + } + + @Test + public void selectAttributeByName() { + String xpath = "//*[@*[local-name() = 'if:true']]"; + + Report report = runXPath(LIGHTNING_WEB_COMPONENT, xpath); + Assert.assertEquals(1, report.getViolations().size()); + Assert.assertEquals(10, report.getViolations().get(0).getBeginLine()); + } + private Report runXPath(String html, String xpath) { LanguageVersion htmlLanguage = LanguageRegistry.findLanguageByTerseName(HtmlLanguageModule.TERSE_NAME).getDefaultVersion(); Parser parser = htmlLanguage.getLanguageVersionHandler().getParser(htmlLanguage.getLanguageVersionHandler().getDefaultParserOptions()); From 3538c6d3bd8d7c9a74df96399219277342ecbfbc Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 6 May 2022 15:52:12 +0200 Subject: [PATCH 02/18] [core] Improve support for #text and #comment node types --- .../pmd/lang/ast/xpath/saxon/ElementNode.java | 2 +- .../rule/xpath/saxon/ElementNodeTest.java | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java index ce9604fe79..702e6605d4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java @@ -80,7 +80,7 @@ public class ElementNode extends BaseNodeInfo implements AstNodeOwner { document.nodeToElementNode.put(node, this); } - private static short determineType(Node node) { + private static int determineType(Node node) { String name = node.getXPathNodeName(); if ("#text".equals(name)) { return Type.TEXT; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/saxon/ElementNodeTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/saxon/ElementNodeTest.java index ead5c73553..756e41eb46 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/saxon/ElementNodeTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/saxon/ElementNodeTest.java @@ -11,6 +11,8 @@ import net.sourceforge.pmd.lang.ast.DummyNode; import net.sourceforge.pmd.lang.ast.xpath.saxon.DocumentNode; import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; +import net.sf.saxon.type.Type; + public class ElementNodeTest { @Test @@ -56,4 +58,32 @@ public class ElementNodeTest { Assert.assertTrue(elementFoo1.compareOrder(elementFoo2) < 0); Assert.assertTrue(elementFoo2.compareOrder(elementFoo1) > 0); } + + @Test + public void verifyTextNodeType() { + DummyNode node = new DummyNode(1, false, "dummy"); + DummyNode foo1 = new DummyNode(2, false, "foo"); + DummyNode foo2 = new DummyNode(2, false, "#text"); + node.jjtAddChild(foo1, 0); + node.jjtAddChild(foo2, 1); + + DocumentNode document = new DocumentNode(node); + ElementNode elementFoo1 = document.nodeToElementNode.get(foo1); + ElementNode elementFoo2 = document.nodeToElementNode.get(foo2); + + Assert.assertEquals(Type.ELEMENT, elementFoo1.getNodeKind()); + Assert.assertEquals(Type.TEXT, elementFoo2.getNodeKind()); + } + + @Test + public void verifyCommentNodeType() { + DummyNode node = new DummyNode(1, false, "dummy"); + DummyNode foo = new DummyNode(2, false, "#comment"); + node.jjtAddChild(foo, 0); + + DocumentNode document = new DocumentNode(node); + ElementNode elementFoo = document.nodeToElementNode.get(foo); + + Assert.assertEquals(Type.COMMENT, elementFoo.getNodeKind()); + } } From 46727eb5d72e8dfff3d947aa1156e109ad28e8bd Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 6 May 2022 15:52:59 +0200 Subject: [PATCH 03/18] [html] Document XPath 2.0 only and text nodes handling --- docs/pages/pmd/languages/html.md | 10 ++++- .../pmd/lang/html/HtmlXPathRuleTest.java | 37 ++++++++++--------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/docs/pages/pmd/languages/html.md b/docs/pages/pmd/languages/html.md index acb96fc416..9c905571e1 100644 --- a/docs/pages/pmd/languages/html.md +++ b/docs/pages/pmd/languages/html.md @@ -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. diff --git a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java index 1a70e5c0fc..1a6272dab8 100644 --- a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java +++ b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java @@ -4,18 +4,14 @@ package net.sourceforge.pmd.lang.html; -import java.io.StringReader; -import java.util.Arrays; - import org.junit.Assert; import org.junit.Test; import net.sourceforge.pmd.Report; -import net.sourceforge.pmd.RuleContext; -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.lang.Parser; -import net.sourceforge.pmd.lang.ast.Node; +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; @@ -46,6 +42,20 @@ public class HtmlXPathRuleTest { Assert.assertEquals(3, report.getViolations().get(0).getBeginLine()); } + @Test + public void verifyTextNodeName() { + ASTHtmlDocument document = HtmlParsingHelper.DEFAULT.parse("

foobar

"); + ASTHtmlTextNode textNode = document.getFirstDescendantOfType(ASTHtmlTextNode.class); + Assert.assertEquals("#text", textNode.getXPathNodeName()); + } + + @Test + public void verifyCommentNodeName() { + ASTHtmlDocument document = HtmlParsingHelper.DEFAULT.parse("

"); + 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 @@ -79,16 +89,9 @@ public class HtmlXPathRuleTest { } private Report runXPath(String html, String xpath) { - LanguageVersion htmlLanguage = LanguageRegistry.findLanguageByTerseName(HtmlLanguageModule.TERSE_NAME).getDefaultVersion(); - Parser parser = htmlLanguage.getLanguageVersionHandler().getParser(htmlLanguage.getLanguageVersionHandler().getDefaultParserOptions()); - XPathRule rule = new XPathRule(XPathVersion.XPATH_2_0, xpath); rule.setMessage("test"); - Node node = parser.parse("n/a", new StringReader(html)); - RuleContext context = new RuleContext(); - context.setLanguageVersion(htmlLanguage); - context.setCurrentRule(rule); - rule.apply(Arrays.asList(node), context); - return context.getReport(); + rule.setLanguage(HtmlParsingHelper.DEFAULT.getLanguage()); + return HtmlParsingHelper.DEFAULT.executeRule(rule, html); } } From 686e878caf2ccf67e998697cd06193c0fd640083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 May 2022 18:42:45 +0200 Subject: [PATCH 04/18] Fix #1445 - Allow CLI to take globs as parameters This doesn't interpret globs or anything, only makes the parameter parsing compatible with shell expansion. Globs are therefore available provided you use a shell with that feature --- .../net/sourceforge/pmd/PMDConfiguration.java | 48 ++++++++++++++++--- .../sourceforge/pmd/cli/PMDParameters.java | 27 +++++++---- .../pmd/cli/PmdParametersParseResult.java | 15 +++++- .../net/sourceforge/pmd/cli/CoreCliTest.java | 23 ++++++++- .../net/sourceforge/pmd/cli/FakeRuleset2.xml | 20 ++++++++ 5 files changed, 116 insertions(+), 17 deletions(-) create mode 100644 pmd-core/src/test/resources/net/sourceforge/pmd/cli/FakeRuleset2.xml diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMDConfiguration.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMDConfiguration.java index 9d3c67aead..a44ec4b421 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMDConfiguration.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMDConfiguration.java @@ -8,6 +8,7 @@ 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; @@ -102,7 +103,7 @@ public class PMDConfiguration extends AbstractConfiguration { // Rule and source file options private List ruleSets = new ArrayList<>(); private RulePriority minimumPriority = RulePriority.LOW; - private String inputPaths; + private List inputPaths; private String inputUri; private String inputFilePath; private String ignoreFilePath; @@ -420,19 +421,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 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 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 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() { @@ -526,7 +562,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); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java index f80dad49bd..129483ee81 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java @@ -8,6 +8,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; +import org.apache.commons.lang3.StringUtils; + import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.RulePriority; @@ -29,14 +31,15 @@ import com.beust.jcommander.validators.PositiveInteger; public class PMDParameters { @Parameter(names = { "--rulesets", "-rulesets", "-R" }, description = "Comma separated list of ruleset names to use.", - required = true) - private String rulesets; + required = true, + variableArity = true) + private List rulesets; @Parameter(names = { "--uri", "-uri", "-u" }, description = "Database URI for sources.") private String uri; - @Parameter(names = { "--dir", "-dir", "-d" }, description = "Root directory for sources.") - private String sourceDir; + @Parameter(names = { "--dir", "-dir", "-d" }, description = "Root directory for sources.", variableArity = true) + private List inputPaths; @Parameter(names = { "--file-list", "-filelist" }, description = "Path to a file containing a list of files to analyze.") private String fileListPath; @@ -192,10 +195,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()); @@ -329,12 +328,22 @@ public class PMDParameters { return auxclasspath; } + @Deprecated public String getRulesets() { + return StringUtils.join(rulesets, ","); + } + + public List getRulesetRefs() { return rulesets; } + public List getInputPaths() { + return inputPaths; + } + + @Deprecated public String getSourceDir() { - return sourceDir; + return StringUtils.join(inputPaths, ","); } public String getFileListPath() { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PmdParametersParseResult.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PmdParametersParseResult.java index 0ffc8465d0..9f33d4e470 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PmdParametersParseResult.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PmdParametersParseResult.java @@ -105,13 +105,26 @@ 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); + // jcommander has no special support for global parameter validation like this + // For consistency we report this with a ParameterException + if (null == result.getSourceDir() + && 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 (-filelist)."); + } + + } + private static Map filterDeprecatedOptions(String... args) { Map argSet = new LinkedHashMap<>(SUGGESTED_REPLACEMENT); argSet.keySet().retainAll(new HashSet<>(Arrays.asList(args))); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java index 157caf975d..56e7337fdf 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java @@ -40,6 +40,7 @@ import net.sourceforge.pmd.junit.JavaUtilLoggingRule; public class CoreCliTest { private static final String DUMMY_RULESET = "net/sourceforge/pmd/cli/FakeRuleset.xml"; + private static final String DUMMY_RULESET2 = "net/sourceforge/pmd/cli/FakeRuleset2.xml"; private static final String STRING_TO_REPLACE = "__should_be_replaced__"; @Rule @@ -54,6 +55,7 @@ public class CoreCliTest { public final SystemErrRule errStreamCaptor = new SystemErrRule(); private Path srcDir; + private Path srcDir2; @Before public void setup() throws IOException { @@ -63,8 +65,10 @@ public class CoreCliTest { // create a few files srcDir = Files.createDirectories(root.resolve("src")); + srcDir2 = Files.createDirectories(root.resolve("src2")); writeString(srcDir.resolve("someSource.dummy"), "dummy text"); - + writeString(srcDir2.resolve("someSource.dummy"), "dummy text"); + // reset logger? Logger.getLogger("net.sourceforge.pmd"); } @@ -201,6 +205,23 @@ public class CoreCliTest { assertThatErrAndOut(not(containsStringIgnoringCase("Available report formats and"))); } + @Test + public void testMultipleRulesets() { + startCapturingErrAndOut(); + runPmdSuccessfully("--no-cache", "-d", srcDir, "-R", DUMMY_RULESET, DUMMY_RULESET2); + runPmdSuccessfully("--no-cache", "-d", srcDir, "-R", DUMMY_RULESET, DUMMY_RULESET2, "--"); + // ensure -d is not considered a ruleset + runPmdSuccessfully("--no-cache", "-R", DUMMY_RULESET, DUMMY_RULESET2, "-d", srcDir); + } + + @Test + public void testMultipleDirectories() { + startCapturingErrAndOut(); + runPmdSuccessfully("--no-cache", "-d", srcDir, srcDir2, "-R", DUMMY_RULESET); + runPmdSuccessfully("--no-cache", "-R", DUMMY_RULESET, "-d", srcDir, srcDir2); + runPmdSuccessfully("--no-cache", "-R", DUMMY_RULESET, "-d", srcDir, srcDir2, "--"); + } + private void assertThatErrAndOut(Matcher matcher) { assertThat("stdout", outStreamCaptor.getLog(), matcher); assertThat("stderr", errStreamCaptor.getLog(), matcher); diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/cli/FakeRuleset2.xml b/pmd-core/src/test/resources/net/sourceforge/pmd/cli/FakeRuleset2.xml new file mode 100644 index 0000000000..eebe094a76 --- /dev/null +++ b/pmd-core/src/test/resources/net/sourceforge/pmd/cli/FakeRuleset2.xml @@ -0,0 +1,20 @@ + + + + + Ruleset used by test RuleSetFactoryTest + + + + +Just for test + + 3 + + + + + From 06d0d6b0fba0a0fcec3b323f5da008fa1f6bc966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 May 2022 18:54:49 +0200 Subject: [PATCH 05/18] More tests, release notes --- docs/pages/release_notes.md | 19 ++++++ .../net/sourceforge/pmd/cli/CoreCliTest.java | 21 ------- .../pmd/cli/PMDParametersTest.java | 63 +++++++++++++++++++ .../net/sourceforge/pmd/cli/FakeRuleset2.xml | 20 ------ 4 files changed, 82 insertions(+), 41 deletions(-) delete mode 100644 pmd-core/src/test/resources/net/sourceforge/pmd/cli/FakeRuleset2.xml diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index c31a705241..647a57daf2 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -14,6 +14,19 @@ 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 +``` + ### Fixed Issues * javascript @@ -21,6 +34,12 @@ This is a {{ site.pmd.release_type }} release. ### 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 {% endtocmaker %} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java index 56e7337fdf..70c140023e 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java @@ -40,7 +40,6 @@ import net.sourceforge.pmd.junit.JavaUtilLoggingRule; public class CoreCliTest { private static final String DUMMY_RULESET = "net/sourceforge/pmd/cli/FakeRuleset.xml"; - private static final String DUMMY_RULESET2 = "net/sourceforge/pmd/cli/FakeRuleset2.xml"; private static final String STRING_TO_REPLACE = "__should_be_replaced__"; @Rule @@ -55,7 +54,6 @@ public class CoreCliTest { public final SystemErrRule errStreamCaptor = new SystemErrRule(); private Path srcDir; - private Path srcDir2; @Before public void setup() throws IOException { @@ -65,9 +63,7 @@ public class CoreCliTest { // create a few files srcDir = Files.createDirectories(root.resolve("src")); - srcDir2 = Files.createDirectories(root.resolve("src2")); writeString(srcDir.resolve("someSource.dummy"), "dummy text"); - writeString(srcDir2.resolve("someSource.dummy"), "dummy text"); // reset logger? Logger.getLogger("net.sourceforge.pmd"); } @@ -205,23 +201,6 @@ public class CoreCliTest { assertThatErrAndOut(not(containsStringIgnoringCase("Available report formats and"))); } - @Test - public void testMultipleRulesets() { - startCapturingErrAndOut(); - runPmdSuccessfully("--no-cache", "-d", srcDir, "-R", DUMMY_RULESET, DUMMY_RULESET2); - runPmdSuccessfully("--no-cache", "-d", srcDir, "-R", DUMMY_RULESET, DUMMY_RULESET2, "--"); - // ensure -d is not considered a ruleset - runPmdSuccessfully("--no-cache", "-R", DUMMY_RULESET, DUMMY_RULESET2, "-d", srcDir); - } - - @Test - public void testMultipleDirectories() { - startCapturingErrAndOut(); - runPmdSuccessfully("--no-cache", "-d", srcDir, srcDir2, "-R", DUMMY_RULESET); - runPmdSuccessfully("--no-cache", "-R", DUMMY_RULESET, "-d", srcDir, srcDir2); - runPmdSuccessfully("--no-cache", "-R", DUMMY_RULESET, "-d", srcDir, srcDir2, "--"); - } - private void assertThatErrAndOut(Matcher matcher) { assertThat("stdout", outStreamCaptor.getLog(), matcher); assertThat("stderr", errStreamCaptor.getLog(), matcher); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cli/PMDParametersTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cli/PMDParametersTest.java index 22ca614a06..40ff67955e 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cli/PMDParametersTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/cli/PMDParametersTest.java @@ -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()); + } + } diff --git a/pmd-core/src/test/resources/net/sourceforge/pmd/cli/FakeRuleset2.xml b/pmd-core/src/test/resources/net/sourceforge/pmd/cli/FakeRuleset2.xml deleted file mode 100644 index eebe094a76..0000000000 --- a/pmd-core/src/test/resources/net/sourceforge/pmd/cli/FakeRuleset2.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Ruleset used by test RuleSetFactoryTest - - - - -Just for test - - 3 - - - - - From e7229407d4ed061910a84633a09057f4b73f1e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 7 May 2022 19:29:00 +0200 Subject: [PATCH 06/18] Fix tests --- .../net/sourceforge/pmd/PMDConfiguration.java | 2 +- .../sourceforge/pmd/cli/PMDParameters.java | 2 +- .../pmd/cli/PmdParametersParseResult.java | 7 ++- .../pmd/it/BinaryDistributionIT.java | 43 +++++++++++-------- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/PMDConfiguration.java b/pmd-core/src/main/java/net/sourceforge/pmd/PMDConfiguration.java index a44ec4b421..ad3b9603c1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/PMDConfiguration.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/PMDConfiguration.java @@ -103,7 +103,7 @@ public class PMDConfiguration extends AbstractConfiguration { // Rule and source file options private List ruleSets = new ArrayList<>(); private RulePriority minimumPriority = RulePriority.LOW; - private List inputPaths; + private List inputPaths = new ArrayList<>(); private String inputUri; private String inputFilePath; private String ignoreFilePath; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java index 129483ee81..fd4c8408e1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java @@ -39,7 +39,7 @@ public class PMDParameters { private String uri; @Parameter(names = { "--dir", "-dir", "-d" }, description = "Root directory for sources.", variableArity = true) - private List inputPaths; + private List inputPaths = new ArrayList<>(); @Parameter(names = { "--file-list", "-filelist" }, description = "Path to a file containing a list of files to analyze.") private String fileListPath; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PmdParametersParseResult.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PmdParametersParseResult.java index 9f33d4e470..2f863ba4d9 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PmdParametersParseResult.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PmdParametersParseResult.java @@ -114,13 +114,16 @@ public final class PmdParametersParseResult { 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 (null == result.getSourceDir() + 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 (-filelist)."); + "Please provide a parameter for source root directory (--dir or -d), database URI (--uri or -u), or file list path (--file-list)."); } } diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java index 48c9bc3ee3..fdb2a97706 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java @@ -36,6 +36,8 @@ public class BinaryDistributionIT extends AbstractBinaryDistributionTest { } } + private final String srcDir = new File(".", "src/test/resources/sample-source/java/").getAbsolutePath(); + @Test public void testFileExistence() { assertTrue(getBinaryDistribution().exists()); @@ -75,27 +77,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, "", " Date: Sat, 7 May 2022 19:33:29 +0200 Subject: [PATCH 07/18] release notes --- docs/pages/release_notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 647a57daf2..9c87026392 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -29,6 +29,8 @@ pmd -d src/*/java -R rset*.xml ### Fixed Issues +* cli + * [#1445](https://github.com/pmd/pmd/issues/1445): \[core] Allow CLI to take globs as parameters * javascript * [#3948](https://github.com/pmd/pmd/issues/3948): \[js] Invalid operator error for method property in object literal From 8d7074dbaa5d2ce5d921788a5cdac401f01e3161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 8 May 2022 15:17:40 +0200 Subject: [PATCH 08/18] Improve doc for parameters --- docs/pages/pmd/userdocs/cli_reference.md | 10 ++--- docs/pages/release_notes.md | 1 + .../sourceforge/pmd/cli/PMDParameters.java | 42 +++++++++++++++---- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/docs/pages/pmd/userdocs/cli_reference.md b/docs/pages/pmd/userdocs/cli_reference.md index 0a27287864..69a29d966d 100644 --- a/docs/pages/pmd/userdocs/cli_reference.md +++ b/docs/pages/pmd/userdocs/cli_reference.md @@ -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." diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 9c87026392..dea79b1d19 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -26,6 +26,7 @@ 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 list as argument to these options. ### Fixed Issues diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java index fd4c8408e1..18c1da8a28 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java @@ -30,21 +30,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.", + @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 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.", variableArity = true) + @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 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.") @@ -106,12 +129,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.") From 402939f9cc928fddab8a72df85993718cc610cd8 Mon Sep 17 00:00:00 2001 From: Luke Lukes <45536418+lukelukes@users.noreply.github.com> Date: Tue, 10 May 2022 10:13:30 +0300 Subject: [PATCH 09/18] [java] ImmutableField: fix mockito/spring false positives --- .../java/rule/design/ImmutableFieldRule.java | 13 ++++++++++ .../java/rule/design/xml/ImmutableField.xml | 26 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java index 76fb6639f1..69baff8219 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java @@ -4,6 +4,8 @@ package net.sourceforge.pmd.lang.java.rule.design; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -41,6 +43,17 @@ public class ImmutableFieldRule extends AbstractLombokAwareRule { CHECKDECL } + @Override + protected Collection defaultSuppressionAnnotations() { + Collection defaultValues = new ArrayList<>(super.defaultSuppressionAnnotations()); + defaultValues.add("org.mockito.Mock"); + defaultValues.add("org.mockito.InjectMocks"); + defaultValues.add("org.springframework.beans.factory.annotation.Autowired"); + defaultValues.add("org.springframework.boot.test.mock.mockito.MockBean"); + + return defaultValues; + } + @Override public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { Object result = super.visit(node, data); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml index 359a1ce214..2b645e9839 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml @@ -569,6 +569,32 @@ public class ExampleImmutableField { this.str = strLocal+"123"; } } +} + ]]> + + + + #3874 [java] ImmutableField - false positive when using field setter annotations + 0 + From dc512e8a04cb4a6fbb74e16c737ac204394b11a2 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 12 May 2022 17:33:54 +0200 Subject: [PATCH 10/18] [ci] Update gems - update pmdtester from 1.5.0 to 1.5.1 - update nokogiri from 1.13.5 to 1.13.6 - update activesupport from 6.0.4.8 to 6.0.5 --- Gemfile.lock | 4 ++-- docs/Gemfile.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index f20255105a..b41e9645e9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -68,14 +68,14 @@ GEM multipart-post (2.1.1) nap (1.1.0) no_proxy_fix (0.1.2) - nokogiri (1.13.5) + nokogiri (1.13.6) mini_portile2 (~> 2.8.0) racc (~> 1.4) octokit (4.22.0) faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) open4 (1.3.4) - pmdtester (1.5.0) + pmdtester (1.5.1) differ (~> 0.1) liquid (~> 5.2) logger-colors (~> 1.0) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 020814c547..af044ad8d5 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - activesupport (6.0.4.8) + activesupport (6.0.5) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -232,7 +232,7 @@ GEM jekyll-seo-tag (~> 2.1) minitest (5.15.0) multipart-post (2.1.1) - nokogiri (1.13.5) + nokogiri (1.13.6) mini_portile2 (~> 2.8.0) racc (~> 1.4) octokit (4.22.0) From 9d23d79802a963e4a4edee8ec7cfcf61cc1f4155 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 18:40:05 +0200 Subject: [PATCH 11/18] [ci] regression test - skip patching/building spring The regression tester now does not anymore execute a "git reset"... and the patched files stay in place in the github actions cache. --- .ci/files/project-list.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.ci/files/project-list.xml b/.ci/files/project-list.xml index 3ecd924ece..ce357698bc 100644 --- a/.ci/files/project-list.xml +++ b/.ci/files/project-list.xml @@ -40,6 +40,11 @@ mvn dependency:build-classpath -DincludeScope=test -Dmdep.outputFile=classpath.t .*/build/generated-sources/.* classpath.txt ]]> From 2daa3381b4f646ca0b862998d12bb598ebe62a34 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 May 2022 09:06:29 +0200 Subject: [PATCH 12/18] [doc] Update release notes (#3874, #3964) --- docs/pages/release_notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index c31a705241..b8bd840b4c 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,6 +16,8 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues +* 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 @@ -23,5 +25,7 @@ This is a {{ site.pmd.release_type }} release. ### External Contributions +* [#3964](https://github.com/pmd/pmd/pull/3964): \[java] Fix #3874 - ImmutableField: fix mockito/spring false positives - [@lukelukes](https://github.com/lukelukes) + {% endtocmaker %} From 8a99dee9117769486c71c4f05e7beda8f865b488 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 May 2022 09:08:05 +0200 Subject: [PATCH 13/18] [java] Update test case (ImmutableField) --- .../pmd/lang/java/rule/design/xml/ImmutableField.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml index 2b645e9839..b6f6bfb687 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/ImmutableField.xml @@ -574,7 +574,7 @@ public class ExampleImmutableField { - #3874 [java] ImmutableField - false positive when using field setter annotations + #3874 [java] ImmutableField reports fields annotated with @Autowired (Spring) and @Mock (Mockito) 0 From d9fce6107e8228fd022e495bb61f67fc36245f75 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 May 2022 09:26:11 +0200 Subject: [PATCH 14/18] Add @lukelukes as a contributor --- .all-contributorsrc | 9 +++++++++ docs/pages/pmd/projectdocs/credits.md | 25 +++++++++++++------------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index dcac68bf60..f5d880797e 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -6639,6 +6639,15 @@ "contributions": [ "code" ] + }, + { + "login": "lukelukes", + "name": "lukelukes", + "avatar_url": "https://avatars.githubusercontent.com/u/45536418?v=4", + "profile": "https://github.com/lukelukes", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index 3f6b6213cf..b2efb5841c 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -835,112 +835,113 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
lpeddy

πŸ›
lujiefsi

πŸ’» +
lukelukes

πŸ’»
lyriccoder

πŸ›
marcelmore

πŸ›
matchbox

πŸ›
matthiaskraaz

πŸ› -
meandonlyme

πŸ› +
meandonlyme

πŸ›
mikesive

πŸ›
milossesic

πŸ›
mriddell95

πŸ›
mrlzh

πŸ›
msloan

πŸ›
mucharlaravalika

πŸ› -
mvenneman

πŸ› +
mvenneman

πŸ›
nareshl119

πŸ›
nicolas-harraudeau-sonarsource

πŸ›
noerremark

πŸ›
novsirion

πŸ›
oggboy

πŸ›
oinume

πŸ› -
orimarko

πŸ’» πŸ› +
orimarko

πŸ’» πŸ›
pallavi agarwal

πŸ›
parksungrin

πŸ›
patpatpat123

πŸ›
patriksevallius

πŸ›
pbrajesh1

πŸ›
phoenix384

πŸ› -
piotrszymanski-sc

πŸ’» +
piotrszymanski-sc

πŸ’»
plan3d

πŸ›
poojasix

πŸ›
prabhushrikant

πŸ›
pujitha8783

πŸ›
r-r-a-j

πŸ›
raghujayjunk

πŸ› -
rajeshveera

πŸ› +
rajeshveera

πŸ›
rajeswarreddy88

πŸ›
recdevs

πŸ›
reudismam

πŸ’» πŸ›
rijkt

πŸ›
rillig-tk

πŸ›
rmohan20

πŸ’» πŸ› -
rxmicro

πŸ› +
rxmicro

πŸ›
ryan-gustafson

πŸ’» πŸ›
sabi0

πŸ›
scais

πŸ›
sebbASF

πŸ›
sergeygorbaty

πŸ’»
shilko2013

πŸ› -
simeonKondr

πŸ› +
simeonKondr

πŸ›
snajberk

πŸ›
sniperrifle2004

πŸ›
snuyanzin

πŸ› πŸ’»
sratz

πŸ›
stonio

πŸ›
sturton

πŸ’» πŸ› -
sudharmohan

πŸ› +
sudharmohan

πŸ›
suruchidawar

πŸ›
svenfinitiv

πŸ›
tashiscool

πŸ›
test-git-hook

πŸ›
testation21

πŸ’» πŸ›
thanosa

πŸ› -
tiandiyixian

πŸ› +
tiandiyixian

πŸ›
tobwoerk

πŸ›
tprouvot

πŸ›
trentchilders

πŸ›
triandicAnt

πŸ›
trishul14

πŸ›
tsui

πŸ› -
winhkey

πŸ› +
winhkey

πŸ›
witherspore

πŸ›
wjljack

πŸ›
wuchiuwong

πŸ›
xingsong

πŸ›
xioayuge

πŸ›
xnYi9wRezm

πŸ’» πŸ› -
xuanuy

πŸ› +
xuanuy

πŸ›
xyf0921

πŸ›
yalechen-cyw3

πŸ›
yasuharu-sato

πŸ›
zenglian

πŸ›
zgrzyt93

πŸ’» πŸ›
zh3ng

πŸ› -
zt_soft

πŸ› +
zt_soft

πŸ›
ztt79

πŸ›
zzzzfeng

πŸ›
ÁrpÑd MagosÑnyi

πŸ› From 77369804755c5e328c4082744c755391c58fc0c4 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 May 2022 09:51:45 +0200 Subject: [PATCH 15/18] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ClΓ©ment Fournier --- .../sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java index 702e6605d4..4568a28d35 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/ElementNode.java @@ -81,6 +81,9 @@ public class ElementNode extends BaseNodeInfo implements AstNodeOwner { } 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; @@ -158,7 +161,7 @@ public class ElementNode extends BaseNodeInfo implements AstNodeOwner { @Override public String getStringValue() { - if (determineType(getUnderlyingNode()) == Type.TEXT) { + if (getNodeKind() == Type.TEXT || getNodeKind() == Type.COMMENT) { return getUnderlyingNode().getImage(); } return ""; From 85095f19d3a60f233d4313059d7a8c0aebd5ad0b Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 May 2022 09:54:48 +0200 Subject: [PATCH 16/18] [html] Added test case to verify #text doesn't find text nodes anymore --- .../net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java index 1a6272dab8..404b110251 100644 --- a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java +++ b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java @@ -42,6 +42,14 @@ public class HtmlXPathRuleTest { Assert.assertEquals(3, report.getViolations().get(0).getBeginLine()); } + @Test + public void selectTextNodeByNodeNameShouldNotWork() { + String xpath = "//*[local-name() = '#text'][contains(@Text, '{ ')]"; + + Report report = runXPath(LIGHTNING_WEB_COMPONENT, xpath); + Assert.assertEquals(0, report.getViolations().size()); + } + @Test public void verifyTextNodeName() { ASTHtmlDocument document = HtmlParsingHelper.DEFAULT.parse("

foobar

"); From 1a596693fdf37b7289bc085c332c822c299db115 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 May 2022 09:56:49 +0200 Subject: [PATCH 17/18] [html] Added test case to verify #text doesn't find text nodes anymore --- .../java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java index 404b110251..1c9f81b1ca 100644 --- a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java +++ b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/HtmlXPathRuleTest.java @@ -44,8 +44,7 @@ public class HtmlXPathRuleTest { @Test public void selectTextNodeByNodeNameShouldNotWork() { - String xpath = "//*[local-name() = '#text'][contains(@Text, '{ ')]"; - + String xpath = "//*[local-name() = '#text']"; Report report = runXPath(LIGHTNING_WEB_COMPONENT, xpath); Assert.assertEquals(0, report.getViolations().size()); } From fd7cae278e35a36719ae867d3e065b18a50c1336 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 May 2022 14:24:42 +0200 Subject: [PATCH 18/18] [doc] Update release notes (#3955) --- docs/pages/release_notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index c31a705241..d565716926 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,6 +16,8 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues +* html + * [#3955](https://github.com/pmd/pmd/pull/3955): \[html] Improvements for handling text and comment nodes * javascript * [#3948](https://github.com/pmd/pmd/issues/3948): \[js] Invalid operator error for method property in object literal