From a95c67c31e8b398a5805b6eadbe3a3ceedc30d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 17 Sep 2020 21:58:00 +0200 Subject: [PATCH 01/17] Upgrade to kotlin 1.4.1 and kotest 4.3.0 --- .../pmd/lang/java/ast/ParserTestSpec.kt | 24 +++++++++---------- pmd-lang-test/pom.xml | 24 +------------------ .../pmd/lang/ast/test/IntelliMarker.kt | 21 ++++++++++++++++ pom.xml | 6 ++--- 4 files changed, 37 insertions(+), 38 deletions(-) create mode 100644 pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/IntelliMarker.kt diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ParserTestSpec.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ParserTestSpec.kt index 3e0d8aabe7..5239e33f65 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ParserTestSpec.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ParserTestSpec.kt @@ -4,17 +4,17 @@ package net.sourceforge.pmd.lang.java.ast -import io.kotest.core.config.Project -import io.kotest.core.spec.style.DslDrivenSpec +import io.kotest.core.config.configuration +import io.kotest.core.spec.DslDrivenSpec import io.kotest.core.spec.style.scopes.Lifecycle import io.kotest.core.spec.style.scopes.RootScope import io.kotest.core.spec.style.scopes.RootTestRegistration import io.kotest.core.test.TestCaseConfig import io.kotest.core.test.TestContext -import io.kotest.core.test.TestName import io.kotest.core.test.TestType -import io.kotest.runner.junit.platform.IntelliMarker +import io.kotest.core.test.createTestName import net.sourceforge.pmd.lang.ast.test.Assertions +import net.sourceforge.pmd.lang.ast.test.IntelliMarker import io.kotest.matchers.should as kotlintestShould /** @@ -33,11 +33,15 @@ abstract class ParserTestSpec(body: ParserTestSpec.() -> Unit) : DslDrivenSpec() override fun lifecycle(): Lifecycle = Lifecycle.from(this) override fun defaultConfig(): TestCaseConfig = actualDefaultConfig() + override fun defaultTestCaseConfig(): TestCaseConfig? = defaultTestConfig override fun registration(): RootTestRegistration = RootTestRegistration.from(this) + private fun actualDefaultConfig() = + defaultTestConfig ?: defaultTestCaseConfig() ?: configuration.defaultTestConfig + fun test(name: String, disabled: Boolean = false, test: suspend TestContext.() -> Unit) = registration().addTest( - name = TestName(name), + name = createTestName(name), xdisabled = disabled, test = test, config = actualDefaultConfig() @@ -63,7 +67,7 @@ abstract class ParserTestSpec(body: ParserTestSpec.() -> Unit) : DslDrivenSpec() disabled: Boolean = false, spec: suspend GroupTestCtx.() -> Unit) = registration().addContainerTest( - name = TestName(name), + name = createTestName(name), test = { GroupTestCtx(this).spec() }, xdisabled = disabled ) @@ -119,24 +123,20 @@ abstract class ParserTestSpec(body: ParserTestSpec.() -> Unit) : DslDrivenSpec() assertions: ParserTestCtx.() -> Unit) { context.registerTestCase( - name = TestName(name), + name = createTestName(name), test = { ParserTestCtx(javaVersion).assertions() }, config = actualDefaultConfig(), type = TestType.Test ) } - private fun actualDefaultConfig() = - defaultTestConfig ?: defaultTestCaseConfig() - ?: Project.testCaseConfig() - inner class GroupTestCtx(private val context: TestContext) { suspend fun onVersions(javaVersions: List, spec: suspend VersionedTestCtx.() -> Unit) { javaVersions.forEach { javaVersion -> context.registerTestCase( - name = TestName("Java ${javaVersion.pmdName}"), + name = createTestName("Java ${javaVersion.pmdName}"), test = { VersionedTestCtx(this, javaVersion).spec() }, config = actualDefaultConfig(), type = TestType.Container diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index c4c752a486..aaa4f717df 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -13,7 +13,6 @@ net.sourceforge.pmd pmd 6.30.0-SNAPSHOT - ../ @@ -62,32 +61,11 @@ package - - dokka + javadocJar - - org.apache.maven.plugins - maven-jar-plugin - - - kotlin-javadoc - package - - jar - - - ${project.build.directory}/dokka/pmd-lang-test - javadoc - - - - diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/IntelliMarker.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/IntelliMarker.kt new file mode 100644 index 0000000000..d7ad20eea0 --- /dev/null +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/IntelliMarker.kt @@ -0,0 +1,21 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.ast.test + + +import org.junit.jupiter.api.TestFactory +import org.junit.jupiter.api.condition.EnabledIfSystemProperty + +/** + * This is to trick Intellij into making subclasses executable (because of @TestFactory). + * But Junit does not use it because of the unsatisfiable condition. This comes from + * Kotest, but was removed in 4.2.0 without explanation. + */ +interface IntelliMarker { + @EnabledIfSystemProperty(named = "wibble", matches = "wobble") + @TestFactory + fun primer() { + } +} diff --git a/pom.xml b/pom.xml index 2463eb14aa..2804bb2b45 100644 --- a/pom.xml +++ b/pom.xml @@ -85,9 +85,9 @@ ${maven.compiler.test.target} - 1.3.72 - 4.1.2 - 0.10.1 + 1.4.10 + 4.3.0 + 1.4.10.2 5.0 From c21784843c57647a36613476a02b98805bab5d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 17:47:48 +0100 Subject: [PATCH 02/17] Check XPath expression result for correct type Fixes #1939 --- .../lang/rule/xpath/SaxonXPathRuleQuery.java | 16 ++++++---------- .../rule/xpath/SaxonXPathRuleQueryTest.java | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java index 4bcb8f7423..b1456b5754 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java @@ -120,25 +120,21 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { assert rootElementNode != null : "Cannot find " + node; final XPathDynamicContext xpathDynamicContext = createDynamicContext(rootElementNode); - final List nodes = new LinkedList<>(); + final List results = new LinkedList<>(); List expressions = getXPathExpressionForNodeOrDefault(node.getXPathNodeName()); for (Expression expression : expressions) { SequenceIterator iterator = expression.iterate(xpathDynamicContext.getXPathContextObject()); Item current = iterator.next(); while (current != null) { - nodes.add((ElementNode) current); + if (current instanceof ElementNode) { + results.add((Node) ((ElementNode) current).getUnderlyingNode()); + } else { + throw new RuntimeException("XPath rule expression returned a non-node (" + current.getClass() + "): " + current); + } current = iterator.next(); } } - /* - Map List of Saxon Nodes -> List of AST Nodes, which were detected to match the XPath expression - (i.e. violation found) - */ - final List results = new ArrayList<>(nodes.size()); - for (final ElementNode elementNode : nodes) { - results.add((Node) elementNode.getUnderlyingNode()); - } Collections.sort(results, RuleChainAnalyzer.documentOrderComparator()); return results; } catch (final XPathException e) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java index 0920d7c4e4..457ccdd6a0 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java @@ -9,8 +9,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.hamcrest.CoreMatchers; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.ast.DummyNodeWithListAndEnum; @@ -22,6 +25,9 @@ import net.sf.saxon.expr.Expression; public class SaxonXPathRuleQueryTest { + @Rule + public final ExpectedException expected = ExpectedException.none(); + @Test public void testListAttribute() { DummyNodeWithListAndEnum dummy = new DummyNodeWithListAndEnum(1); @@ -37,6 +43,18 @@ public class SaxonXPathRuleQueryTest { assertQuery(0, "//dummyNode[@EmptyList = (\"A\")]", dummy); } + @Test + public void testInvalidReturn() { + DummyNodeWithListAndEnum dummy = new DummyNodeWithListAndEnum(1); + + + expected.expect(RuntimeException.class); + expected.expectMessage(CoreMatchers.containsString("XPath rule expression returned a non-node")); + expected.expectMessage(CoreMatchers.containsString("Int64Value")); + + createQuery("1+2").evaluate(dummy, new RuleContext()); + } + @Test public void ruleChainVisits() { SaxonXPathRuleQuery query = createQuery("//dummyNode[@Image='baz']/foo | //bar[@Public = 'true'] | //dummyNode[@Public = false()] | //dummyNode"); From 7a8ca28c3f7cf3e895fc106f9496eeb7567e6c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 17:54:33 +0100 Subject: [PATCH 03/17] Check result of / expression Refs #1938 --- .../pmd/lang/ast/xpath/internal/AstNodeOwner.java | 15 +++++++++++++++ .../pmd/lang/ast/xpath/saxon/DocumentNode.java | 10 +++++++++- .../pmd/lang/ast/xpath/saxon/ElementNode.java | 5 +++-- .../pmd/lang/rule/xpath/SaxonXPathRuleQuery.java | 5 +++-- .../lang/rule/xpath/SaxonXPathRuleQueryTest.java | 12 +++++++++++- 5 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/AstNodeOwner.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/AstNodeOwner.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/AstNodeOwner.java new file mode 100644 index 0000000000..3d7f3a7f7e --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/internal/AstNodeOwner.java @@ -0,0 +1,15 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.ast.xpath.internal; + +import net.sourceforge.pmd.lang.ast.Node; + +/** + * Marker interface. + */ +public interface AstNodeOwner { + + Node getUnderlyingNode(); +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java index d91f1828a6..23d99fb778 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java @@ -10,6 +10,7 @@ import java.util.Map; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.internal.AstNodeOwner; import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttrLogger; import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery; @@ -27,7 +28,7 @@ import net.sf.saxon.type.Type; */ @Deprecated @InternalApi -public class DocumentNode extends BaseNodeInfo implements DocumentInfo { +public class DocumentNode extends BaseNodeInfo implements DocumentInfo, AstNodeOwner { /** * The root ElementNode of the DocumentNode. @@ -99,6 +100,13 @@ public class DocumentNode extends BaseNodeInfo implements DocumentInfo { } } + @Override + public Node getUnderlyingNode() { + // this is a concession to the model, so that the expression "/" + // may be interpreted as the root node + return rootNode.getUnderlyingNode(); + } + public DeprecatedAttrLogger getAttrCtx() { return attrCtx == null ? DeprecatedAttrLogger.noop() : attrCtx; } 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 6db157eac4..e9341542ea 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 @@ -11,6 +11,7 @@ import java.util.Map; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.xpath.Attribute; +import net.sourceforge.pmd.lang.ast.xpath.internal.AstNodeOwner; import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery; import net.sf.saxon.om.Axis; @@ -38,7 +39,7 @@ import net.sf.saxon.value.Value; */ @Deprecated @InternalApi -public class ElementNode extends BaseNodeInfo { +public class ElementNode extends BaseNodeInfo implements AstNodeOwner { protected final DocumentNode document; protected final ElementNode parent; @@ -94,7 +95,7 @@ public class ElementNode extends BaseNodeInfo { } @Override - public Object getUnderlyingNode() { + public Node getUnderlyingNode() { return node; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java index b1456b5754..2a8815798c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQuery.java @@ -17,6 +17,7 @@ import java.util.regex.Pattern; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.xpath.internal.AstNodeOwner; import net.sourceforge.pmd.lang.ast.xpath.internal.DeprecatedAttrLogger; import net.sourceforge.pmd.lang.ast.xpath.saxon.DocumentNode; import net.sourceforge.pmd.lang.ast.xpath.saxon.ElementNode; @@ -126,8 +127,8 @@ public class SaxonXPathRuleQuery extends AbstractXPathRuleQuery { SequenceIterator iterator = expression.iterate(xpathDynamicContext.getXPathContextObject()); Item current = iterator.next(); while (current != null) { - if (current instanceof ElementNode) { - results.add((Node) ((ElementNode) current).getUnderlyingNode()); + if (current instanceof AstNodeOwner) { + results.add(((AstNodeOwner) current).getUnderlyingNode()); } else { throw new RuntimeException("XPath rule expression returned a non-node (" + current.getClass() + "): " + current); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java index 457ccdd6a0..e2be132092 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java @@ -16,6 +16,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.lang.ast.DummyNode; import net.sourceforge.pmd.lang.ast.DummyNodeWithListAndEnum; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -55,6 +56,14 @@ public class SaxonXPathRuleQueryTest { createQuery("1+2").evaluate(dummy, new RuleContext()); } + @Test + public void testRootExpression() { + DummyNode dummy = new DummyNode(); // todo in pmd 7 this should be a RootNode + + List result = assertQuery(1, "/", dummy); + Assert.assertEquals(dummy, result.get(0)); + } + @Test public void ruleChainVisits() { SaxonXPathRuleQuery query = createQuery("//dummyNode[@Image='baz']/foo | //bar[@Public = 'true'] | //dummyNode[@Public = false()] | //dummyNode"); @@ -193,10 +202,11 @@ public class SaxonXPathRuleQueryTest { assertExpression("((DocumentSorter(((((/)/descendant::element(dummyNode, xs:anyType))[QuantifiedExpression(Atomizer(attribute::attribute(Image, xs:anyAtomicType)), ($qq:qq692331943 singleton eq \"baz\"))])/child::element(foo, xs:anyType))) | (((/)/descendant::element(bar, xs:anyType))[QuantifiedExpression(Atomizer(attribute::attribute(Public, xs:anyAtomicType)), ($qq:qq2127036371 singleton eq \"true\"))])) | (((/)/descendant::element(dummyNode, xs:anyType))[QuantifiedExpression(Atomizer(attribute::attribute(Public, xs:anyAtomicType)), ($qq:qq1529060733 singleton eq \"false\"))]))", query.nodeNameToXPaths.get(SaxonXPathRuleQuery.AST_ROOT).get(0)); } - private static void assertQuery(int resultSize, String xpath, Node node) { + private static List assertQuery(int resultSize, String xpath, Node node) { SaxonXPathRuleQuery query = createQuery(xpath); List result = query.evaluate(node, new RuleContext()); Assert.assertEquals(resultSize, result.size()); + return result; } private static SaxonXPathRuleQuery createQuery(String xpath, PropertyDescriptor ...descriptors) { From 0a4dd810c9901cb4a80219b7e7e1938805c573ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 17:57:42 +0100 Subject: [PATCH 04/17] Test remaining cases of #1938 --- .../pmd/lang/ast/xpath/saxon/DocumentNode.java | 2 ++ .../rule/xpath/SaxonXPathRuleQueryTest.java | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java index 23d99fb778..65c5ecec8b 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/xpath/saxon/DocumentNode.java @@ -95,6 +95,8 @@ public class DocumentNode extends BaseNodeInfo implements DocumentInfo, AstNodeO return new Navigator.DescendantEnumeration(this, true, true); case Axis.CHILD: return SingleNodeIterator.makeIterator(rootNode); + case Axis.SELF: + return SingleNodeIterator.makeIterator(this); default: return super.iterateAxis(axisNumber); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java index e2be132092..bfe925bac3 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/SaxonXPathRuleQueryTest.java @@ -64,6 +64,24 @@ public class SaxonXPathRuleQueryTest { Assert.assertEquals(dummy, result.get(0)); } + @Test + public void testRootExpressionIsADocumentNode() { + DummyNode dummy = new DummyNode(); // todo in pmd 7 this should be a RootNode + + List result = assertQuery(1, "(/)[self::document-node()]", dummy); + Assert.assertEquals(dummy, result.get(0)); + } + + @Test + public void testRootExpressionWithName() { + DummyNode dummy = new DummyNode(0, false, "DummyNodeA"); // todo in pmd 7 this should be a RootNode + + List result = assertQuery(1, "(/)[self::document-node(element(DummyNodeA))]", dummy); + Assert.assertEquals(dummy, result.get(0)); + + assertQuery(0, "(/)[self::document-node(element(DummyNodeX))]", dummy); + } + @Test public void ruleChainVisits() { SaxonXPathRuleQuery query = createQuery("//dummyNode[@Image='baz']/foo | //bar[@Public = 'true'] | //dummyNode[@Public = false()] | //dummyNode"); From 27441ae3dcc5c3e05dc93fa2726f086e4c467a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 18:30:21 +0100 Subject: [PATCH 05/17] Document #1938 in migration guide --- .../pmd/userdocs/extending/writing_xpath_rules.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/pages/pmd/userdocs/extending/writing_xpath_rules.md b/docs/pages/pmd/userdocs/extending/writing_xpath_rules.md index 5b8f886623..a24a512cf7 100644 --- a/docs/pages/pmd/userdocs/extending/writing_xpath_rules.md +++ b/docs/pages/pmd/userdocs/extending/writing_xpath_rules.md @@ -127,6 +127,18 @@ represented by our 1.0 implementation as strings, meaning that `@BeginLine > "1" worked ---that's not the case in 2.0 mode. * @ArgumentCount > '1' → `@ArgumentCount > 1` +* In XPath 1.0, the expression `/Foo` matches the *children* of the root named `Foo`. +In XPath 2.0, that expression matches the root, if it is named `Foo`. Consider the following tree: +```java +Foo +└─ Foo +└─ Foo +``` +Then `/Foo` will match the root in XPath 2, and the other nodes (but not the root) in XPath 1. +See eg [an issue caused by this](https://github.com/pmd/pmd/issues/1919#issuecomment-512865434) in Apex, +with nested classes. + + ## Rule properties **See [Defining rule properties](pmd_userdocs_extending_defining_properties.html#for-xpath-rules)** From ddcf3536b438c4e7ec8e1ce85a07e2f9bc8c3dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 26 Oct 2020 18:32:53 +0100 Subject: [PATCH 06/17] Update release notes, refs #1939 --- 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 b8f8783555..973e2dd715 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,6 +16,10 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues +- pmd-core + - [#1939](https://github.com/pmd/pmd/issues/1939) \[core] XPath expressions return handling + + ### API Changes ### External Contributions From 9b81f943381f9357bcd3775195f3c16c921fe76a Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 27 Oct 2020 15:34:38 +0100 Subject: [PATCH 07/17] [ci] Update travis build badge After move to travis-ci.com --- BUILDING.md | 2 +- README.md | 2 +- do-release.sh | 2 +- docs/pages/pmd/devdocs/development.md | 2 +- docs/pages/pmd/projectdocs/committers/releasing.md | 2 +- pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 522608f37a..bfa7c16245 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -25,7 +25,7 @@ limitations apply: * Generally give **different results on Windows and Unix** because of different newlines. (carriage return linefeed on Windows, linefeed on Unixes). - We build our releases under **Linux** on [Travis CI](https://travis-ci.org/pmd/pmd). + We build our releases under **Linux** on [Travis CI](https://travis-ci.com/pmd/pmd). * Generally depend on the **major version of the JDK** used to compile. (Even with source/target defined, each major JDK version changes the generated bytecode.). diff --git a/README.md b/README.md index f9e7e67a02..a1bed340d3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # PMD [![Join the chat at https://gitter.im/pmd/pmd](https://badges.gitter.im/pmd/pmd.svg)](https://gitter.im/pmd/pmd?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://travis-ci.org/pmd/pmd.svg?branch=master)](https://travis-ci.org/pmd/pmd) +[![Build Status](https://travis-ci.com/pmd/pmd.svg?branch=master)](https://travis-ci.com/pmd/pmd) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.sourceforge.pmd/pmd/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.sourceforge.pmd/pmd) [![Reproducible Builds](https://img.shields.io/badge/Reproducible_Builds-ok-green?labelColor=blue)](https://github.com/jvm-repo-rebuild/reproducible-central#net.sourceforge.pmd:pmd) [![Coverage Status](https://coveralls.io/repos/github/pmd/pmd/badge.svg)](https://coveralls.io/github/pmd/pmd) diff --git a/do-release.sh b/do-release.sh index b5a36b66a1..fa8617e1a4 100755 --- a/do-release.sh +++ b/do-release.sh @@ -163,7 +163,7 @@ git commit -a -m "Prepare pmd release ${RELEASE_VERSION}" echo -echo "Tag has been pushed.... now check travis build: " +echo "Tag has been pushed.... now check travis build: " echo echo echo "Press enter to continue..." diff --git a/docs/pages/pmd/devdocs/development.md b/docs/pages/pmd/devdocs/development.md index 450a47cda2..f7e47c89fd 100644 --- a/docs/pages/pmd/devdocs/development.md +++ b/docs/pages/pmd/devdocs/development.md @@ -18,7 +18,7 @@ The complete source code can be found on github: ## Continuous Integration -We use [Travis CI](https://travis-ci.org/pmd) as our ci service. The main repo and the eclipse plugin are built for +We use [Travis CI](https://travis-ci.com/pmd) as our ci service. The main repo and the eclipse plugin are built for every push. Each pull request is built as well. The maven snapshot artifacts are deployed at [Sonatypes OSS snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/net/sourceforge/pmd/pmd/). diff --git a/docs/pages/pmd/projectdocs/committers/releasing.md b/docs/pages/pmd/projectdocs/committers/releasing.md index e0cfe8a22f..f64b93b896 100644 --- a/docs/pages/pmd/projectdocs/committers/releasing.md +++ b/docs/pages/pmd/projectdocs/committers/releasing.md @@ -6,7 +6,7 @@ author: Romain Pelisse , Andreas Dangel https://pmd.github.io/ - https://travis-ci.org/pmd/pmd + https://travis-ci.com/pmd/pmd 2002 From edc33e6927db41467fc4857076e968c98eb95b6b Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 26 Oct 2020 17:44:04 +0100 Subject: [PATCH 08/17] [ci] Update install-openjdk to always use latest jdk This change will download openjdk from fixed URLs so that we don't need to update the script everytime a new jdk version is relased. --- .travis.yml | 2 +- .travis/install-openjdk.sh | 28 +++++++++++++++------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5ff4e3b8b8..c2d57d75f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,7 @@ jobs: env: BUILD=publish before_install: - - bash .travis/before_install.sh "11.0.8+10" + - bash .travis/before_install.sh "11" - source ${HOME}/java.env install: true before_script: true diff --git a/.travis/install-openjdk.sh b/.travis/install-openjdk.sh index 1e07be76e9..af59870c50 100644 --- a/.travis/install-openjdk.sh +++ b/.travis/install-openjdk.sh @@ -2,36 +2,38 @@ set -e # -# AdoptOpenJDK Builds from: -# https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/tag/jdk-11.0.4%2B11 +# Downloads AdoptOpenJDK Builds from +# https://pmd-code.org/openjdk/latest/jdk-11-linux64.tar.gz +# https://pmd-code.org/openjdk/latest/jdk-11-windows64.zip +# https://pmd-code.org/openjdk/latest/jdk-11-mac64.tar.gz +# +# The Build are originally from: +# https://github.com/AdoptOpenJDK/openjdk11-binaries/releases # source .travis/logger.sh source .travis/common-functions.sh -# VERSION_TAG e.g. "11.0.4+11" or "13+33" -VERSION_TAG=$1 -OPENJDK_MAJOR=${VERSION_TAG/.*/} -OPENJDK_MAJOR=${OPENJDK_MAJOR/+*/} -#BASE_URL=https://github.com/AdoptOpenJDK/openjdk${OPENJDK_MAJOR}-binaries/releases/download -BASE_URL=https://pmd-code.org/openjdk +# OPENJDK_VERSION e.g. "11" +OPENJDK_VERSION=$1 +BASE_URL=https://pmd-code.org/openjdk/latest/jdk-${OPENJDK_VERSION}- -log_info "Installing OpenJDK${OPENJDK_MAJOR}U ${VERSION_TAG} for ${TRAVIS_OS_NAME}" +log_info "Installing OpenJDK${OPENJDK_VERSION} for ${TRAVIS_OS_NAME}" if travis_isOSX; then - DOWNLOAD_URL=${BASE_URL}/jdk-${VERSION_TAG/+/%2B}/OpenJDK${OPENJDK_MAJOR}U-jdk_x64_mac_hotspot_${VERSION_TAG/+/_}.tar.gz + DOWNLOAD_URL=${BASE_URL}mac64.tar.gz COMPONENTS_TO_STRIP=3 # e.g. jdk-11.0.3+7/Contents/Home/bin/java elif travis_isWindows; then - DOWNLOAD_URL=${BASE_URL}/jdk-${VERSION_TAG/+/%2B}/OpenJDK${OPENJDK_MAJOR}U-jdk_x64_windows_hotspot_${VERSION_TAG/+/_}.zip + DOWNLOAD_URL=${BASE_URL}windows64.zip else - DOWNLOAD_URL=${BASE_URL}/jdk-${VERSION_TAG/+/%2B}/OpenJDK${OPENJDK_MAJOR}U-jdk_x64_linux_hotspot_${VERSION_TAG/+/_}.tar.gz + DOWNLOAD_URL=${BASE_URL}linux64.tar.gz COMPONENTS_TO_STRIP=1 # e.g. openjdk-11.0.3+7/bin/java fi OPENJDK_ARCHIVE=$(basename $DOWNLOAD_URL) LOCAL_DIR=${HOME}/.cache/openjdk -TARGET_DIR=${HOME}/openjdk${OPENJDK_MAJOR} +TARGET_DIR=${HOME}/openjdk${OPENJDK_VERSION} mkdir -p ${LOCAL_DIR} mkdir -p ${TARGET_DIR} From 398305144de585a083e89ff916fb8f1b9e517a33 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 26 Oct 2020 20:15:07 +0100 Subject: [PATCH 09/17] [ci] Display used java version in github action --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c38a847dfa..3222a0467a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,4 +27,4 @@ jobs: java-version: ${{ matrix.java }} - name: Build with mvnw run: | - ./mvnw clean install + ./mvnw -V clean install From ff6e5278f3208aa2b797f7b94bc2d3c895135a48 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 26 Oct 2020 17:46:05 +0100 Subject: [PATCH 10/17] [ci] Update pmd-tester, use auxclasspath This will test pmd/pmd-regression-tester#72 checkstyle: Add exclude patterns for checkstyle: after compilation, testresources appear now under target/test-classes and they don't need to be analyzed again. Also exclude generated-sources. --- .travis/before_install.sh | 40 +++++++++++++++++++------------- .travis/project-list.xml | 48 ++++++++++++++++++++++++++++++++++++++- Gemfile | 3 ++- Gemfile.lock | 30 ++++++++++++++---------- 4 files changed, 91 insertions(+), 30 deletions(-) diff --git a/.travis/before_install.sh b/.travis/before_install.sh index 4b0182f2cf..0f34538540 100644 --- a/.travis/before_install.sh +++ b/.travis/before_install.sh @@ -13,6 +13,24 @@ bash .travis/configure-maven.sh bash .travis/install-openjdk.sh $OPENJDK_VERSION +function install_jdk() { + LOCAL_DIR=$1 + TARGET_DIR=$2 + DOWNLOAD_URL=$3 + ARCHIVE=$(basename $DOWNLOAD_URL) + + mkdir -p ${LOCAL_DIR} + mkdir -p ${TARGET_DIR} + if [ ! -e ${LOCAL_DIR}/${ARCHIVE} ]; then + log_info "Downloading from ${DOWNLOAD_URL} to ${LOCAL_DIR}" + wget --directory-prefix ${LOCAL_DIR} --timestamping --continue ${DOWNLOAD_URL} + else + log_info "Skipped download, file ${LOCAL_DIR}/${ARCHIVE} already exists" + fi + log_info "Extracting to ${TARGET_DIR}" + tar --extract --file ${LOCAL_DIR}/${ARCHIVE} -C ${TARGET_DIR} --strip-components=1 +} + if travis_isLinux; then gem install bundler bundle config set --local path vendor/bundle @@ -20,23 +38,13 @@ if travis_isLinux; then bundle install # install jdk7 for integration test - LOCAL_DIR=${HOME}/.cache/jdk7 - TARGET_DIR=${HOME}/oraclejdk7 - JDK7_ARCHIVE=jdk-7u80-linux-x64.tar.gz - DOWNLOAD_URL=https://pmd-code.org/oraclejdk/${JDK7_ARCHIVE} - mkdir -p ${LOCAL_DIR} - mkdir -p ${TARGET_DIR} - if [ ! -e ${LOCAL_DIR}/${JDK7_ARCHIVE} ]; then - log_info "Downloading from ${DOWNLOAD_URL} to ${LOCAL_DIR}" - wget --directory-prefix ${LOCAL_DIR} --timestamping --continue ${DOWNLOAD_URL} - else - log_info "Skipped download, file ${LOCAL_DIR}/${JDK7_ARCHIVE} already exists" - fi - log_info "Extracting to ${TARGET_DIR}" - tar --extract --file ${LOCAL_DIR}/${JDK7_ARCHIVE} -C ${TARGET_DIR} --strip-components=1 - log_info "OracleJDK7 can be used via -Djava7.home=${TARGET_DIR}" + install_jdk "${HOME}/.cache/jdk7" "${HOME}/oraclejdk7" "https://pmd-code.org/oraclejdk/jdk-7u80-linux-x64.tar.gz" + log_info "OracleJDK7 can be used via -Djava7.home=${HOME}/oraclejdk7" + # install openjdk8 for pmd-regression-tests + install_jdk "${HOME}/.cache/openjdk" "${HOME}/openjdk8" "https://pmd-code.org/openjdk/latest/jdk-8-linux64.tar.gz" + log_info "OpenJDK8 can be used from ${HOME}/openjdk8" else - log_info "Not setting up ruby for ${TRAVIS_OS_NAME}." + log_info "Not setting up ruby and additional jvms for ${TRAVIS_OS_NAME}." exit 0 fi diff --git a/.travis/project-list.xml b/.travis/project-list.xml index 5471d6f2e3..600061f674 100644 --- a/.travis/project-list.xml +++ b/.travis/project-list.xml @@ -1,7 +1,7 @@ +xsi:noNamespaceSchemaLocation="projectlist_1_1_0.xsd"> Standard Projects @@ -9,6 +9,19 @@ xsi:noNamespaceSchemaLocation="projectlist_1_0_0.xsd"> git https://github.com/checkstyle/checkstyle checkstyle-8.10 + + .*/target/test-classes/com/puppycrawl/tools/checkstyle/.* + .*/target/generated-sources/.* + + + echo -n "$(pwd)/target/classes:$(pwd)/target/test-classes:"; cat classpath.txt @@ -16,6 +29,39 @@ xsi:noNamespaceSchemaLocation="projectlist_1_0_0.xsd"> git https://github.com/spring-projects/spring-framework v5.0.6.RELEASE + + > build.gradle < classpath.txt +]]> + cat classpath.txt + 0 + interceptors; + private int preProcessIndex = -1; + public void applyPreProcess(NativeWebRequest request, Callable task) throws Exception { + for (CallableProcessingInterceptor interceptor : this.interceptors) { + interceptor.preProcess(request, task); + this.preProcessIndex++; + } + } + } + ]]> + + From 01f1e8dede091846daedb7eda2b2742b4ee6c6e4 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Wed, 28 Oct 2020 16:53:45 +0100 Subject: [PATCH 15/17] Add back pom.parent.relativePath for pmd-lang-test --- pmd-lang-test/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index aaa4f717df..1f63a2c9ad 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -13,6 +13,7 @@ net.sourceforge.pmd pmd 6.30.0-SNAPSHOT + ../ From 3e23e6645e92d022bca4378c282712f94dcc1952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Wed, 28 Oct 2020 22:48:03 +0100 Subject: [PATCH 16/17] Fix release notes format Co-authored-by: Andreas Dangel --- docs/pages/release_notes.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 973e2dd715..1f2ee87b35 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -16,8 +16,8 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues -- pmd-core - - [#1939](https://github.com/pmd/pmd/issues/1939) \[core] XPath expressions return handling +* pmd-core + * [#1939](https://github.com/pmd/pmd/issues/1939): \[core] XPath expressions return handling ### API Changes @@ -25,4 +25,3 @@ This is a {{ site.pmd.release_type }} release. ### External Contributions {% endtocmaker %} - From 9bda5b368f09fa5dcf6cef326a73af20bf815399 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 29 Oct 2020 10:14:48 +0100 Subject: [PATCH 17/17] [ci] Remove jobs for mac and windows on travis Builds are executed by github actions and don't need to run on travis again. --- .travis.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index c2d57d75f4..34758b8d66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,13 +34,6 @@ jobs: dist: bionic env: BUILD=coveralls if: "type = push && repo = pmd/pmd && fork = false" - - name: "macosx - mvn verify" - os: osx - env: BUILD=deploy - - name: "windows - mvn verify" - os: windows - env: BUILD=deploy - language: shell - stage: publish name: "Release Build - Publish" os: linux