From de1368275381c8a1511574759113d5813990ba64 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 28 Apr 2022 12:53:28 +0200 Subject: [PATCH 01/54] [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 e9341542ead..ce9604fe798 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 ElementNode(DocumentNode document, 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 ElementNode(DocumentNode document, 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 Value atomize() { } @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 6c2c53e2f94..1a70e5c0fca 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 void selectAttributes() { 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 98f44b7e3f4abe75112361b5aa92a5db76db7603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 1 May 2022 16:00:25 +0200 Subject: [PATCH 02/54] Allow Phonetic Extensions block in java Fix #3423 --- pmd-java/etc/grammar/Java.jjt | 4 ++-- .../pmd/lang/java/ast/ParserCornersTest.java | 6 ++++++ .../pmd/lang/java/ast/UnicodeIndent.java | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/UnicodeIndent.java diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index e9eaacf5e57..f455a765e66 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -953,7 +953,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"-"\u1d7f","\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", @@ -1022,7 +1022,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", diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java index ef404408351..8f513b2690c 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java @@ -128,6 +128,12 @@ public void testGenericsProblem() { java7.parse(GENERICS_PROBLEM); } + @Test + public void testUnicodeIndent() { + // https://github.com/pmd/pmd/issues/3423 + java7.parseResource("UnicodeIndent.java"); + } + @Test public void testParsersCases15() { java5.parseResource("ParserCornerCases.java"); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/UnicodeIndent.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/UnicodeIndent.java new file mode 100644 index 00000000000..d6cbab3b848 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/UnicodeIndent.java @@ -0,0 +1,18 @@ +/* + * 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ᵤ + μᵤ); + } + +} From b328bc5fdc543f8605a99b8fc65251006bd7639f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 1 May 2022 17:47:06 +0200 Subject: [PATCH 03/54] Add more cjk and exotic scripts, also to JS Fix #2605 --- pmd-java/etc/grammar/Java.jjt | 3 ++- pmd-javascript/etc/grammar/es5.jj | 7 +++---- .../pmd/lang/ecmascript/ast/EcmascriptParserTest.java | 10 ++++++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index f455a765e66..004a5714538 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -961,7 +961,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", @@ -1033,6 +1033,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", diff --git a/pmd-javascript/etc/grammar/es5.jj b/pmd-javascript/etc/grammar/es5.jj index 688692d61d8..9e2b28be827 100644 --- a/pmd-javascript/etc/grammar/es5.jj +++ b/pmd-javascript/etc/grammar/es5.jj @@ -534,11 +534,10 @@ TOKEN : "\u31A0"-"\u31B7", "\u3400", "\u4DB5", - "\u4E00", - "\u9FA5", + "\u4E00"-"\u9EA5", "\uA000"-"\uA48C", - "\uAC00", - "\uD7A3", + "\uA490"-"\uABFF", + "\uAC00"-"\ud7AF", "\uF900"-"\uFA2D", "\uFB00"-"\uFB06", "\uFB13"-"\uFB17", diff --git a/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserTest.java b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserTest.java index f6fe15ce3fe..73a066e41a9 100644 --- a/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserTest.java +++ b/pmd-javascript/src/test/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParserTest.java @@ -183,6 +183,16 @@ public void testXorAssignment() { assertEquals("^=", infix.getImage()); } + @Test + public void testUnicodeCjk() { + // the first is u+4F60 + js.parse("import { Test } from 'test2'\n" + + "define('element', class extends Test {\n" + + " \n" + + " }\n" + + "})"); + } + /** * [javascript] Failing with OutOfMemoryError parsing a Javascript file #2081 */ From 71b936282854eacc008a4e2dfffea28bace0935a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 1 May 2022 17:51:38 +0200 Subject: [PATCH 04/54] [python] unicode support Fix #2604 --- pmd-python/etc/grammar/python.jj | 52 ++++++++++++++++++- .../pmd/cpd/PythonTokenizerTest.java | 5 ++ .../python/cpd/testdata/sample_unicode.py | 4 ++ .../python/cpd/testdata/sample_unicode.txt | 13 +++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/sample_unicode.py create mode 100644 pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/sample_unicode.txt diff --git a/pmd-python/etc/grammar/python.jj b/pmd-python/etc/grammar/python.jj index 1f97f9d9489..5ca99e73318 100644 --- a/pmd-python/etc/grammar/python.jj +++ b/pmd-python/etc/grammar/python.jj @@ -133,7 +133,57 @@ TOKEN : /* KEYWORDS */ TOKEN : /* Python identifiers */ { < NAME: ( | )* > -| < #LETTER: ["_","a"-"z","A"-"Z"] > +| < #LETTER : ["$","A"-"Z","_","a"-"z","\u00a2"-"\u00a5","\u00aa","\u00b5","\u00ba", + "\u00c0"-"\u00d6","\u00d8"-"\u00f6","\u00f8"-"\u021f","\u0222"-"\u0233","\u0250"-"\u02ad", + "\u02b0"-"\u02b8","\u02bb"-"\u02c1","\u02d0"-"\u02d1","\u02e0"-"\u02e4","\u02ee","\u037a", + "\u0386","\u0388"-"\u038a","\u038c","\u038e"-"\u03a1","\u03a3"-"\u03ce","\u03d0"-"\u03d7", + "\u03da"-"\u03f3","\u0400"-"\u0481","\u048c"-"\u04c4","\u04c7"-"\u04c8","\u04cb"-"\u04cc", + "\u04d0"-"\u04f5","\u04f8"-"\u04f9","\u0531"-"\u0556","\u0559","\u0561"-"\u0587", + "\u05d0"-"\u05ea","\u05f0"-"\u05f2","\u0621"-"\u063a","\u0640"-"\u064a","\u0671"-"\u06d3", + "\u06d5","\u06e5"-"\u06e6","\u06fa"-"\u06fc","\u0710","\u0712"-"\u072c","\u0780"-"\u07a5", + "\u0905"-"\u0939","\u093d","\u0950","\u0958"-"\u0961","\u0985"-"\u098c","\u098f"-"\u0990", + "\u0993"-"\u09a8","\u09aa"-"\u09b0","\u09b2","\u09b6"-"\u09b9","\u09dc"-"\u09dd", + "\u09df"-"\u09e1","\u09f0"-"\u09f3","\u0a05"-"\u0a0a","\u0a0f"-"\u0a10","\u0a13"-"\u0a28", + "\u0a2a"-"\u0a30","\u0a32"-"\u0a33","\u0a35"-"\u0a36","\u0a38"-"\u0a39","\u0a59"-"\u0a5c", + "\u0a5e","\u0a72"-"\u0a74","\u0a85"-"\u0a8b","\u0a8d","\u0a8f"-"\u0a91","\u0a93"-"\u0aa8", + "\u0aaa"-"\u0ab0","\u0ab2"-"\u0ab3","\u0ab5"-"\u0ab9","\u0abd","\u0ad0","\u0ae0", + "\u0b05"-"\u0b0c","\u0b0f"-"\u0b10","\u0b13"-"\u0b28","\u0b2a"-"\u0b30","\u0b32"-"\u0b33", + "\u0b36"-"\u0b39","\u0b3d","\u0b5c"-"\u0b5d","\u0b5f"-"\u0b61","\u0b85"-"\u0b8a", + "\u0b8e"-"\u0b90","\u0b92"-"\u0b95","\u0b99"-"\u0b9a","\u0b9c","\u0b9e"-"\u0b9f", + "\u0ba3"-"\u0ba4","\u0ba8"-"\u0baa","\u0bae"-"\u0bb5","\u0bb7"-"\u0bb9","\u0c05"-"\u0c0c", + "\u0c0e"-"\u0c10","\u0c12"-"\u0c28","\u0c2a"-"\u0c33","\u0c35"-"\u0c39","\u0c60"-"\u0c61", + "\u0c85"-"\u0c8c","\u0c8e"-"\u0c90","\u0c92"-"\u0ca8","\u0caa"-"\u0cb3","\u0cb5"-"\u0cb9", + "\u0cde","\u0ce0"-"\u0ce1","\u0d05"-"\u0d0c","\u0d0e"-"\u0d10","\u0d12"-"\u0d28", + "\u0d2a"-"\u0d39","\u0d60"-"\u0d61","\u0d85"-"\u0d96","\u0d9a"-"\u0db1","\u0db3"-"\u0dbb", + "\u0dbd","\u0dc0"-"\u0dc6","\u0e01"-"\u0e30","\u0e32"-"\u0e33","\u0e3f"-"\u0e46", + "\u0e81"-"\u0e82","\u0e84","\u0e87"-"\u0e88","\u0e8a","\u0e8d","\u0e94"-"\u0e97", + "\u0e99"-"\u0e9f","\u0ea1"-"\u0ea3","\u0ea5","\u0ea7","\u0eaa"-"\u0eab","\u0ead"-"\u0eb0", + "\u0eb2"-"\u0eb3","\u0ebd","\u0ec0"-"\u0ec4","\u0ec6","\u0edc"-"\u0edd","\u0f00", + "\u0f40"-"\u0f47","\u0f49"-"\u0f6a","\u0f88"-"\u0f8b","\u1000"-"\u1021","\u1023"-"\u1027", + "\u1029"-"\u102a","\u1050"-"\u1055","\u10a0"-"\u10c5","\u10d0"-"\u10f6","\u1100"-"\u1159", + "\u115f"-"\u11a2","\u11a8"-"\u11f9","\u1200"-"\u1206","\u1208"-"\u1246","\u1248", + "\u124a"-"\u124d","\u1250"-"\u1256","\u1258","\u125a"-"\u125d","\u1260"-"\u1286","\u1288", + "\u128a"-"\u128d","\u1290"-"\u12ae","\u12b0","\u12b2"-"\u12b5","\u12b8"-"\u12be","\u12c0", + "\u12c2"-"\u12c5","\u12c8"-"\u12ce","\u12d0"-"\u12d6","\u12d8"-"\u12ee","\u12f0"-"\u130e", + "\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","\u1d00"-"\u1d7f","\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", + "\u207f","\u20a0"-"\u20af","\u2102","\u2107","\u210a"-"\u2113","\u2115","\u2119"-"\u211d", + "\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","\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", + "\ufe33"-"\ufe34","\ufe4d"-"\ufe4f","\ufe69","\ufe70"-"\ufe72","\ufe74","\ufe76"-"\ufefc", + "\uff04","\uff21"-"\uff3a","\uff3f","\uff41"-"\uff5a","\uff65"-"\uffbe","\uffc2"-"\uffc7", + "\uffca"-"\uffcf","\uffd2"-"\uffd7","\uffda"-"\uffdc","\uffe0"-"\uffe1","\uffe5"-"\uffe6"]> + } diff --git a/pmd-python/src/test/java/net/sourceforge/pmd/cpd/PythonTokenizerTest.java b/pmd-python/src/test/java/net/sourceforge/pmd/cpd/PythonTokenizerTest.java index 254b8cdbe81..ad15fbe6616 100644 --- a/pmd-python/src/test/java/net/sourceforge/pmd/cpd/PythonTokenizerTest.java +++ b/pmd-python/src/test/java/net/sourceforge/pmd/cpd/PythonTokenizerTest.java @@ -42,6 +42,11 @@ public void testBackticks() { doTest("backticks"); } + @Test + public void testUnicode() { + doTest("sample_unicode"); + } + @Test public void testTabWidth() { doTest("tabWidth"); diff --git a/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/sample_unicode.py b/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/sample_unicode.py new file mode 100644 index 00000000000..b0143e7e1a0 --- /dev/null +++ b/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/sample_unicode.py @@ -0,0 +1,4 @@ +# note: add more examples here when bugs arise + +def check(): + total_cost_μs = [] # https://github.com/pmd/pmd/issues/2604 diff --git a/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/sample_unicode.txt b/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/sample_unicode.txt new file mode 100644 index 00000000000..9476d45ba4b --- /dev/null +++ b/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/sample_unicode.txt @@ -0,0 +1,13 @@ + [Image] or [Truncated image[ Bcol Ecol +L3 + [def] 1 3 + [check] 5 9 + [(] 10 10 + [)] 11 11 + [:] 12 12 +L4 + [total_cost_μs] 5 17 + [=] 19 19 + [\[] 21 21 + [\]] 22 22 +EOF From 669f2fecbd36025ddba0661ccd6378f4d56e4cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 1 May 2022 17:58:52 +0200 Subject: [PATCH 05/54] Same for go Fix #2752 --- .../sourceforge/pmd/lang/go/antlr4/Golang.g4 | 7 +- .../sourceforge/pmd/cpd/GoTokenizerTest.java | 7 ++ .../lang/go/cpd/testdata/sample_unicode.go | 20 +++++ .../lang/go/cpd/testdata/sample_unicode.txt | 89 +++++++++++++++++++ 4 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 pmd-go/src/test/resources/net/sourceforge/pmd/lang/go/cpd/testdata/sample_unicode.go create mode 100644 pmd-go/src/test/resources/net/sourceforge/pmd/lang/go/cpd/testdata/sample_unicode.txt diff --git a/pmd-go/src/main/antlr4/net/sourceforge/pmd/lang/go/antlr4/Golang.g4 b/pmd-go/src/main/antlr4/net/sourceforge/pmd/lang/go/antlr4/Golang.g4 index 673c0b66828..4f68b092317 100644 --- a/pmd-go/src/main/antlr4/net/sourceforge/pmd/lang/go/antlr4/Golang.g4 +++ b/pmd-go/src/main/antlr4/net/sourceforge/pmd/lang/go/antlr4/Golang.g4 @@ -1264,11 +1264,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] diff --git a/pmd-go/src/test/java/net/sourceforge/pmd/cpd/GoTokenizerTest.java b/pmd-go/src/test/java/net/sourceforge/pmd/cpd/GoTokenizerTest.java index 309867e9953..0a21eb2e1b6 100644 --- a/pmd-go/src/test/java/net/sourceforge/pmd/cpd/GoTokenizerTest.java +++ b/pmd-go/src/test/java/net/sourceforge/pmd/cpd/GoTokenizerTest.java @@ -40,4 +40,11 @@ public void bigFileTest() { public void testIssue1751() { doTest("issue-1751"); } + + @Test + public void testUnicode() { + // https://github.com/pmd/pmd/issues/2752 + doTest("sample_unicode"); + } + } diff --git a/pmd-go/src/test/resources/net/sourceforge/pmd/lang/go/cpd/testdata/sample_unicode.go b/pmd-go/src/test/resources/net/sourceforge/pmd/lang/go/cpd/testdata/sample_unicode.go new file mode 100644 index 00000000000..02325f94df1 --- /dev/null +++ b/pmd-go/src/test/resources/net/sourceforge/pmd/lang/go/cpd/testdata/sample_unicode.go @@ -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) + +} diff --git a/pmd-go/src/test/resources/net/sourceforge/pmd/lang/go/cpd/testdata/sample_unicode.txt b/pmd-go/src/test/resources/net/sourceforge/pmd/lang/go/cpd/testdata/sample_unicode.txt new file mode 100644 index 00000000000..f1b02aef861 --- /dev/null +++ b/pmd-go/src/test/resources/net/sourceforge/pmd/lang/go/cpd/testdata/sample_unicode.txt @@ -0,0 +1,89 @@ + [Image] or [Truncated image[ Bcol Ecol +L1 + [func] 1 4 + [main] 6 9 + [(] 10 10 + [)] 11 11 + [{] 13 13 +L3 + [str] 2 4 + [:=] 6 7 + ["hello world"] 9 21 +L4 + [slice] 2 6 + [:=] 8 9 + [str] 11 13 + [\[] 14 14 + [4] 15 15 + [:] 16 16 + [\]] 17 17 +L5 + [fmt] 2 4 + [.] 5 5 + [Println] 6 12 + [(] 13 13 + [slice] 14 18 + [)] 19 19 +L9 + [bytes] 2 6 + [:=] 8 9 + [\[] 11 11 + [\]] 12 12 + [byte] 13 16 + [(] 17 17 + [str] 18 20 + [)] 21 21 +L10 + [bytes] 2 6 + [\[] 7 7 + [2] 8 8 + [\]] 9 9 + [=] 11 11 + ['x'] 13 15 +L11 + [str] 2 4 + [=] 6 6 + [string] 8 13 + [(] 14 14 + [bytes] 15 19 + [)] 20 20 +L12 + [fmt] 2 4 + [.] 5 5 + [Println] 6 12 + [(] 13 13 + [str] 14 16 + [)] 17 17 +L15 + [runes] 2 6 + [:=] 8 9 + [\[] 11 11 + [\]] 12 12 + [rune] 13 16 + [(] 17 17 + [str] 18 20 + [)] 21 21 +L16 + [runes] 2 6 + [\[] 7 7 + [0] 8 8 + [\]] 9 9 + [=] 11 11 + ['哈'] 13 15 +L17 + [str] 2 4 + [=] 6 6 + [string] 8 13 + [(] 14 14 + [runes] 15 19 + [)] 20 20 +L18 + [fmt] 2 4 + [.] 5 5 + [Println] 6 12 + [(] 13 13 + [str] 14 16 + [)] 17 17 +L20 + [}] 1 1 +EOF From e6054e4b653f9f3e2fa77c27623f1a3cdbc82c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 1 May 2022 18:09:04 +0200 Subject: [PATCH 06/54] Add another test case for java --- .../pmd/lang/java/ast/ParserCornersTest.java | 2 +- ...codeIndent.java => UnicodeIdentifier.java} | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) rename pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/{UnicodeIndent.java => UnicodeIdentifier.java} (53%) diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java index 8f513b2690c..686e9f3c6c6 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java @@ -131,7 +131,7 @@ public void testGenericsProblem() { @Test public void testUnicodeIndent() { // https://github.com/pmd/pmd/issues/3423 - java7.parseResource("UnicodeIndent.java"); + java7.parseResource("UnicodeIdentifier.java"); } @Test diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/UnicodeIndent.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/UnicodeIdentifier.java similarity index 53% rename from pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/UnicodeIndent.java rename to pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/UnicodeIdentifier.java index d6cbab3b848..3eae15d2a90 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/UnicodeIndent.java +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/UnicodeIdentifier.java @@ -16,3 +16,22 @@ public static void main(String[] args) { } } + +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; + } +} From 078345fbca6970113b5b7ed17523980b30c76789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 1 May 2022 18:16:39 +0200 Subject: [PATCH 07/54] Add phonetic extensions to other langs --- .../main/antlr4/net/sourceforge/pmd/lang/go/antlr4/Golang.g4 | 1 + pmd-java/etc/grammar/Java.jjt | 2 +- pmd-javascript/etc/grammar/es5.jj | 1 + pmd-python/etc/grammar/python.jj | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pmd-go/src/main/antlr4/net/sourceforge/pmd/lang/go/antlr4/Golang.g4 b/pmd-go/src/main/antlr4/net/sourceforge/pmd/lang/go/antlr4/Golang.g4 index 4f68b092317..c54605fc858 100644 --- a/pmd-go/src/main/antlr4/net/sourceforge/pmd/lang/go/antlr4/Golang.g4 +++ b/pmd-go/src/main/antlr4/net/sourceforge/pmd/lang/go/antlr4/Golang.g4 @@ -1215,6 +1215,7 @@ fragment UNICODE_LETTER | [\u1780-\u17B3] | [\u1820-\u1877] | [\u1880-\u18A8] + | [\u1D00-\u1DFF] | [\u1E00-\u1E9B] | [\u1EA0-\u1EE0] | [\u1EE1-\u1EF9] diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 004a5714538..4e655ead41f 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -953,7 +953,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","\u1d00"-"\u1d7f","\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", diff --git a/pmd-javascript/etc/grammar/es5.jj b/pmd-javascript/etc/grammar/es5.jj index 9e2b28be827..a237b0899e0 100644 --- a/pmd-javascript/etc/grammar/es5.jj +++ b/pmd-javascript/etc/grammar/es5.jj @@ -488,6 +488,7 @@ TOKEN : "\u1E00"-"\u1E9B", "\u1EA0"-"\u1EE0", "\u1EE1"-"\u1EF9", + "\u1EE1"-"\u1EEF", "\u1F00"-"\u1F15", "\u1F18"-"\u1F1D", "\u1F20"-"\u1F39", diff --git a/pmd-python/etc/grammar/python.jj b/pmd-python/etc/grammar/python.jj index 5ca99e73318..41640cd724b 100644 --- a/pmd-python/etc/grammar/python.jj +++ b/pmd-python/etc/grammar/python.jj @@ -168,7 +168,7 @@ TOKEN : /* Python identifiers */ "\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","\u1d00"-"\u1d7f","\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", From f80c73e44f813d300252a389546ec14e58787a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 1 May 2022 18:21:43 +0200 Subject: [PATCH 08/54] Test dollar in ident in python --- .../sourceforge/pmd/cpd/PythonTokenizerTest.java | 6 ++++++ .../pmd/lang/python/cpd/testdata/var_with_dollar.py | 2 ++ .../lang/python/cpd/testdata/var_with_dollar.txt | 13 +++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/var_with_dollar.py create mode 100644 pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/var_with_dollar.txt diff --git a/pmd-python/src/test/java/net/sourceforge/pmd/cpd/PythonTokenizerTest.java b/pmd-python/src/test/java/net/sourceforge/pmd/cpd/PythonTokenizerTest.java index ad15fbe6616..e72eb3e4892 100644 --- a/pmd-python/src/test/java/net/sourceforge/pmd/cpd/PythonTokenizerTest.java +++ b/pmd-python/src/test/java/net/sourceforge/pmd/cpd/PythonTokenizerTest.java @@ -51,4 +51,10 @@ public void testUnicode() { public void testTabWidth() { doTest("tabWidth"); } + + @Test + public void testVarWithDollar() { + doTest("var_with_dollar"); + } + } diff --git a/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/var_with_dollar.py b/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/var_with_dollar.py new file mode 100644 index 00000000000..5c425202827 --- /dev/null +++ b/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/var_with_dollar.py @@ -0,0 +1,2 @@ +def check(): + a$a = [] diff --git a/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/var_with_dollar.txt b/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/var_with_dollar.txt new file mode 100644 index 00000000000..39607ea38fc --- /dev/null +++ b/pmd-python/src/test/resources/net/sourceforge/pmd/lang/python/cpd/testdata/var_with_dollar.txt @@ -0,0 +1,13 @@ + [Image] or [Truncated image[ Bcol Ecol +L1 + [def] 1 3 + [check] 5 9 + [(] 10 10 + [)] 11 11 + [:] 12 12 +L2 + [a$a] 5 7 + [=] 9 9 + [\[] 11 11 + [\]] 12 12 +EOF From 3538c6d3bd8d7c9a74df96399219277342ecbfbc Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 6 May 2022 15:52:12 +0200 Subject: [PATCH 09/54] [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 ce9604fe798..702e6605d4e 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 ElementNode(DocumentNode document, 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 ead5c73553f..756e41eb465 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.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 void testCompareOrderSamePosition() { 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 10/54] [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 acb96fc416f..9c905571e18 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 1a70e5c0fca..1a6272dab80 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 void selectTextNode() { 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 void selectAttributeByName() { } 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 11/54] 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 9d3c67aeade..a44ec4b4218 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.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 void setMinimumPriority(RulePriority minimumPriority) { * 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 Renderer createRenderer(boolean withReportWriter) { 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 f80dad49bd9..129483ee819 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.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 @@ 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 RulePriority convert(String value) { * @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 String getAuxclasspath() { 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 0ffc8465d06..9f33d4e4706 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 static PmdParametersParseResult extractParameters(String... args) { 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 157caf975de..56e7337fdf9 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 @@ 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 void setup() throws IOException { // 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 void testWrongCliOptionsDoNotPrintUsage() { 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 00000000000..eebe094a769 --- /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 12/54] 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 c31a705241f..647a57daf2e 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 56e7337fdf9..70c140023e1 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 @@ 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 void setup() throws IOException { // 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 void testWrongCliOptionsDoNotPrintUsage() { 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 22ca614a068..40ff67955e6 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 void testVersion() throws Exception { 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 eebe094a769..00000000000 --- 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 13/54] Fix tests --- .../net/sourceforge/pmd/PMDConfiguration.java | 2 +- .../sourceforge/pmd/cli/PMDParameters.java | 2 +- .../pmd/cli/PmdParametersParseResult.java | 7 +++- .../pmd/it/BinaryDistributionIT.java | 41 +++++++++++-------- 4 files changed, 32 insertions(+), 20 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 a44ec4b4218..ad3b9603c1a 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 129483ee819..fd4c8408e1e 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 9f33d4e4706..2f863ba4d9d 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 static PmdParametersParseResult extractParameters(String... 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 (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 48c9bc3ee39..fdb2a97706c 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 void testZipFileContent() throws IOException { } @Test - public void runPMD() throws Exception { - String srcDir = new File(".", "src/test/resources/sample-source/java/").getAbsolutePath(); - - ExecutionResult result; - - result = PMDExecutor.runPMD(tempDir); // without any argument, display usage help and error - result.assertExecutionResultErrOutput(1, CliMessages.runWithHelpFlagMessage()); + public void testPmdJavaQuickstart() throws Exception { + ExecutionResult result = PMDExecutor.runPMDRules(folder.newFile().toPath(), tempDir, srcDir, "rulesets/java/quickstart.xml"); + result.assertExecutionResult(4, ""); + } - result = PMDExecutor.runPMD(tempDir, "-h"); - result.assertExecutionResult(0, SUPPORTED_LANGUAGES_PMD); + @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, "", ""); - result.assertExecutionResult(4, "", " Date: Sat, 7 May 2022 19:33:29 +0200 Subject: [PATCH 14/54] 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 647a57daf2e..9c870263924 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 5657559026f5d7584b35172b87b9eff4d860c89a Mon Sep 17 00:00:00 2001 From: Per Abich Date: Sun, 8 May 2022 11:55:20 +0200 Subject: [PATCH 15/54] Fixed #3954 and wrote test confirming it. --- .../bestpractices/UseCollectionIsEmptyRule.java | 15 ++++----------- .../bestpractices/xml/UseCollectionIsEmpty.xml | 13 +++++++++++++ 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java index 27974ec8454..5ddf60c787d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java @@ -12,17 +12,7 @@ import java.util.Map; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; -import net.sourceforge.pmd.lang.java.ast.ASTEnumBody; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTName; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; -import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; -import net.sourceforge.pmd.lang.java.ast.ASTResultType; -import net.sourceforge.pmd.lang.java.ast.ASTType; -import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; -import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.ast.*; import net.sourceforge.pmd.lang.java.rule.AbstractInefficientZeroCheck; import net.sourceforge.pmd.lang.java.symboltable.ClassScope; import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence; @@ -124,6 +114,9 @@ private JavaTypeDefinition getTypeOfVariableByName(String varName, ASTPrimaryExp if (classOrEnumBody == null) { classOrEnumBody = expr.getFirstParentOfType(ASTEnumBody.class); } + if (classOrEnumBody == null) { + classOrEnumBody = expr.getFirstParentOfType(ASTRecordBody.class); + } List varDeclarators = classOrEnumBody.findDescendantsOfType(ASTVariableDeclarator.class); for (ASTVariableDeclarator varDeclarator : varDeclarators) { if (varDeclarator.getName().equals(varName)) { diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseCollectionIsEmpty.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseCollectionIsEmpty.xml index 77e39ab95dc..5e5439f3ff5 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseCollectionIsEmpty.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseCollectionIsEmpty.xml @@ -489,4 +489,17 @@ public class Foo { } ]]> + + With records + 0 + stringSet) { + + public boolean hasMoreThanOneItem() { + return this.stringSet.size() > 1; + } +} ]]> + From 418fe220b9ab541ba06a2b7b0fec3f7d25602e70 Mon Sep 17 00:00:00 2001 From: Per Abich Date: Sun, 8 May 2022 12:45:40 +0200 Subject: [PATCH 16/54] Fixed #3954 missing reporting of issue on records. --- .../bestpractices/UseCollectionIsEmptyRule.java | 8 +++++++- .../bestpractices/xml/UseCollectionIsEmpty.xml | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java index 5ddf60c787d..d0abde1db23 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java @@ -115,7 +115,13 @@ private JavaTypeDefinition getTypeOfVariableByName(String varName, ASTPrimaryExp classOrEnumBody = expr.getFirstParentOfType(ASTEnumBody.class); } if (classOrEnumBody == null) { - classOrEnumBody = expr.getFirstParentOfType(ASTRecordBody.class); + classOrEnumBody = expr.getFirstParentOfType(ASTRecordDeclaration.class); + List descendantsOfType = classOrEnumBody.findDescendantsOfType(ASTVariableDeclaratorId.class); + for (ASTVariableDeclaratorId variableDeclaratorId : descendantsOfType) { + if (variableDeclaratorId.getName().equals(varName)) { + return variableDeclaratorId.getTypeNode().getTypeDefinition(); + } + } } List varDeclarators = classOrEnumBody.findDescendantsOfType(ASTVariableDeclarator.class); for (ASTVariableDeclarator varDeclarator : varDeclarators) { diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseCollectionIsEmpty.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseCollectionIsEmpty.xml index 5e5439f3ff5..d296c995dc0 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseCollectionIsEmpty.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseCollectionIsEmpty.xml @@ -500,6 +500,20 @@ public record Record(Set stringSet) { public boolean hasMoreThanOneItem() { return this.stringSet.size() > 1; } +} ]]> + + + With records and size check + 1 + 6 + stringSet) { + + public boolean hasMoreThanOneItem() { + return this.stringSet.size() == 0; + } } ]]> From f85a635669de95234f027ea1b6a1681d91abd529 Mon Sep 17 00:00:00 2001 From: Per Abich Date: Sun, 8 May 2022 13:02:15 +0200 Subject: [PATCH 17/54] Fixed checkstyle violations --- .../bestpractices/UseCollectionIsEmptyRule.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java index d0abde1db23..c1cc304e6ac 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java @@ -12,7 +12,18 @@ import java.util.Map; import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.*; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; +import net.sourceforge.pmd.lang.java.ast.ASTEnumBody; +import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTName; +import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; +import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; +import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; +import net.sourceforge.pmd.lang.java.ast.ASTRecordDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTResultType; +import net.sourceforge.pmd.lang.java.ast.ASTType; +import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; +import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.rule.AbstractInefficientZeroCheck; import net.sourceforge.pmd.lang.java.symboltable.ClassScope; import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence; 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 18/54] 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 0a272878649..69a29d966df 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 9c870263924..dea79b1d19f 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 fd4c8408e1e..18c1da8a28a 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 @@ @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 d0ed105b9060aaa59a87e59d5bc7cef03bd5acf8 Mon Sep 17 00:00:00 2001 From: Per Abich Date: Mon, 9 May 2022 09:12:33 +0200 Subject: [PATCH 19/54] Slight refactoring of my changes to reduce complexity --- .../bestpractices/UseCollectionIsEmptyRule.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java index c1cc304e6ac..b780c222913 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UseCollectionIsEmptyRule.java @@ -22,7 +22,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTRecordDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTResultType; import net.sourceforge.pmd.lang.java.ast.ASTType; -import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.rule.AbstractInefficientZeroCheck; import net.sourceforge.pmd.lang.java.symboltable.ClassScope; @@ -124,20 +123,14 @@ private JavaTypeDefinition getTypeOfVariableByName(String varName, ASTPrimaryExp Node classOrEnumBody = expr.getFirstParentOfType(ASTClassOrInterfaceBody.class); if (classOrEnumBody == null) { classOrEnumBody = expr.getFirstParentOfType(ASTEnumBody.class); - } + } if (classOrEnumBody == null) { classOrEnumBody = expr.getFirstParentOfType(ASTRecordDeclaration.class); - List descendantsOfType = classOrEnumBody.findDescendantsOfType(ASTVariableDeclaratorId.class); - for (ASTVariableDeclaratorId variableDeclaratorId : descendantsOfType) { - if (variableDeclaratorId.getName().equals(varName)) { - return variableDeclaratorId.getTypeNode().getTypeDefinition(); - } - } } - List varDeclarators = classOrEnumBody.findDescendantsOfType(ASTVariableDeclarator.class); - for (ASTVariableDeclarator varDeclarator : varDeclarators) { - if (varDeclarator.getName().equals(varName)) { - return varDeclarator.getVariableId().getTypeNode().getTypeDefinition(); + List varDeclaratorIds = classOrEnumBody.findDescendantsOfType(ASTVariableDeclaratorId.class); + for (ASTVariableDeclaratorId variableDeclaratorId : varDeclaratorIds) { + if (variableDeclaratorId.getName().equals(varName)) { + return variableDeclaratorId.getTypeNode().getTypeDefinition(); } } return null; 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 20/54] [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 76fb6639f11..69baff82190 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 @@ private enum FieldImmutabilityType { 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 359a1ce214c..2b645e9839f 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 28b0d13da9cfb519b925ed80199ebfcf5b7b1ec5 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 12 May 2022 15:16:49 +0200 Subject: [PATCH 21/54] [java] UseArraysAsList - ignore non-trivial loops Fixes #3965 --- docs/pages/release_notes.md | 2 + .../resources/category/java/performance.xml | 1 + .../rule/performance/xml/UseArraysAsList.xml | 38 +++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index c31a705241f..d50ee17ddc0 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-performance + * [#3965](https://github.com/pmd/pmd/issues/3965): \[java] UseArraysAsList false positive with non-trivial loops * javascript * [#3948](https://github.com/pmd/pmd/issues/3948): \[js] Invalid operator error for method property in object literal diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml index de0987520d2..2c0f9cd4502 100644 --- a/pmd-java/src/main/resources/category/java/performance.xml +++ b/pmd-java/src/main/resources/category/java/performance.xml @@ -968,6 +968,7 @@ You must use `new ArrayList<>(Arrays.asList(...))` if that is inconvenient for y + + + [java] UseArraysAsList false positive with non-trivial loops #3965 + 0 + l = new ArrayList<>(100); + for (int i = 0; i < 100; i++) { + switch (lookup(ints[i])) { + case 1: l.add(ints[i]); break; // line 10 - false positive + case 2: l.addAll(getInts(i)); break; + } + } + + List anotherList = new ArrayList<>(); + for (int i : ints) { + switch (lookup(i)) { + case 1: anotherList.add(i); break; // line 18 - false positive + case 2: anotherList.addAll(getInts(i)); break; + } + } + } + + int lookup(int a) { + return a; + } + + List getInts(int a) { + return Arrays.asList(a); + } +} +]]> + From f81752dc57c4c15b89e2da25c2963607e3eec1f6 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 12 May 2022 15:54:47 +0200 Subject: [PATCH 22/54] [java] UseArraysAsList - skip primitive arrays Fixes #3379 --- docs/pages/release_notes.md | 1 + .../resources/category/java/performance.xml | 10 ++++- .../rule/performance/xml/UseArraysAsList.xml | 42 +++++++++++++++---- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index d50ee17ddc0..a6e1fe7d24c 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -17,6 +17,7 @@ This is a {{ site.pmd.release_type }} release. ### Fixed Issues * java-performance + * [#3379](https://github.com/pmd/pmd/issues/3379): \[java] UseArraysAsList must ignore primitive arrays * [#3965](https://github.com/pmd/pmd/issues/3965): \[java] UseArraysAsList false positive with non-trivial loops * javascript * [#3948](https://github.com/pmd/pmd/issues/3948): \[js] Invalid operator error for method property in object literal diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml index 2c0f9cd4502..8411f356033 100644 --- a/pmd-java/src/main/resources/category/java/performance.xml +++ b/pmd-java/src/main/resources/category/java/performance.xml @@ -970,6 +970,12 @@ You must use `new ArrayList<>(Arrays.asList(...))` if that is inconvenient for y [not(.//IfStatement)] [count(Statement//StatementExpression)=1] [@Foreach = true() or ForInit//VariableInitializer//Literal[@IntLiteral= true() and @Image='0']] + (: skip primitive types :) + [@Foreach = true() and Expression[not(pmd-java:typeIs('boolean[]') or pmd-java:typeIs('char[]') or pmd-java:typeIs('byte[]') or pmd-java:typeIs('short[]') or pmd-java:typeIs('int[]') or pmd-java:typeIs('long[]') or pmd-java:typeIs('float[]') or pmd-java:typeIs('double[]'))] + or Expression/RelationalExpression/PrimaryExpression/PrimaryPrefix/Name[substring-before(@Image, '.length') = + ancestor::MethodDeclaration[1]//VariableDeclaratorId[not(pmd-java:typeIs('boolean[]') or pmd-java:typeIs('char[]') or pmd-java:typeIs('byte[]') or pmd-java:typeIs('short[]') or pmd-java:typeIs('int[]') or pmd-java:typeIs('long[]') or pmd-java:typeIs('float[]') or pmd-java:typeIs('double[]'))] + /@Name] + ] //StatementExpression [PrimaryExpression [PrimaryPrefix/Name @@ -1013,12 +1019,12 @@ public class Test { public void foo(Integer[] ints) { // could just use Arrays.asList(ints) List l = new ArrayList<>(100); - for (int i = 0; i < 100; i++) { + for (int i = 0; i < ints.length; i++) { l.add(ints[i]); } List anotherList = new ArrayList<>(); - for (int i = 0; i < 100; i++) { + for (int i = 0; i < ints.length; i++) { anotherList.add(ints[i].toString()); // won't trigger the rule } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseArraysAsList.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseArraysAsList.xml index 11ba87f95be..a3ad5af636a 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseArraysAsList.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/UseArraysAsList.xml @@ -14,9 +14,9 @@ import java.util.List; public class Bar { void foo() { - Integer[] ints = new Integer(10); - List l = new ArrayList(10); - for (int i = 0; i < 100; i++) { + Integer[] ints = new Integer[10]; + List l = new ArrayList(ints.length); + for (int i = 0; i < ints.length; i++) { l.add(ints[i]); } } @@ -114,11 +114,13 @@ public class Test { public void foo(Integer[] ints) { // could just use Arrays.asList(ints) List l = new ArrayList(10); - for (int i = 0; i < 100; i++) { + for (int i = 0; i < ints.length; i++) { l.add(ints[i]); } - for (int i = 0; i < 100; i++) { - l.add(a[i].toString()); // won't trigger the rule + + List l2 = new ArrayList(10); + for (int i = 0; i < ints.length; i++) { + l2.add(ints[i].toString()); // won't trigger the rule } } } @@ -179,11 +181,11 @@ public class Test { public void foo(Integer[] ints) { // could just use Arrays.asList(ints) List l = new ArrayList<>(100); - for (int i = 0; i < 100; i++) { + for (int i = 0; i < ints.length; i++) { l.add(ints[i]); // line 9, here is the violation } List anotherList = new ArrayList<>(); - for (int i = 0; i < 100; i++) { + for (int i = 0; i < ints.length; i++) { anotherList.add(ints[i].toString()); // line 13 - false positive } } @@ -226,6 +228,30 @@ public class Test { return Arrays.asList(a); } } +]]> + + + + [java] UseArraysAsList must ignore primitive arrays #3379 + 0 + arrayList = new ArrayList<>(array.length); + for (short v : array) { + arrayList.add(v); // line 9 - false positive + } + + List arrayList2 = new ArrayList<>(array.length); + for (int i = 0; i < array.length; i++) { + arrayList2.add(array[i]); // line 14 - false positive + } + } +} ]]> From 03a51a73a5cc1c2c8d6fea15e03bffe4b91872c1 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 12 May 2022 17:48:04 +0200 Subject: [PATCH 23/54] Bump kotlin from 1.4.10 to 1.4.32 Fixes https://nvd.nist.gov/vuln/detail/CVE-2020-29582 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 08d245b8ffd..8387d388534 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ ${maven.compiler.test.target} - 1.4.10 + 1.4.32 4.3.1 1.4.32 From a28c2399218b17d799cbae3b5cc9adbede46ca77 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 12 May 2022 17:54:20 +0200 Subject: [PATCH 24/54] Bump kotest from 4.3.1 to 4.4.3 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8387d388534..7b503ac88ea 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ ${maven.compiler.test.target} 1.4.32 - 4.3.1 + 4.4.3 1.4.32 From 4944177cc4a8a6b3467950bab061795e1c261813 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 7 May 2022 21:30:47 +0200 Subject: [PATCH 25/54] [core] Add missing methods to IOUtil as replacement for IOUtils --- .../java/net/sourceforge/pmd/util/IOUtil.java | 318 +++++++++++++++++- .../net/sourceforge/pmd/util/IOUtilTest.java | 258 ++++++++++++++ 2 files changed, 574 insertions(+), 2 deletions(-) create mode 100644 pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java index d4833987d12..791561bc7ac 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java @@ -7,21 +7,30 @@ import java.io.BufferedReader; import java.io.Closeable; import java.io.File; +import java.io.FilterInputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CodingErrorAction; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Collection; import java.util.List; +import java.util.Objects; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.annotation.InternalApi; @@ -35,6 +44,8 @@ @Deprecated public final class IOUtil { + private static final int BUFFER_SIZE = 8192; + private IOUtil() { } @@ -119,7 +130,7 @@ public static Reader skipBOM(Reader source) { public static void tryCloseClassLoader(ClassLoader classLoader) { if (classLoader instanceof Closeable) { - IOUtils.closeQuietly((Closeable) classLoader); + closeQuietly((Closeable) classLoader); } } @@ -169,4 +180,307 @@ public static void ensureClosed(List toClose, } } + public static void closeQuietly(Closeable closeable) { + try { + closeable.close(); + } catch (IOException ignored) { + // ignored + } + } + + public static byte[] toByteArray(InputStream stream) throws IOException { + byte[] result = new byte[0]; + byte[] buffer = new byte[BUFFER_SIZE]; + int count = stream.read(buffer); + while (count > -1) { + byte[] newResult = new byte[result.length + count]; + System.arraycopy(result, 0, newResult, 0, result.length); + System.arraycopy(buffer, 0, newResult, result.length, count); + result = newResult; + count = stream.read(buffer); + } + return result; + } + + public static long skipFully(InputStream stream, long n) throws IOException { + if (n < 0) { + throw new IllegalArgumentException(); + } + + long bytesToSkip = n; + byte[] buffer = new byte[(int) Math.min(BUFFER_SIZE, bytesToSkip)]; + while (bytesToSkip > 0) { + int count = stream.read(buffer, 0, (int) Math.min(BUFFER_SIZE, bytesToSkip)); + if (count < 0) { + // reached eof + break; + } + bytesToSkip -= count; + } + return n - bytesToSkip; + } + + public static String normalizePath(String path) { + Path path1 = Paths.get(path); + path1.isAbsolute(); + String normalized = path1.normalize().toString(); + if (normalized.contains("." + File.separator) || normalized.contains(".." + File.separator) || "".equals(normalized)) { + return null; + } + return normalized; + } + + public static boolean equalsNormalizedPaths(String path1, String path2) { + return Objects.equals(normalizePath(path1), normalizePath(path2)); + } + + public static String getFilenameExtension(String name) { + String filename = Paths.get(name).getFileName().toString(); + int dot = filename.lastIndexOf('.'); + if (dot > -1) { + return filename.substring(dot + 1); + } + return ""; + } + + public static String getFilenameBase(String name) { + String filename = Paths.get(name).getFileName().toString(); + int dot = filename.lastIndexOf('.'); + if (dot > -1) { + return filename.substring(0, dot); + } + return filename; + } + + public static void copy(InputStream from, OutputStream to) throws IOException { + byte[] buffer = new byte[BUFFER_SIZE]; + int count = from.read(buffer); + while (count > -1) { + to.write(buffer, 0, count); + count = from.read(buffer); + } + } + + public static void copy(Reader from, Writer to) throws IOException { + char[] buffer = new char[BUFFER_SIZE]; + int count = from.read(buffer); + while (count > -1) { + to.write(buffer, 0, count); + count = from.read(buffer); + } + } + + public static String readFileToString(File file) throws IOException { + return readFileToString(file, Charset.defaultCharset()); + } + + public static String readFileToString(File file, Charset charset) throws IOException { + byte[] bytes = Files.readAllBytes(file.toPath()); + return charset.decode(ByteBuffer.wrap(bytes)).toString(); + } + + public static String readToString(Reader reader) throws IOException { + StringBuilder sb = new StringBuilder(BUFFER_SIZE); + char[] buffer = new char[BUFFER_SIZE]; + int count = reader.read(buffer); + while (count > -1) { + sb.append(buffer, 0, count); + count = reader.read(buffer); + } + return sb.toString(); + } + + public static String readToString(InputStream stream, Charset charset) throws IOException { + byte[] bytes = toByteArray(stream); + return charset.decode(ByteBuffer.wrap(bytes)).toString(); + } + + public static InputStream fromReader(Reader reader) throws IOException { + class ReaderInputStream extends InputStream { + private final Reader reader; + private final CharBuffer charBuffer = CharBuffer.allocate(BUFFER_SIZE); + private final ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE); + private final CharsetEncoder encoder; + + private boolean eof; + + ReaderInputStream(Reader reader) { + this.reader = reader; + encoder = Charset.defaultCharset().newEncoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + charBuffer.clear(); + byteBuffer.clear(); + byteBuffer.flip(); // byte buffer is empty at the beginning, no bytes read yet + } + + @Override + public int read() throws IOException { + if (!byteBuffer.hasRemaining()) { + if (charBuffer.hasRemaining() && !eof) { + int count = reader.read(charBuffer); + eof = count == -1; + } + byteBuffer.clear(); + charBuffer.flip(); + encoder.encode(charBuffer, byteBuffer, eof); + byteBuffer.flip(); + charBuffer.flip(); + } + + if (byteBuffer.hasRemaining()) { + return byteBuffer.get(); + } + + return -1; + } + + @Override + public int available() throws IOException { + return byteBuffer.remaining(); + } + + @Override + public void close() throws IOException { + reader.close(); + } + } + + return new ReaderInputStream(reader); + } + + public static OutputStream fromWriter(Writer writer, String encoding) throws UnsupportedCharsetException { + class WriterOutputStream extends OutputStream { + private final Writer writer; + private final CharsetDecoder decoder; + private final ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_SIZE); + private final CharBuffer charBuffer = CharBuffer.allocate(BUFFER_SIZE); + + WriterOutputStream(Writer writer, String encoding) throws UnsupportedCharsetException { + this.writer = writer; + Charset charset = Charset.forName(encoding); + decoder = charset.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + byteBuffer.clear(); + charBuffer.clear(); + } + + @Override + public void write(int b) throws IOException { + if (!byteBuffer.hasRemaining()) { + decodeByteBuffer(false); + } + byteBuffer.put((byte) b); + } + + @Override + public void flush() throws IOException { + decodeByteBuffer(false); + } + + private void decodeByteBuffer(boolean isClosing) throws IOException { + byteBuffer.flip(); + charBuffer.clear(); + decoder.decode(byteBuffer, charBuffer, isClosing); + writer.write(charBuffer.array(), 0, charBuffer.position()); + writer.flush(); + byteBuffer.compact(); + } + + @Override + public void close() throws IOException { + flush(); + decodeByteBuffer(true); + writer.close(); + } + } + + return new WriterOutputStream(writer, encoding); + } + + /** + *

+ * Input stream that skips an optional byte order mark at the beginning + * of the stream. Whether the stream had a byte order mark (encoded in either UTF-8, + * UTF-16LE or UTF-16BE) can be checked with {@link #hasBom()}. The corresponding + * charset can be retrieved with {@link #getBomCharsetName()}. + *

+ * + *

+ * If the stream didn't had a BOM, then no bytes are skipped. + *

+ */ + public static class BomAwareInputStream extends FilterInputStream { + + private byte[] begin; + int beginIndex; + + private String charset; + + public BomAwareInputStream(InputStream in) { + super(in); + begin = determineBom(); + } + + private byte[] determineBom() { + byte[] bytes = new byte[3]; + try { + int count = in.read(bytes); + if (count == 3 && bytes[0] == (byte) 0xef && bytes[1] == (byte) 0xbb && bytes[2] == (byte) 0xbf) { + charset = StandardCharsets.UTF_8.name(); + return new byte[0]; // skip all 3 bytes + } else if (count >= 2 && bytes[0] == (byte) 0xfe && bytes[1] == (byte) 0xff) { + charset = StandardCharsets.UTF_16BE.name(); + return new byte[] { bytes[2] }; + } else if (count >= 2 && bytes[0] == (byte) 0xff && bytes[1] == (byte) 0xfe) { + charset = StandardCharsets.UTF_16LE.name(); + return new byte[] { bytes[2] }; + } else if (count == 3) { + return bytes; + } + + if (count < 0) { + return new byte[0]; + } + + byte[] read = new byte[count]; + for (int i = 0; i < count; i++) { + read[i] = bytes[i]; + } + return read; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public int read() throws IOException { + if (beginIndex < begin.length) { + return begin[beginIndex++]; + } + return super.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (beginIndex < begin.length) { + int count = 0; + for (; count < len && beginIndex < begin.length; beginIndex++) { + b[off + count] = begin[beginIndex]; + count++; + } + return count; + } + return super.read(b, off, len); + } + + public boolean hasBom() { + return charset != null; + } + + public String getBomCharsetName() { + return charset; + } + } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java new file mode 100644 index 00000000000..35e772cfc9a --- /dev/null +++ b/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java @@ -0,0 +1,258 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.CharArrayReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.commons.lang3.SystemUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.function.ThrowingRunnable; + +public class IOUtilTest { + + @Test + public void testReadAllBytes() throws IOException { + byte[] data = "12345".getBytes(StandardCharsets.UTF_8); + try (InputStream stream = new ByteArrayInputStream(data)) { + byte[] bytes = IOUtil.toByteArray(stream); + Assert.assertEquals(5, bytes.length); + Assert.assertArrayEquals(data, bytes); + } + } + + @Test + public void testToByteArrayResize() throws IOException { + int size = 8192 + 8192 + 10; + byte[] data = new byte[size]; + for (int i = 0; i < size; i++) { + data[i] = 'A'; + } + try (InputStream stream = new ByteArrayInputStream(data)) { + byte[] bytes = IOUtil.toByteArray(stream); + Assert.assertEquals(size, bytes.length); + Assert.assertArrayEquals(data, bytes); + } + } + + @Test + public void testSkipFully() throws IOException { + byte[] data = "12345".getBytes(StandardCharsets.UTF_8); + try (InputStream stream = new ByteArrayInputStream(data)) { + Assert.assertThrows(IllegalArgumentException.class, new ThrowingRunnable() { + @Override + public void run() throws Throwable { + IOUtil.skipFully(stream, -1); + } + }); + + Assert.assertEquals(3, IOUtil.skipFully(stream, 3)); + byte[] bytes = IOUtil.toByteArray(stream); + Assert.assertEquals(2, bytes.length); + Assert.assertArrayEquals("45".getBytes(StandardCharsets.UTF_8), bytes); + } + } + + @Test + public void testSkipFully2() throws IOException { + byte[] data = "12345".getBytes(StandardCharsets.UTF_8); + try (InputStream stream = new ByteArrayInputStream(data)) { + // skip more bytes than the stream contains + Assert.assertEquals(data.length, IOUtil.skipFully(stream, data.length + 1)); + byte[] bytes = IOUtil.toByteArray(stream); + Assert.assertEquals(0, bytes.length); + } + } + + @Test + public void testNormalizePath() { + Assert.assertEquals("ab/cd.txt", IOUtil.normalizePath("ab/ef/../cd.txt")); + Assert.assertEquals("/a.txt", IOUtil.normalizePath("/x/../../a.txt")); + Assert.assertEquals("/foo", IOUtil.normalizePath("//../foo")); + Assert.assertEquals("/foo", IOUtil.normalizePath("/foo//")); + Assert.assertEquals("/foo", IOUtil.normalizePath("/foo/./")); + Assert.assertEquals("/bar", IOUtil.normalizePath("/foo/../bar")); + Assert.assertEquals("/bar", IOUtil.normalizePath("/foo/../bar/")); + Assert.assertEquals("/baz", IOUtil.normalizePath("/foo/../bar/../baz")); + Assert.assertEquals("/foo/bar", IOUtil.normalizePath("//foo//./bar")); + Assert.assertEquals("foo", IOUtil.normalizePath("foo/bar/..")); + Assert.assertEquals("bar", IOUtil.normalizePath("foo/../bar")); + Assert.assertEquals("/foo/baz", IOUtil.normalizePath("//foo/bar/../baz")); + Assert.assertEquals("~/bar", IOUtil.normalizePath("~/foo/../bar/")); + Assert.assertEquals("/", IOUtil.normalizePath("/../")); + Assert.assertEquals("bar", IOUtil.normalizePath("~/../bar")); + Assert.assertEquals("bar", IOUtil.normalizePath("./bar")); + + Assert.assertNull(IOUtil.normalizePath("../foo")); + Assert.assertNull(IOUtil.normalizePath("foo/../../bar")); + Assert.assertNull(IOUtil.normalizePath(".")); + + Assert.assertTrue(IOUtil.equalsNormalizedPaths("foo/../bar", "bar/./")); + + if (SystemUtils.IS_OS_WINDOWS) { + Assert.assertEquals("C:\\bar", IOUtil.normalizePath("C:\\..\\bar")); + Assert.assertEquals("ab\\cd.txt", IOUtil.normalizePath("ab\\ef\\..\\cd.txt")); + Assert.assertEquals("C:\\ab\\cd.txt", IOUtil.normalizePath("C:\\ab\\ef\\..\\.\\cd.txt")); + Assert.assertNull(IOUtil.normalizePath("..\\foo")); + Assert.assertNull(IOUtil.normalizePath("foo\\..\\..\\bar")); + } + } + + @Test + public void testFilenameExtension() { + Assert.assertEquals("txt", IOUtil.getFilenameExtension("ab/cd.txt")); + Assert.assertEquals("txt", IOUtil.getFilenameExtension("ab.cd.txt")); + Assert.assertEquals("", IOUtil.getFilenameExtension("ab/cd")); + Assert.assertEquals("html", IOUtil.getFilenameExtension("cd.html")); + } + + @Test + public void testFilenameBase() { + Assert.assertEquals("cd", IOUtil.getFilenameBase("ab/cd.txt")); + Assert.assertEquals("ab.cd", IOUtil.getFilenameBase("ab.cd.txt")); + Assert.assertEquals("cd", IOUtil.getFilenameBase("ab/cd")); + } + + @Test + public void testBomAwareStream() throws IOException { + assertBomStream("No BOM".getBytes(StandardCharsets.UTF_8), "No BOM", null); + assertBomStream("\ufeffBOM".getBytes(StandardCharsets.UTF_8), "BOM", StandardCharsets.UTF_8.name()); + assertBomStream("\ufeffBOM".getBytes(StandardCharsets.UTF_16LE), "BOM", StandardCharsets.UTF_16LE.name()); + assertBomStream("\ufeffBOM".getBytes(StandardCharsets.UTF_16BE), "BOM", StandardCharsets.UTF_16BE.name()); + } + + private void assertBomStream(byte[] data, String expectedData, String expectedCharset) throws IOException { + try (IOUtil.BomAwareInputStream stream = new IOUtil.BomAwareInputStream(new ByteArrayInputStream(data))) { + if (expectedCharset != null) { + Assert.assertTrue(stream.hasBom()); + Assert.assertEquals(expectedCharset, stream.getBomCharsetName()); + Assert.assertEquals(expectedData, new String(IOUtil.toByteArray(stream), stream.getBomCharsetName())); + + } else { + Assert.assertFalse(stream.hasBom()); + Assert.assertNull(stream.getBomCharsetName()); + Assert.assertEquals(expectedData, new String(IOUtil.toByteArray(stream), StandardCharsets.UTF_8)); + } + } + } + + @Test + public void testOutputStreamFromWriter() throws IOException { + StringWriter writer = new StringWriter(); + try (OutputStream outputStream = IOUtil.fromWriter(writer, "UTF-8")) { + outputStream.write("abc".getBytes(StandardCharsets.UTF_8)); + } + Assert.assertEquals("abc", writer.toString()); + } + + @Test + public void testInputStreamFromReader() throws IOException { + try (InputStream inputStream = IOUtil.fromReader(new StringReader("abc"))) { + byte[] bytes = IOUtil.toByteArray(inputStream); + Assert.assertEquals("abc", new String(bytes, StandardCharsets.UTF_8)); + } + } + + @Test + public void testCopyStream() throws IOException { + int size = 8192 + 8192 + 10; + byte[] data = new byte[size]; + for (int i = 0; i < size; i++) { + data[i] = 'A'; + } + try (InputStream stream = new ByteArrayInputStream(data); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + IOUtil.copy(stream, out); + byte[] bytes = out.toByteArray(); + Assert.assertEquals(size, bytes.length); + Assert.assertArrayEquals(data, bytes); + } + } + + @Test + public void testCopyReader() throws IOException { + int size = 8192 + 8192 + 10; + char[] data = new char[size]; + for (int i = 0; i < size; i++) { + data[i] = 'A'; + } + try (Reader reader = new CharArrayReader(data); + StringWriter writer = new StringWriter()) { + IOUtil.copy(reader, writer); + char[] chars = writer.toString().toCharArray(); + Assert.assertEquals(size, chars.length); + Assert.assertArrayEquals(data, chars); + } + } + + @Test + public void testReadEmptyStream() throws IOException { + try (InputStream in = new ByteArrayInputStream(new byte[0])) { + byte[] bytes = IOUtil.toByteArray(in); + Assert.assertNotNull(bytes); + Assert.assertEquals(0, bytes.length); + } + } + + @Test + public void testCloseQuietly() { + class Stream extends InputStream { + private boolean closed = false; + + @Override + public int read() throws IOException { + return 0; + } + + @Override + public void close() throws IOException { + closed = true; + throw new IOException("test"); + } + + public boolean isClosed() { + return closed; + } + } + + Stream stream = new Stream(); + IOUtil.closeQuietly(stream); + Assert.assertTrue(stream.isClosed()); + } + + @Test + public void testReadFileToString() throws IOException { + String testString = "Test ABC"; + Path tempFile = Files.createTempFile("pmd", ".txt"); + Files.write(tempFile, testString.getBytes(Charset.defaultCharset())); + Assert.assertEquals(testString, IOUtil.readFileToString(tempFile.toFile())); + } + + @Test + public void testReadToString() throws IOException { + String testString = "testReadToString"; + Reader reader = new StringReader(testString); + Assert.assertEquals(testString, IOUtil.readToString(reader)); + } + + @Test + public void testReadStreamToString() throws IOException { + String testString = "testReadStreamToString"; + InputStream stream = new ByteArrayInputStream(testString.getBytes(StandardCharsets.UTF_8)); + Assert.assertEquals(testString, IOUtil.readToString(stream, StandardCharsets.UTF_8)); + } +} From 753cb49e403b71d683bc7bcc7104fd01cb813530 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 09:51:54 +0200 Subject: [PATCH 26/54] [all] Remove dependency to commons-io --- pmd-apex/pom.xml | 4 ---- pmd-core/pom.xml | 4 ---- pmd-dist/pom.xml | 4 ---- pmd-doc/pom.xml | 4 ---- pmd-java/pom.xml | 4 ---- pmd-javascript/pom.xml | 4 ---- pmd-lang-test/pom.xml | 4 ---- pmd-plsql/pom.xml | 4 ---- pmd-scala-modules/pmd-scala-common/pom.xml | 4 ---- pmd-test/pom.xml | 4 ---- pmd-xml/pom.xml | 4 ---- pom.xml | 5 ----- 12 files changed, 49 deletions(-) diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml index 9c0e6b93a96..4b7786ff4ec 100644 --- a/pmd-apex/pom.xml +++ b/pmd-apex/pom.xml @@ -58,10 +58,6 @@ pom - - commons-io - commons-io - org.apache.commons commons-lang3 diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml index bd5ed97a91b..bd60fcdfadd 100644 --- a/pmd-core/pom.xml +++ b/pmd-core/pom.xml @@ -111,10 +111,6 @@ com.beust jcommander - - commons-io - commons-io - jaxen jaxen diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml index 66d4134964d..58348f8bbfa 100644 --- a/pmd-dist/pom.xml +++ b/pmd-dist/pom.xml @@ -236,10 +236,6 @@ - - commons-io - commons-io - org.apache.commons commons-lang3 diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml index db23e84ae71..5fda1dc5b93 100644 --- a/pmd-doc/pom.xml +++ b/pmd-doc/pom.xml @@ -83,10 +83,6 @@ pmd-core ${project.version} - - commons-io - commons-io - org.apache.commons commons-lang3 diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index b85810aaeb2..df12c9505f5 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -127,10 +127,6 @@ org.ow2.asm asm - - commons-io - commons-io - org.apache.commons commons-lang3 diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml index d4256cf9bcd..d87540aceba 100644 --- a/pmd-javascript/pom.xml +++ b/pmd-javascript/pom.xml @@ -84,10 +84,6 @@ rhino 1.7.14 - - commons-io - commons-io - junit diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index c657cdd6b88..cbe2246ebdd 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -81,10 +81,6 @@ org.apache.commons commons-lang3 - - commons-io - commons-io - - - commons-io - commons-io - 2.6 - org.apache.commons commons-lang3 From 2887fe3ae0e7cb573380142aa004d040b47f8877 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 09:52:13 +0200 Subject: [PATCH 27/54] [core] Replace IOUtils with IOUtil --- .../sourceforge/pmd/RuleSetFactoryCompatibility.java | 5 ++--- .../main/java/net/sourceforge/pmd/RuleSetWriter.java | 4 ++-- .../main/java/net/sourceforge/pmd/ant/Formatter.java | 6 +++--- .../sourceforge/pmd/cache/AbstractAnalysisCache.java | 5 ++--- .../java/net/sourceforge/pmd/cache/AnalysisResult.java | 6 ++---- .../pmd/cache/internal/RawFileFingerprinter.java | 4 ++-- .../src/main/java/net/sourceforge/pmd/cpd/CPD.java | 6 ++---- .../main/java/net/sourceforge/pmd/cpd/SourceCode.java | 10 ++++------ .../net/sourceforge/pmd/document/DocumentFile.java | 4 ++-- .../pmd/internal/util/FileCollectionUtil.java | 5 ++--- .../net/sourceforge/pmd/lang/document/NioTextFile.java | 5 ++--- .../pmd/processor/AbstractPMDProcessor.java | 4 ++-- .../sourceforge/pmd/renderers/AbstractRenderer.java | 4 +--- .../net/sourceforge/pmd/renderers/XMLRenderer.java | 4 ++-- .../main/java/net/sourceforge/pmd/util/FileFinder.java | 10 +++++++--- .../main/java/net/sourceforge/pmd/util/FileUtil.java | 3 +-- .../pmd/util/datasource/ReaderDataSource.java | 5 ++--- .../pmd/RuleSetFactoryCompatibilityTest.java | 10 +++++----- .../net/sourceforge/pmd/RuleSetReferenceIdTest.java | 10 +++++----- .../src/test/java/net/sourceforge/pmd/RuleSetTest.java | 4 ++-- .../test/java/net/sourceforge/pmd/ant/PMDTaskTest.java | 9 +++++---- .../test/java/net/sourceforge/pmd/cli/CoreCliTest.java | 4 ++-- .../java/net/sourceforge/pmd/cpd/CPDFilelistTest.java | 6 +++--- .../test/java/net/sourceforge/pmd/cpd/CpdXsltTest.java | 5 +++-- .../net/sourceforge/pmd/document/DocumentFileTest.java | 7 ++++--- .../net/sourceforge/pmd/junit/JavaUtilLoggingRule.java | 9 +++++++-- .../net/sourceforge/pmd/lang/DummyLanguageModule.java | 4 ++-- .../pmd/renderers/AbstractRendererTest.java | 4 ++-- .../sourceforge/pmd/renderers/JsonRendererTest.java | 4 ++-- .../sourceforge/pmd/renderers/SarifRendererTest.java | 5 ++--- .../net/sourceforge/pmd/renderers/XMLRendererTest.java | 4 ++-- .../sourceforge/pmd/renderers/YAHTMLRendererTest.java | 10 +++++----- .../pmd/util/treeexport/TreeExportCliTest.java | 4 ++-- .../sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt | 4 ++-- .../sourceforge/pmd/AbstractRuleSetFactoryTest.java | 4 ++-- 35 files changed, 97 insertions(+), 100 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java index 6ed1d189a4e..2d4c1ab420d 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactoryCompatibility.java @@ -16,9 +16,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.io.IOUtils; - import net.sourceforge.pmd.annotation.InternalApi; +import net.sourceforge.pmd.util.IOUtil; /** * Provides a simple filter mechanism to avoid failing to parse an old ruleset, @@ -116,7 +115,7 @@ void addFilterRuleRemoved(String language, String ruleset, String name) { * @throws IOException if the stream couldn't be read */ public Reader filterRuleSetFile(InputStream stream) throws IOException { - byte[] bytes = IOUtils.toByteArray(stream); + byte[] bytes = IOUtil.toByteArray(stream); String encoding = determineEncoding(bytes); String ruleset = new String(bytes, encoding); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java index 97aa27ca45a..07691f4e127 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetWriter.java @@ -22,7 +22,6 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; -import org.apache.commons.io.IOUtils; import org.w3c.dom.CDATASection; import org.w3c.dom.DOMException; import org.w3c.dom.Document; @@ -37,6 +36,7 @@ import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyDescriptorField; import net.sourceforge.pmd.properties.PropertyTypeId; +import net.sourceforge.pmd.util.IOUtil; /** * This class represents a way to serialize a RuleSet to an XML configuration @@ -62,7 +62,7 @@ public RuleSetWriter(OutputStream outputStream) { } public void close() { - IOUtils.closeQuietly(outputStream); + IOUtil.closeQuietly(outputStream); } public void write(RuleSet ruleSet) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java index da031a01520..e248dc6f187 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java @@ -18,7 +18,6 @@ import java.util.List; import java.util.Properties; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.reflect.FieldUtils; import org.apache.commons.lang3.reflect.MethodUtils; @@ -30,6 +29,7 @@ import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.renderers.RendererFactory; +import net.sourceforge.pmd.util.IOUtil; public class Formatter { @@ -187,8 +187,8 @@ private static Writer getToFileWriter(String baseDir, File toFile, Charset chars isOnError = false; } finally { if (isOnError) { - IOUtils.closeQuietly(output); - IOUtils.closeQuietly(writer); + IOUtil.closeQuietly(output); + IOUtil.closeQuietly(writer); } } return writer; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cache/AbstractAnalysisCache.java b/pmd-core/src/main/java/net/sourceforge/pmd/cache/AbstractAnalysisCache.java index 57568be50ca..ce3b5056cf6 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cache/AbstractAnalysisCache.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cache/AbstractAnalysisCache.java @@ -23,8 +23,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import org.apache.commons.io.FilenameUtils; - import net.sourceforge.pmd.PMDVersion; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleSets; @@ -35,6 +33,7 @@ import net.sourceforge.pmd.benchmark.TimedOperationCategory; import net.sourceforge.pmd.cache.internal.ClasspathFingerprinter; import net.sourceforge.pmd.stat.Metric; +import net.sourceforge.pmd.util.IOUtil; /** * Abstract implementation of the analysis cache. Handles all operations, except for persistence. @@ -189,7 +188,7 @@ public FileVisitResult visitFile(final Path file, @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { - String extension = FilenameUtils.getExtension(file.toString()); + String extension = IOUtil.getFilenameExtension(file.toString()); if ("jar".equalsIgnoreCase(extension)) { fileVisitor.visitFile(file, attrs); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cache/AnalysisResult.java b/pmd-core/src/main/java/net/sourceforge/pmd/cache/AnalysisResult.java index 0e5f5d9736b..4fa7f0e0f68 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cache/AnalysisResult.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cache/AnalysisResult.java @@ -13,10 +13,9 @@ import java.util.zip.Adler32; import java.util.zip.CheckedInputStream; -import org.apache.commons.io.IOUtils; - import net.sourceforge.pmd.RuleViolation; import net.sourceforge.pmd.annotation.InternalApi; +import net.sourceforge.pmd.util.IOUtil; /** * The result of a single file analysis. @@ -45,8 +44,7 @@ private static long computeFileChecksum(final File sourceFile) { new BufferedInputStream(Files.newInputStream(sourceFile.toPath())), new Adler32()); ) { // Just read it, the CheckedInputStream will update the checksum on it's own - IOUtils.skipFully(stream, sourceFile.length()); - + IOUtil.skipFully(stream, sourceFile.length()); return stream.getChecksum().getValue(); } catch (final IOException ignored) { // We don't really care, if it's unreadable diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cache/internal/RawFileFingerprinter.java b/pmd-core/src/main/java/net/sourceforge/pmd/cache/internal/RawFileFingerprinter.java index 6f8854f09c5..a183e69f091 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cache/internal/RawFileFingerprinter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cache/internal/RawFileFingerprinter.java @@ -14,7 +14,7 @@ import java.util.zip.CheckedInputStream; import java.util.zip.Checksum; -import org.apache.commons.io.IOUtils; +import net.sourceforge.pmd.util.IOUtil; /** * Base fingerprinter for raw files. @@ -40,7 +40,7 @@ public boolean appliesTo(String fileExtension) { public void fingerprint(URL entry, Checksum checksum) throws IOException { try (CheckedInputStream inputStream = new CheckedInputStream(entry.openStream(), checksum)) { // Just read it, the CheckedInputStream will update the checksum on it's own - while (IOUtils.skip(inputStream, Long.MAX_VALUE) == Long.MAX_VALUE) { + while (IOUtil.skipFully(inputStream, Long.MAX_VALUE) == Long.MAX_VALUE) { // just loop } } catch (final FileNotFoundException ignored) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPD.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPD.java index a18b4d2791b..130791c1238 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPD.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/CPD.java @@ -17,11 +17,10 @@ import java.util.logging.Level; import java.util.logging.Logger; -import org.apache.commons.io.FilenameUtils; - import net.sourceforge.pmd.annotation.Experimental; import net.sourceforge.pmd.lang.ast.TokenMgrError; import net.sourceforge.pmd.util.FileFinder; +import net.sourceforge.pmd.util.IOUtil; import net.sourceforge.pmd.util.database.DBMSMetadata; import net.sourceforge.pmd.util.database.DBURI; import net.sourceforge.pmd.util.database.SourceObject; @@ -93,8 +92,7 @@ public void add(File file) throws IOException { current.add(signature); } - if (!FilenameUtils.equalsNormalizedOnSystem(file.getAbsoluteFile().getCanonicalPath(), - file.getAbsolutePath())) { + if (!IOUtil.equalsNormalizedPaths(file.getAbsoluteFile().getCanonicalPath(), file.getAbsolutePath())) { System.err.println("Skipping " + file + " since it appears to be a symlink"); return; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java index 99cf8f88297..b7ac55af7b2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java @@ -14,8 +14,7 @@ import java.util.ArrayList; import java.util.List; -import org.apache.commons.io.ByteOrderMark; -import org.apache.commons.io.input.BOMInputStream; +import net.sourceforge.pmd.util.IOUtil; public class SourceCode { @@ -112,11 +111,10 @@ public FileCodeLoader(File file, String encoding) { @Override public Reader getReader() throws Exception { - BOMInputStream inputStream = new BOMInputStream(Files.newInputStream(file.toPath()), ByteOrderMark.UTF_8, - ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE); + IOUtil.BomAwareInputStream inputStream = new IOUtil.BomAwareInputStream(Files.newInputStream(file.toPath())); - if (inputStream.hasBOM()) { - encoding = inputStream.getBOMCharsetName(); + if (inputStream.hasBom()) { + encoding = inputStream.getBomCharsetName(); } return new InputStreamReader(inputStream, encoding); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/document/DocumentFile.java b/pmd-core/src/main/java/net/sourceforge/pmd/document/DocumentFile.java index 7c3e1640c0b..0c1bae358a1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/document/DocumentFile.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/document/DocumentFile.java @@ -21,7 +21,7 @@ import java.util.logging.Level; import java.util.logging.Logger; -import org.apache.commons.io.IOUtils; +import net.sourceforge.pmd.util.IOUtil; /** * Implementation that handles a Document as a file in the filesystem and receives operations in a sorted manner @@ -159,7 +159,7 @@ public void close() throws IOException { } private void writeUntilEOF() throws IOException { - IOUtils.copy(reader, writer); + IOUtil.copy(reader, writer); } /* package-private */ List getLineToOffset() { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/FileCollectionUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/FileCollectionUtil.java index 68e1ab16e13..e8041d34305 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/FileCollectionUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/internal/util/FileCollectionUtil.java @@ -15,13 +15,12 @@ import java.util.List; import java.util.Set; -import org.apache.commons.io.IOUtils; - import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.document.FileCollector; import net.sourceforge.pmd.lang.document.TextFile; import net.sourceforge.pmd.util.FileUtil; +import net.sourceforge.pmd.util.IOUtil; import net.sourceforge.pmd.util.database.DBMSMetadata; import net.sourceforge.pmd.util.database.DBURI; import net.sourceforge.pmd.util.database.SourceObject; @@ -157,7 +156,7 @@ public static void collectDB(FileCollector collector, String uriString) { collector.getReporter().trace("Adding database source object {0}", falseFilePath); try (Reader sourceCode = dbmsMetadata.getSourceCode(sourceObject)) { - String source = IOUtils.toString(sourceCode); + String source = IOUtil.readToString(sourceCode); collector.addSourceFile(source, falseFilePath); } catch (SQLException ex) { collector.getReporter().warnEx("Cannot get SourceCode for {0} - skipping ...", diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java index 705ef530a72..c7d77e1de88 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/document/NioTextFile.java @@ -12,11 +12,10 @@ import java.nio.file.Path; import java.util.Objects; -import org.apache.commons.io.IOUtils; - import net.sourceforge.pmd.annotation.Experimental; import net.sourceforge.pmd.internal.util.AssertionUtil; import net.sourceforge.pmd.lang.LanguageVersion; +import net.sourceforge.pmd.util.IOUtil; import net.sourceforge.pmd.util.datasource.DataSource; import net.sourceforge.pmd.util.datasource.FileDataSource; @@ -68,7 +67,7 @@ public String readContents() throws IOException { } try (BufferedReader br = Files.newBufferedReader(path, charset)) { - return IOUtils.toString(br); + return IOUtil.readToString(br); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java index 8da879721fb..93a1487e0f3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/AbstractPMDProcessor.java @@ -11,7 +11,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.exception.ContextedRuntimeException; import net.sourceforge.pmd.PMDConfiguration; @@ -27,6 +26,7 @@ import net.sourceforge.pmd.benchmark.TimedOperation; import net.sourceforge.pmd.benchmark.TimedOperationCategory; import net.sourceforge.pmd.renderers.Renderer; +import net.sourceforge.pmd.util.IOUtil; import net.sourceforge.pmd.util.datasource.DataSource; /** @@ -151,7 +151,7 @@ public void processFiles(RuleSets rulesets, List files, RuleContext // in case we analyzed files within Zip Files/Jars, we need to close them after // the analysis is finished for (DataSource dataSource : files) { - IOUtils.closeQuietly(dataSource); + IOUtil.closeQuietly(dataSource); } } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/AbstractRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/AbstractRenderer.java index 88b69d2202f..5ee89c4cc23 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/AbstractRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/AbstractRenderer.java @@ -9,8 +9,6 @@ import java.util.Collections; import java.util.List; -import org.apache.commons.io.IOUtils; - import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.annotation.Experimental; import net.sourceforge.pmd.cli.PMDParameters; @@ -108,7 +106,7 @@ public void flush() { } catch (IOException e) { throw new IllegalStateException(e); } finally { - IOUtils.closeQuietly(writer); + IOUtil.closeQuietly(writer); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java index f9dfd96a726..e7adaa64269 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java @@ -21,13 +21,13 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; -import org.apache.commons.io.output.WriterOutputStream; import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.PMDVersion; import net.sourceforge.pmd.Report; import net.sourceforge.pmd.RuleViolation; import net.sourceforge.pmd.properties.StringProperty; +import net.sourceforge.pmd.util.IOUtil; import net.sourceforge.pmd.util.StringUtil; /** @@ -256,7 +256,7 @@ public void setReportFile(String reportFilename) { public void setWriter(final Writer writer) { String encoding = getProperty(ENCODING); // for backwards compatibility, create a OutputStream that writes to the writer. - this.stream = new WriterOutputStream(writer, encoding); + this.stream = IOUtil.fromWriter(writer, encoding); XMLOutputFactory outputFactory = XMLOutputFactory.newFactory(); try { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/FileFinder.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/FileFinder.java index 874a004bcf7..c632997409a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/FileFinder.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/FileFinder.java @@ -8,10 +8,9 @@ import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.List; -import org.apache.commons.io.comparator.PathFileComparator; - import net.sourceforge.pmd.annotation.InternalApi; /** @@ -49,7 +48,12 @@ private void scanDirectory(File dir, List list, boolean recurse) { return; } - Arrays.sort(candidates, PathFileComparator.PATH_INSENSITIVE_COMPARATOR); + Arrays.sort(candidates, new Comparator() { + @Override + public int compare(File o1, File o2) { + return o1.getPath().compareToIgnoreCase(o2.getPath()); + } + }); for (File tmp : candidates) { if (tmp.isDirectory()) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java index 7b2bd58d575..efb047050f1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/FileUtil.java @@ -20,7 +20,6 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.annotation.InternalApi; @@ -181,7 +180,7 @@ public static boolean findPatternInFile(final File file, final String pattern) { * @throws IOException if the file couldn't be read */ public static String readFilelist(File filelist) throws IOException { - String filePaths = FileUtils.readFileToString(filelist); + String filePaths = IOUtil.readFileToString(filelist); filePaths = StringUtils.trimToEmpty(filePaths); filePaths = filePaths.replaceAll("\\r?\\n", ","); filePaths = filePaths.replaceAll(",+", ","); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/ReaderDataSource.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/ReaderDataSource.java index ec21c09f4bd..fe530ae40cc 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/ReaderDataSource.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/datasource/ReaderDataSource.java @@ -8,8 +8,7 @@ import java.io.InputStream; import java.io.Reader; -import org.apache.commons.io.input.ReaderInputStream; - +import net.sourceforge.pmd.util.IOUtil; import net.sourceforge.pmd.util.datasource.internal.AbstractDataSource; /** @@ -50,7 +49,7 @@ public ReaderDataSource(Reader reader, String dataSourceName) { */ @Override public InputStream getInputStream() throws IOException { - return new ReaderInputStream(reader); + return IOUtil.fromReader(reader); } /** diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryCompatibilityTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryCompatibilityTest.java index 7dfb6e1f093..b573c371f15 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryCompatibilityTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryCompatibilityTest.java @@ -9,10 +9,10 @@ import java.io.Reader; import java.nio.charset.StandardCharsets; -import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; +import net.sourceforge.pmd.util.IOUtil; import net.sourceforge.pmd.util.ResourceLoader; public class RuleSetFactoryCompatibilityTest { @@ -48,7 +48,7 @@ public void testCorrectMovedAndRename() throws Exception { InputStream stream = new ByteArrayInputStream(ruleset.getBytes(StandardCharsets.ISO_8859_1)); Reader filtered = rsfc.filterRuleSetFile(stream); - String out = IOUtils.toString(filtered); + String out = IOUtil.readToString(filtered); Assert.assertFalse(out.contains("notexisting.xml")); Assert.assertFalse(out.contains("OldDummyBasicMockRule")); @@ -90,7 +90,7 @@ public void testExclusionRenamedAndMoved() throws Exception { InputStream stream = new ByteArrayInputStream(ruleset.getBytes(StandardCharsets.ISO_8859_1)); Reader filtered = rsfc.filterRuleSetFile(stream); - String out = IOUtils.toString(filtered); + String out = IOUtil.readToString(filtered); Assert.assertTrue(out.contains("OldDummyBasicMockRule")); } @@ -112,7 +112,7 @@ public void testFilter() throws Exception { + " \n" + "\n"; InputStream stream = new ByteArrayInputStream(in.getBytes(StandardCharsets.ISO_8859_1)); Reader filtered = rsfc.filterRuleSetFile(stream); - String out = IOUtils.toString(filtered); + String out = IOUtil.readToString(filtered); Assert.assertFalse(out.contains("notexisting.xml")); Assert.assertTrue(out.contains("")); @@ -136,7 +136,7 @@ public void testExclusionFilter() throws Exception { + " \n" + " \n" + "\n"; InputStream stream = new ByteArrayInputStream(in.getBytes(StandardCharsets.ISO_8859_1)); Reader filtered = rsfc.filterRuleSetFile(stream); - String out = IOUtils.toString(filtered); + String out = IOUtil.readToString(filtered); Assert.assertFalse(out.contains("OldNameOfBasicMockRule")); Assert.assertTrue(out.contains("")); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetReferenceIdTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetReferenceIdTest.java index 09140455729..fa48c866987 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetReferenceIdTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetReferenceIdTest.java @@ -22,9 +22,9 @@ import java.nio.charset.StandardCharsets; import java.util.List; -import org.apache.commons.io.IOUtils; import org.junit.Test; +import net.sourceforge.pmd.util.IOUtil; import net.sourceforge.pmd.util.ResourceLoader; import com.github.tomakehurst.wiremock.junit.WireMockRule; @@ -123,7 +123,7 @@ public void testConstructorGivenHttpUrlInputStream() throws Exception { assertRuleSetReferenceId(true, rulesetUrl, true, null, rulesetUrl, ruleSetReferenceId); try (InputStream inputStream = ruleSetReferenceId.getInputStream(new ResourceLoader())) { - String loaded = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + String loaded = IOUtil.readToString(inputStream, StandardCharsets.UTF_8); assertEquals("xyz", loaded); } @@ -139,8 +139,8 @@ public void testConstructorGivenHttpUrlSingleRuleInputStream() throws Exception String path = "/profiles/export?format=pmd&language=java&name=Sonar%2520way"; String completePath = path + "/DummyBasicMockRule"; String hostpart = "http://localhost:" + wireMockRule.port(); - String basicRuleSet = IOUtils - .toString(RuleSetReferenceId.class.getResourceAsStream("/rulesets/dummy/basic.xml"), StandardCharsets.UTF_8); + String basicRuleSet = IOUtil + .readToString(RuleSetReferenceId.class.getResourceAsStream("/rulesets/dummy/basic.xml"), StandardCharsets.UTF_8); stubFor(head(urlEqualTo(completePath)).willReturn(aResponse().withStatus(404))); stubFor(head(urlEqualTo(path)).willReturn(aResponse().withStatus(200).withHeader("Content-type", "text/xml"))); @@ -152,7 +152,7 @@ public void testConstructorGivenHttpUrlSingleRuleInputStream() throws Exception ruleSetReferenceId); try (InputStream inputStream = ruleSetReferenceId.getInputStream(new ResourceLoader())) { - String loaded = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + String loaded = IOUtil.readToString(inputStream, StandardCharsets.UTF_8); assertEquals(basicRuleSet, loaded); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java index 7c0f5c88130..14f4db10726 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java @@ -22,7 +22,6 @@ import java.util.Set; import java.util.regex.Pattern; -import org.apache.commons.io.FilenameUtils; import org.junit.Test; import net.sourceforge.pmd.Report.ProcessingError; @@ -35,6 +34,7 @@ import net.sourceforge.pmd.lang.rule.MockRule; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.util.CollectionUtil; +import net.sourceforge.pmd.util.IOUtil; public class RuleSetTest { @@ -582,7 +582,7 @@ public void apply(List nodes, RuleContext ctx) { assertTrue("Should be a RuntimeException", processingError.getError() instanceof RuntimeException); assertEquals("Wrong filename in processing error", "net.sourceforge.pmd.RuleSetTest/ruleExceptionShouldBeReported.java", - FilenameUtils.normalize(processingError.getFile(), true)); + IOUtil.normalizePath(processingError.getFile())); assertEquals("There should be a violation", 1, context.getReport().size()); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java index 48acda9ba2c..fba597a5f17 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/ant/PMDTaskTest.java @@ -11,7 +11,6 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; -import org.apache.commons.io.IOUtils; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildFileRule; import org.junit.Assert; @@ -19,6 +18,8 @@ import org.junit.Rule; import org.junit.Test; +import net.sourceforge.pmd.util.IOUtil; + public class PMDTaskTest { @Rule @@ -74,7 +75,7 @@ public void testWithShortFilenames() throws IOException { buildRule.executeTarget("testWithShortFilenames"); try (InputStream in = new FileInputStream("target/pmd-ant-test.txt")) { - String actual = IOUtils.toString(in, StandardCharsets.UTF_8); + String actual = IOUtil.readToString(in, StandardCharsets.UTF_8); // remove any trailing newline actual = actual.replaceAll("\n|\r", ""); Assert.assertEquals("sample.dummy:0:\tSampleXPathRule:\tTest Rule 2", actual); @@ -87,11 +88,11 @@ public void testXmlFormatter() throws IOException { try (InputStream in = new FileInputStream("target/pmd-ant-xml.xml"); InputStream expectedStream = PMDTaskTest.class.getResourceAsStream("xml/expected-pmd-ant-xml.xml")) { - String actual = IOUtils.toString(in, StandardCharsets.UTF_8); + String actual = IOUtil.readToString(in, StandardCharsets.UTF_8); actual = actual.replaceFirst("timestamp=\"[^\"]+\"", "timestamp=\"\""); actual = actual.replaceFirst("\\.xsd\" version=\"[^\"]+\"", ".xsd\" version=\"\""); - String expected = IOUtils.toString(expectedStream, StandardCharsets.UTF_8); + String expected = IOUtil.readToString(expectedStream, StandardCharsets.UTF_8); expected = expected.replaceFirst("timestamp=\"[^\"]+\"", "timestamp=\"\""); expected = expected.replaceFirst("\\.xsd\" version=\"[^\"]+\"", ".xsd\" version=\"\""); 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 157caf975de..e8d19a0c361 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 @@ -20,7 +20,6 @@ import java.nio.file.Path; import java.util.logging.Logger; -import org.apache.commons.io.IOUtils; import org.hamcrest.Matcher; import org.junit.Before; import org.junit.Rule; @@ -33,6 +32,7 @@ import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMD.StatusCode; import net.sourceforge.pmd.junit.JavaUtilLoggingRule; +import net.sourceforge.pmd.util.IOUtil; /** * @@ -131,7 +131,7 @@ public void testFileCollectionWithUnknownFiles() throws IOException { runPmdSuccessfully("--no-cache", "--dir", srcDir, "--rulesets", DUMMY_RULESET, "--report-file", reportFile, "--debug"); assertTrue("Report file should have been created", Files.exists(reportFile)); - String reportText = IOUtils.toString(Files.newBufferedReader(reportFile, StandardCharsets.UTF_8)); + String reportText = IOUtil.readToString(Files.newBufferedReader(reportFile, StandardCharsets.UTF_8)); assertThat(reportText, not(containsStringIgnoringCase("error"))); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDFilelistTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDFilelistTest.java index 5c21740f857..74604cc10ae 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDFilelistTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CPDFilelistTest.java @@ -7,11 +7,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.nio.file.Paths; import java.util.HashSet; import java.util.List; import java.util.Set; -import org.apache.commons.io.FilenameUtils; import org.junit.Test; public class CPDFilelistTest { @@ -28,7 +28,7 @@ public void testFilelist() { assertEquals(2, paths.size()); Set simpleNames = new HashSet<>(); for (String path : paths) { - simpleNames.add(FilenameUtils.getName(path)); + simpleNames.add(Paths.get(path).getFileName().toString()); } assertTrue(simpleNames.contains("anotherfile.dummy")); assertTrue(simpleNames.contains("somefile.dummy")); @@ -46,7 +46,7 @@ public void testFilelistMultipleLines() { assertEquals(2, paths.size()); Set simpleNames = new HashSet<>(); for (String path : paths) { - simpleNames.add(FilenameUtils.getName(path)); + simpleNames.add(Paths.get(path).getFileName().toString()); } assertTrue(simpleNames.contains("anotherfile.dummy")); assertTrue(simpleNames.contains("somefile.dummy")); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdXsltTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdXsltTest.java index 085475f8d00..af8d5ada202 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdXsltTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/cpd/CpdXsltTest.java @@ -17,10 +17,11 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; -import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; +import net.sourceforge.pmd.util.IOUtil; + public class CpdXsltTest { /* Sample ant build.xml file. Run with "ant cpdxsl". @@ -49,7 +50,7 @@ public void cpdhtml() throws Exception { transformer.setErrorListener(errorListener); transformer.transform(cpdReport, result); - String expected = IOUtils.toString(CpdXsltTest.class.getResourceAsStream("ExpectedCpdHtmlReport.html"), StandardCharsets.UTF_8); + String expected = IOUtil.readToString(CpdXsltTest.class.getResourceAsStream("ExpectedCpdHtmlReport.html"), StandardCharsets.UTF_8); Assert.assertEquals(expected, result.getWriter().toString()); Assert.assertTrue("XSLT errors occured: " + errorListener, errorListener.hasNoErrors()); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/document/DocumentFileTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/document/DocumentFileTest.java index ece529938d6..d578dec542f 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/document/DocumentFileTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/document/DocumentFileTest.java @@ -16,12 +16,13 @@ import java.util.Arrays; import java.util.List; -import org.apache.commons.io.IOUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import net.sourceforge.pmd.util.IOUtil; + public class DocumentFileTest { private static final String FILE_PATH = "psvm.java"; @@ -51,8 +52,8 @@ public void insertAtStartOfTheFileShouldSucceed() throws IOException { @Test public void shouldPreserveNewlines() throws IOException { - final String testFileContent = IOUtils.toString( - DocumentFileTest.class.getResource("ShouldPreserveNewlines.java"), StandardCharsets.UTF_8); + final String testFileContent = IOUtil.readToString( + DocumentFileTest.class.getResourceAsStream("ShouldPreserveNewlines.java"), StandardCharsets.UTF_8); writeContentToTemporaryFile(testFileContent); try (DocumentFile documentFile = new DocumentFile(temporaryFile, StandardCharsets.UTF_8)) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/junit/JavaUtilLoggingRule.java b/pmd-core/src/test/java/net/sourceforge/pmd/junit/JavaUtilLoggingRule.java index 572ed0388fa..da674a405a5 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/junit/JavaUtilLoggingRule.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/junit/JavaUtilLoggingRule.java @@ -4,11 +4,12 @@ package net.sourceforge.pmd.junit; +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.util.logging.Logger; import java.util.logging.StreamHandler; -import org.apache.commons.io.output.ByteArrayOutputStream; import org.junit.rules.ExternalResource; /** @@ -63,7 +64,11 @@ protected void after() { */ public String getLog() { customLogHandler.flush(); - return stream.toString(StandardCharsets.UTF_8); + try { + return stream.toString(StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } } /** diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/DummyLanguageModule.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/DummyLanguageModule.java index a439fa10db7..901ef705344 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/DummyLanguageModule.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/DummyLanguageModule.java @@ -12,7 +12,6 @@ import java.util.List; import java.util.Map; -import org.apache.commons.io.IOUtils; import org.jaxen.Navigator; import net.sourceforge.pmd.Rule; @@ -29,6 +28,7 @@ import net.sourceforge.pmd.lang.rule.AbstractRuleViolationFactory; import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; import net.sourceforge.pmd.lang.rule.RuleChainVisitor; +import net.sourceforge.pmd.util.IOUtil; import net.sf.saxon.expr.XPathContext; import net.sf.saxon.sxpath.IndependentContext; @@ -130,7 +130,7 @@ public Parser getParser(ParserOptions parserOptions) { @Override public Node parse(String fileName, Reader source) throws ParseException { try { - String text = IOUtils.toString(source); + String text = IOUtil.readToString(source); DummyRootNode rootNode = readLispNode(text); AbstractParser.setFileName(fileName, rootNode); return rootNode; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java index faa66b88e49..52a5a2e2938 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java @@ -10,7 +10,6 @@ import java.io.IOException; import java.nio.charset.Charset; -import org.apache.commons.io.FileUtils; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -26,6 +25,7 @@ import net.sourceforge.pmd.lang.ast.DummyNode; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; +import net.sourceforge.pmd.util.IOUtil; public abstract class AbstractRendererTest { @@ -204,6 +204,6 @@ protected String renderReport(Renderer renderer, Report report, Charset expected renderer.renderFileReport(report); renderer.end(); renderer.flush(); - return FileUtils.readFileToString(file, expectedEncoding); + return IOUtil.readFileToString(file, expectedEncoding); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/JsonRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/JsonRendererTest.java index 38f3a1ad9a1..2ef04e695a5 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/JsonRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/JsonRendererTest.java @@ -11,7 +11,6 @@ import java.util.HashMap; import java.util.Map; -import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; @@ -19,6 +18,7 @@ import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report.ConfigurationError; import net.sourceforge.pmd.Report.ProcessingError; +import net.sourceforge.pmd.util.IOUtil; public class JsonRendererTest extends AbstractRendererTest { @@ -69,7 +69,7 @@ public String getExpectedErrorWithoutMessage(ProcessingError error) { private String readFile(String name) { try (InputStream in = JsonRendererTest.class.getResourceAsStream("json/" + name)) { - return IOUtils.toString(in, StandardCharsets.UTF_8); + return IOUtil.readToString(in, StandardCharsets.UTF_8); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SarifRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SarifRendererTest.java index ae6f605dd47..b13f03ca096 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SarifRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SarifRendererTest.java @@ -10,7 +10,6 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; -import org.apache.commons.io.IOUtils; import org.json.JSONArray; import org.json.JSONObject; import org.junit.Test; @@ -18,7 +17,7 @@ import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Rule; - +import net.sourceforge.pmd.util.IOUtil; public class SarifRendererTest extends AbstractRendererTest { @@ -112,7 +111,7 @@ private Report reportThreeViolationsTwoRules() { private String readFile(String name) { try (InputStream in = SarifRendererTest.class.getResourceAsStream("sarif/" + name)) { - String asd = IOUtils.toString(in, StandardCharsets.UTF_8); + String asd = IOUtil.readToString(in, StandardCharsets.UTF_8); return asd; } catch (IOException e) { throw new RuntimeException(e); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java index e5ef41c5edd..9ead15cf850 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java @@ -12,7 +12,6 @@ import java.nio.charset.StandardCharsets; import javax.xml.parsers.DocumentBuilderFactory; -import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; @@ -33,6 +32,7 @@ import net.sourceforge.pmd.lang.ast.DummyNode; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; +import net.sourceforge.pmd.util.IOUtil; public class XMLRendererTest extends AbstractRendererTest { @Rule // Restores system properties after test @@ -177,7 +177,7 @@ private String renderTempFile(Renderer renderer, Report report, Charset expected renderer.flush(); try (FileInputStream input = new FileInputStream(reportFile)) { - return IOUtils.toString(input, expectedCharset); + return IOUtil.readToString(input, expectedCharset); } } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java index f52cc72a233..0b9ff1dd1f4 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.regex.Pattern; -import org.apache.commons.io.IOUtils; import org.junit.Before; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -30,6 +29,7 @@ import net.sourceforge.pmd.lang.ast.DummyNode; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; +import net.sourceforge.pmd.util.IOUtil; public class YAHTMLRendererTest extends AbstractRendererTest { @@ -79,8 +79,8 @@ public void testReportMultipleViolations() throws Exception { for (String file : htmlFiles) { try (FileInputStream in = new FileInputStream(new File(outputDir, file)); InputStream expectedIn = YAHTMLRendererTest.class.getResourceAsStream("yahtml/" + file)) { - String data = IOUtils.toString(in, StandardCharsets.UTF_8); - String expected = normalizeLineSeparators(IOUtils.toString(expectedIn, StandardCharsets.UTF_8)); + String data = IOUtil.readToString(in, StandardCharsets.UTF_8); + String expected = normalizeLineSeparators(IOUtil.readToString(expectedIn, StandardCharsets.UTF_8)); assertEquals("File " + file + " is different", expected, data); } @@ -88,8 +88,8 @@ public void testReportMultipleViolations() throws Exception { } private static String normalizeLineSeparators(String s) { - return s.replaceAll(Pattern.quote(IOUtils.LINE_SEPARATOR_WINDOWS), IOUtils.LINE_SEPARATOR_UNIX) - .replaceAll(Pattern.quote(IOUtils.LINE_SEPARATOR_UNIX), PMD.EOL); + return s.replaceAll(Pattern.quote("\r\n"), "\n") + .replaceAll(Pattern.quote("\n"), PMD.EOL); } @Override diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/util/treeexport/TreeExportCliTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/util/treeexport/TreeExportCliTest.java index edcf3e660b4..ccd54033506 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/util/treeexport/TreeExportCliTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/util/treeexport/TreeExportCliTest.java @@ -7,6 +7,7 @@ import static org.hamcrest.Matchers.containsString; import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -15,7 +16,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import org.apache.commons.io.IOUtils; import org.hamcrest.Matcher; import org.hamcrest.MatcherAssert; import org.junit.Assert; @@ -67,7 +67,7 @@ private File newFileWithContents(String data) throws IOException { } private static InputStream stdinContaining(String input) { - return IOUtils.toInputStream(input, StandardCharsets.UTF_8); + return new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)); } static class IoSpy { diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt index 560512b1890..2538932a142 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt @@ -7,7 +7,7 @@ import net.sourceforge.pmd.* import net.sourceforge.pmd.lang.* import net.sourceforge.pmd.lang.ast.Node import net.sourceforge.pmd.lang.ast.RootNode -import org.apache.commons.io.IOUtils +import net.sourceforge.pmd.util.IOUtil import java.io.File import java.io.InputStream import java.io.StringReader @@ -160,7 +160,7 @@ abstract class BaseParsingHelper, T : RootNode } private fun consume(input: InputStream) = - IOUtils.toString(input, StandardCharsets.UTF_8) + IOUtil.readToString(input, StandardCharsets.UTF_8) .replace("\r\n", "\n") // normalize line-endings /** diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java index a1aa1327d5b..3fca13161b7 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java @@ -31,7 +31,6 @@ import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; -import org.apache.commons.io.FilenameUtils; import org.junit.BeforeClass; import org.junit.Test; import org.junit.contrib.java.lang.system.SystemErrRule; @@ -45,6 +44,7 @@ import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.util.IOUtil; import net.sourceforge.pmd.util.ResourceLoader; /** @@ -155,7 +155,7 @@ public void testAllPMDBuiltInRulesMeetConventions() throws Exception { } else { String expectedExternalInfoURL = "https?://pmd.(sourceforge.net|github.io)/.+/pmd_rules_" + language.getTerseName() + "_" - + FilenameUtils.getBaseName(fileName) + + IOUtil.getFilenameBase(fileName) + ".html#" + rule.getName().toLowerCase(Locale.ROOT); if (rule.getExternalInfoUrl() == null From abfc463ef9003f2f3d85377b8b21882954550567 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 09:46:46 +0200 Subject: [PATCH 28/54] Update build-tools to 18-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 995f2034769..459fe190c12 100644 --- a/pom.xml +++ b/pom.xml @@ -105,7 +105,7 @@ -Xmx512m -Dfile.encoding=${project.build.sourceEncoding} - 17 + 18-SNAPSHOT 6.37.0 From a4ebb66769e780cc9b2bbe85fa9eb24b6418821f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 10:46:11 +0200 Subject: [PATCH 29/54] Replace IOUtils with IOUtil plsql, xml, apex, html, javascript, scala --- .../java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java | 5 ++--- .../java/net/sourceforge/pmd/lang/html/ast/HtmlParser.java | 4 ++-- .../pmd/lang/ecmascript/ast/EcmascriptParser.java | 4 ++-- .../java/net/sourceforge/pmd/lang/plsql/PLSQLParser.java | 4 +--- .../java/net/sourceforge/pmd/lang/scala/ScalaParser.java | 5 ++--- .../java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java | 4 ++-- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java index a6ff552503f..fea54903e78 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexParser.java @@ -8,12 +8,11 @@ import java.io.Reader; import java.util.Map; -import org.apache.commons.io.IOUtils; - import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.apex.ApexJorjeLogging; import net.sourceforge.pmd.lang.apex.ApexParserOptions; import net.sourceforge.pmd.lang.ast.ParseException; +import net.sourceforge.pmd.util.IOUtil; import apex.jorje.data.Locations; import apex.jorje.semantic.ast.compilation.Compilation; @@ -50,7 +49,7 @@ public Compilation parseApex(final String sourceCode) throws ParseException { public ApexNode parse(final Reader reader) { try { - final String sourceCode = IOUtils.toString(reader); + final String sourceCode = IOUtil.readToString(reader); final Compilation astRoot = parseApex(sourceCode); final ApexTreeBuilder treeBuilder = new ApexTreeBuilder(sourceCode, parserOptions); suppressMap = treeBuilder.getSuppressMap(); diff --git a/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/ast/HtmlParser.java b/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/ast/HtmlParser.java index c61cb4f5a40..1c0b57f65c0 100644 --- a/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/ast/HtmlParser.java +++ b/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/ast/HtmlParser.java @@ -10,7 +10,6 @@ import java.util.HashMap; import java.util.Map; -import org.apache.commons.io.IOUtils; import org.jsoup.nodes.Document; import org.jsoup.parser.Parser; @@ -18,6 +17,7 @@ import net.sourceforge.pmd.lang.TokenManager; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.ParseException; +import net.sourceforge.pmd.util.IOUtil; public final class HtmlParser implements net.sourceforge.pmd.lang.Parser { @@ -29,7 +29,7 @@ public boolean canParse() { @Override public Node parse(String fileName, Reader source) throws ParseException { try { - String data = IOUtils.toString(source); + String data = IOUtil.readToString(source); Document doc = Parser.xmlParser().parseInput(data, ""); HtmlTreeBuilder builder = new HtmlTreeBuilder(); return builder.build(doc, data); diff --git a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParser.java b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParser.java index 359d96b0b4d..156728171ce 100644 --- a/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParser.java +++ b/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/ast/EcmascriptParser.java @@ -11,7 +11,6 @@ import java.util.List; import java.util.Map; -import org.apache.commons.io.IOUtils; import org.mozilla.javascript.CompilerEnvirons; import org.mozilla.javascript.Parser; import org.mozilla.javascript.ast.AstRoot; @@ -22,6 +21,7 @@ import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.ParseException; import net.sourceforge.pmd.lang.ecmascript.EcmascriptParserOptions; +import net.sourceforge.pmd.util.IOUtil; public class EcmascriptParser { @Deprecated @@ -64,7 +64,7 @@ protected AstRoot parseEcmascript(final String sourceCode, final List parse(final Reader reader) { try { final List parseProblems = new ArrayList<>(); - final String sourceCode = IOUtils.toString(reader); + final String sourceCode = IOUtil.readToString(reader); final AstRoot astRoot = parseEcmascript(sourceCode, parseProblems); final EcmascriptTreeBuilder treeBuilder = new EcmascriptTreeBuilder(sourceCode, parseProblems); EcmascriptNode tree = treeBuilder.build(astRoot); diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLParser.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLParser.java index 4466d614809..442a6c8be0a 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLParser.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLParser.java @@ -10,8 +10,6 @@ import java.util.HashMap; import java.util.Map; -import org.apache.commons.io.IOUtils; - import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.AbstractParser; import net.sourceforge.pmd.lang.LanguageVersionHandler; @@ -56,7 +54,7 @@ public boolean canParse() { @Override public Node parse(String fileName, Reader source) throws ParseException { try { - String sourcecode = IOUtils.toString(source); + String sourcecode = IOUtil.readToString(source); AbstractTokenManager.setFileName(fileName); return createPLSQLParser(new StringReader(sourcecode)).Input(sourcecode); } catch (IOException e) { diff --git a/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/lang/scala/ScalaParser.java b/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/lang/scala/ScalaParser.java index 8edb8d5ab9b..ded0c0c04a7 100644 --- a/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/lang/scala/ScalaParser.java +++ b/pmd-scala-modules/pmd-scala-common/src/main/java/net/sourceforge/pmd/lang/scala/ScalaParser.java @@ -9,13 +9,12 @@ import java.util.HashMap; import java.util.Map; -import org.apache.commons.io.IOUtils; - import net.sourceforge.pmd.lang.AbstractParser; import net.sourceforge.pmd.lang.ParserOptions; import net.sourceforge.pmd.lang.TokenManager; import net.sourceforge.pmd.lang.ast.ParseException; import net.sourceforge.pmd.lang.scala.ast.ASTSource; +import net.sourceforge.pmd.util.IOUtil; import scala.meta.Dialect; import scala.meta.Source; @@ -52,7 +51,7 @@ public boolean canParse() { public ASTSource parse(String fileName, Reader source) throws ParseException { Input.VirtualFile virtualFile; try { - String sourceString = IOUtils.toString(source); + String sourceString = IOUtil.readToString(source); virtualFile = new Input.VirtualFile(fileName, sourceString); } catch (IOException e) { throw new ParseException(e); diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java index 2bf8d097f9c..9ac23763894 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/XmlParser.java @@ -13,7 +13,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import org.apache.commons.io.IOUtils; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; @@ -22,6 +21,7 @@ import net.sourceforge.pmd.lang.ast.ParseException; import net.sourceforge.pmd.lang.ast.RootNode; import net.sourceforge.pmd.lang.xml.XmlParserOptions; +import net.sourceforge.pmd.util.IOUtil; public class XmlParser { @@ -37,7 +37,7 @@ public XmlParser(XmlParserOptions parserOptions) { protected Document parseDocument(Reader reader) throws ParseException { nodeCache.clear(); try { - String xmlData = IOUtils.toString(reader); + String xmlData = IOUtil.readToString(reader); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(parserOptions.isNamespaceAware()); From a1922c59565283c701dbb8aa8746badc11ca095f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 11:18:55 +0200 Subject: [PATCH 30/54] [dist] Replace IOUtils with IOUtil --- .../java/net/sourceforge/pmd/it/AntIT.java | 36 +++++++++++++++---- .../net/sourceforge/pmd/it/PMDExecutor.java | 12 ++++--- .../sourceforge/pmd/it/ZipFileExtractor.java | 5 +-- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AntIT.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AntIT.java index 6d11b7d9d72..2c840d24873 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AntIT.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AntIT.java @@ -8,15 +8,19 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.concurrent.TimeUnit; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.SystemUtils; import org.junit.Assume; import org.junit.Test; import net.sourceforge.pmd.PMDVersion; +import net.sourceforge.pmd.util.IOUtil; /** * This test calls ant in a fake terminal to make sure we have a {@link java.io.Console} connected. @@ -41,10 +45,28 @@ public void runAnt() throws IOException, InterruptedException { private File prepareAntTestProjectFolder() throws IOException { - File sourceProjectFolder = new File("src/test/resources/ant-it"); - File projectFolder = folder.newFolder(); - FileUtils.copyDirectory(sourceProjectFolder, projectFolder); - return projectFolder; + final Path sourceProjectFolder = new File("src/test/resources/ant-it").toPath(); + final Path projectFolder = folder.newFolder().toPath(); + Files.walkFileTree(sourceProjectFolder, new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + assert !dir.isAbsolute(); + Path target = projectFolder.resolve(sourceProjectFolder.relativize(dir)); + if (!target.toFile().exists()) { + target.toFile().mkdir(); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + assert !file.isAbsolute(); + Path target = projectFolder.resolve(sourceProjectFolder.relativize(file)); + Files.copy(file, target); + return FileVisitResult.CONTINUE; + } + }); + return projectFolder.toFile(); } @@ -64,7 +86,7 @@ private ExecutionResult runAnt(String antLibPath, String pmdHomePath, File antTe @Override public void run() { try (InputStream in = process.getInputStream()) { - String output = IOUtils.toString(process.getInputStream(), StandardCharsets.UTF_8); + String output = IOUtil.readToString(process.getInputStream(), StandardCharsets.UTF_8); result.withOutput(output); } catch (IOException e) { result.withOutput("Exception occurred: " + e.toString()); diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/PMDExecutor.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/PMDExecutor.java index fdfaf79acb0..69bd4bb3ce3 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/PMDExecutor.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/PMDExecutor.java @@ -5,18 +5,20 @@ package net.sourceforge.pmd.it; import java.io.IOException; +import java.io.Reader; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import net.sourceforge.pmd.PMDVersion; +import net.sourceforge.pmd.util.IOUtil; /** * Executes PMD from command line. Deals with the differences, when PMD is run on Windows or on Linux. @@ -59,7 +61,7 @@ static ExecutionResult runCommand(String cmd, List arguments, Path repor public void run() { String output; try { - output = IOUtils.toString(process.getInputStream(), StandardCharsets.UTF_8); + output = IOUtil.readToString(process.getInputStream(), StandardCharsets.UTF_8); result.withOutput(output); } catch (IOException e) { result.withOutput("Exception occurred: " + e.toString()); @@ -72,7 +74,7 @@ public void run() { public void run() { String error; try { - error = IOUtils.toString(process.getErrorStream(), StandardCharsets.UTF_8); + error = IOUtil.readToString(process.getErrorStream(), StandardCharsets.UTF_8); result.withErrorOutput(error); } catch (IOException e) { result.withErrorOutput("Exception occurred: " + e.toString()); @@ -87,7 +89,9 @@ public void run() { String report = null; if (reportFile != null) { - report = IOUtils.toString(reportFile.toUri(), StandardCharsets.UTF_8); + try (Reader reader = Files.newBufferedReader(reportFile, StandardCharsets.UTF_8)) { + report = IOUtil.readToString(reader); + } } return result.withExitCode(exitCode).withReport(report).build(); } diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/ZipFileExtractor.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/ZipFileExtractor.java index 27a8b325d64..dbfe2d13a5d 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/ZipFileExtractor.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/ZipFileExtractor.java @@ -17,7 +17,8 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; -import org.apache.commons.io.IOUtils; + +import net.sourceforge.pmd.util.IOUtil; /** * Extracts a zip file with preserving the unix file permissions. @@ -49,7 +50,7 @@ public static void extractZipFile(Path zipPath, Path tempDir) throws Exception { } else { try (InputStream data = zip.getInputStream(entry); OutputStream fileOut = new FileOutputStream(file);) { - IOUtils.copy(data, fileOut); + IOUtil.copy(data, fileOut); } if ((entry.getUnixMode() & OWNER_EXECUTABLE) == OWNER_EXECUTABLE) { file.setExecutable(true); From bef7eed0ec1778427e54c03f0d2ec27ba90b3ad4 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 11:39:22 +0200 Subject: [PATCH 31/54] [doc] Replace IOUtils with IOUtil --- .../pmd/docs/DeadLinksChecker.java | 5 ++- .../pmd/docs/GenerateRuleDocsCmd.java | 6 ++-- .../pmd/docs/RuleDocGenerator.java | 31 ++++++++++--------- .../sourceforge/pmd/docs/RuleSetUtils.java | 10 +++--- .../pmd/docs/MockedFileWriter.java | 5 ++- .../pmd/docs/RuleDocGeneratorTest.java | 12 +++---- .../pmd/docs/RuleSetResolverTest.java | 4 +-- .../pmd/docs/SidebarGeneratorTest.java | 4 +-- 8 files changed, 40 insertions(+), 37 deletions(-) diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DeadLinksChecker.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DeadLinksChecker.java index 750e7c934c8..9f651c36109 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DeadLinksChecker.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DeadLinksChecker.java @@ -37,8 +37,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.commons.io.IOUtils; - +import net.sourceforge.pmd.util.IOUtil; /** * Checks links to local pages for non-existing link-targets. @@ -298,7 +297,7 @@ private List listMdFiles(Path pagesDirectory) { private String fileToString(Path mdFile) { try (InputStream inputStream = Files.newInputStream(mdFile)) { - return IOUtils.toString(inputStream, StandardCharsets.UTF_8); + return IOUtil.readToString(inputStream, StandardCharsets.UTF_8); } catch (IOException ex) { throw new RuntimeException("error reading " + mdFile, ex); } diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java index caf1cb67a5b..d5b3002a6bc 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java @@ -10,16 +10,16 @@ import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; -import org.apache.commons.io.FilenameUtils; - import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetLoader; +import net.sourceforge.pmd.util.IOUtil; public final class GenerateRuleDocsCmd { private GenerateRuleDocsCmd() { @@ -51,7 +51,7 @@ public static List findAdditionalRulesets(Path basePath) { try { List additionalRulesets = new ArrayList<>(); Pattern rulesetPattern = Pattern.compile("^.+" + Pattern.quote(File.separator) + "pmd-\\w+" - + Pattern.quote(FilenameUtils.normalize("/src/main/resources/rulesets/")) + + Pattern.quote(IOUtil.normalizePath(File.separator + Paths.get("src", "main", "resources", "rulesets").toString() + File.separator)) + "\\w+" + Pattern.quote(File.separator) + "\\w+.xml$"); Files.walkFileTree(basePath, new SimpleFileVisitor() { @Override diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index 891580ad846..a1e23965cd4 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -30,8 +30,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.SystemUtils; import org.apache.commons.text.StringEscapeUtils; import net.sourceforge.pmd.Rule; @@ -43,6 +43,7 @@ import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.properties.MultiValuePropertyDescriptor; import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.util.IOUtil; public class RuleDocGenerator { private static final Logger LOG = Logger.getLogger(RuleDocGenerator.class.getName()); @@ -131,7 +132,7 @@ private List resolveAdditionalRulesets(List additionalRulesets) } private Path getAbsoluteOutputPath(String filename) { - return root.resolve(FilenameUtils.normalize(filename)); + return root.resolve(IOUtil.normalizePath(filename)); } private Map> sortRulesets(List rulesets) { @@ -608,17 +609,13 @@ private void determineRuleClassSourceFiles(Map> sortedRu // is replaced by a correct path. for (List rulesets : sortedRulesets.values()) { for (RuleSet ruleset : rulesets) { - // Note: the path is normalized to unix path separators, so that the editme link - // uses forward slashes - String rulesetFilename = FilenameUtils.normalize(StringUtils.chomp(ruleset.getFileName()), true); + String rulesetFilename = normalizeForwardSlashes(StringUtils.chomp(ruleset.getFileName())); allRulesets.put(ruleset.getFileName(), rulesetFilename); for (Rule rule : ruleset.getRules()) { String ruleClass = rule.getRuleClass(); String relativeSourceFilename = ruleClass.replaceAll("\\.", Matcher.quoteReplacement(File.separator)) + ".java"; - // Note: the path is normalized to unix path separators, so that the editme link - // uses forward slashes - allRules.put(ruleClass, FilenameUtils.normalize(relativeSourceFilename, true)); + allRules.put(ruleClass, normalizeForwardSlashes(relativeSourceFilename)); } } } @@ -640,9 +637,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { } if (foundRuleClass != null) { Path foundPath = root.relativize(file); - // Note: the path is normalized to unix path separators, so that the editme link - // uses forward slashes - allRules.put(foundRuleClass, FilenameUtils.normalize(foundPath.toString(), true)); + allRules.put(foundRuleClass, normalizeForwardSlashes(foundPath.toString())); } String foundRuleset = null; @@ -654,9 +649,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { } if (foundRuleset != null) { Path foundPath = root.relativize(file); - // Note: the path is normalized to unix path separators, so that the editme link - // uses forward slashes - allRulesets.put(foundRuleset, FilenameUtils.normalize(foundPath.toString(), true)); + allRulesets.put(foundRuleset, normalizeForwardSlashes(foundPath.toString())); } } return FileVisitResult.CONTINUE; @@ -666,4 +659,14 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { throw new RuntimeException(e); } } + + private static String normalizeForwardSlashes(String path) { + String normalized = IOUtil.normalizePath(path); + if (SystemUtils.IS_OS_WINDOWS) { + // Note: windows path separators are changed to forward slashes, + // so that the editme link works + normalized = normalized.replaceAll(Pattern.quote(File.separator), "/"); + } + return normalized; + } } diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleSetUtils.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleSetUtils.java index f928fe1de63..a7afef7b5b0 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleSetUtils.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleSetUtils.java @@ -4,12 +4,14 @@ package net.sourceforge.pmd.docs; -import org.apache.commons.io.FilenameUtils; +import java.io.File; + import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.lang.rule.RuleReference; +import net.sourceforge.pmd.util.IOUtil; public final class RuleSetUtils { @@ -28,7 +30,7 @@ public static String getRuleSetFilename(RuleSet ruleset) { } public static String getRuleSetFilename(String rulesetFileName) { - return FilenameUtils.getBaseName(StringUtils.chomp(rulesetFileName)); + return IOUtil.getFilenameBase(StringUtils.chomp(rulesetFileName)); } /** @@ -50,8 +52,8 @@ public static boolean isRuleSetDeprecated(RuleSet ruleset) { } public static String getRuleSetClasspath(RuleSet ruleset) { - final String RESOURCES_PATH = "/resources/"; - String filename = FilenameUtils.normalize(StringUtils.chomp(ruleset.getFileName()), true); + final String RESOURCES_PATH = File.separator + "resources" + File.separator; + String filename = IOUtil.normalizePath(StringUtils.chomp(ruleset.getFileName())); int startIndex = filename.lastIndexOf(RESOURCES_PATH); if (startIndex > -1) { return filename.substring(startIndex + RESOURCES_PATH.length()); diff --git a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/MockedFileWriter.java b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/MockedFileWriter.java index dc5ee7e626c..3f90cbe4cb0 100644 --- a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/MockedFileWriter.java +++ b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/MockedFileWriter.java @@ -10,7 +10,6 @@ import java.util.List; import java.util.regex.Pattern; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.PMD; @@ -49,7 +48,7 @@ public void reset() { } public static String normalizeLineSeparators(String s) { - return s.replaceAll(Pattern.quote(IOUtils.LINE_SEPARATOR_WINDOWS), IOUtils.LINE_SEPARATOR_UNIX) - .replaceAll(Pattern.quote(IOUtils.LINE_SEPARATOR_UNIX), PMD.EOL); + return s.replaceAll(Pattern.quote("\r\n"), "\n") + .replaceAll(Pattern.quote("\n"), PMD.EOL); } } diff --git a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java index dc96ec33a59..f994834900b 100644 --- a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java +++ b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java @@ -11,11 +11,10 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -24,6 +23,7 @@ import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetLoader; import net.sourceforge.pmd.docs.MockedFileWriter.FileEntry; +import net.sourceforge.pmd.util.IOUtil; public class RuleDocGeneratorTest { @@ -52,7 +52,7 @@ public void setup() throws IOException { private static String loadResource(String name) throws IOException { return MockedFileWriter.normalizeLineSeparators( - IOUtils.toString(RuleDocGeneratorTest.class.getResourceAsStream(name), StandardCharsets.UTF_8)); + IOUtil.readToString(RuleDocGeneratorTest.class.getResourceAsStream(name), StandardCharsets.UTF_8)); } @Test @@ -69,15 +69,15 @@ public void testSingleRuleset() throws IOException { assertEquals(3, writer.getData().size()); FileEntry languageIndex = writer.getData().get(0); - assertTrue(FilenameUtils.normalize(languageIndex.getFilename(), true).endsWith("docs/pages/pmd/rules/java.md")); + assertTrue(IOUtil.normalizePath(languageIndex.getFilename()).endsWith(Paths.get("docs", "pages", "pmd", "rules", "java.md").toString())); assertEquals(loadResource("/expected/java.md"), languageIndex.getContent()); FileEntry ruleSetIndex = writer.getData().get(1); - assertTrue(FilenameUtils.normalize(ruleSetIndex.getFilename(), true).endsWith("docs/pages/pmd/rules/java/sample.md")); + assertTrue(IOUtil.normalizePath(ruleSetIndex.getFilename()).endsWith(Paths.get("docs", "pages", "pmd", "rules", "java", "sample.md").toString())); assertEquals(loadResource("/expected/sample.md"), ruleSetIndex.getContent()); FileEntry sidebar = writer.getData().get(2); - assertTrue(FilenameUtils.normalize(sidebar.getFilename(), true).endsWith("docs/_data/sidebars/pmd_sidebar.yml")); + assertTrue(IOUtil.normalizePath(sidebar.getFilename()).endsWith(Paths.get("docs", "_data", "sidebars", "pmd_sidebar.yml").toString())); assertEquals(loadResource("/expected/pmd_sidebar.yml"), sidebar.getContent()); } } diff --git a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleSetResolverTest.java b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleSetResolverTest.java index c2c082c44f2..3d85da8daa9 100644 --- a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleSetResolverTest.java +++ b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleSetResolverTest.java @@ -12,19 +12,19 @@ import java.util.Iterator; import java.util.List; -import org.apache.commons.io.FilenameUtils; import org.junit.Test; import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSetNotFoundException; import net.sourceforge.pmd.RulesetsFactoryUtils; +import net.sourceforge.pmd.util.IOUtil; public class RuleSetResolverTest { private static List excludedRulesets = new ArrayList<>(); static { - excludedRulesets.add(FilenameUtils.normalize("pmd-test/src/main/resources/rulesets/dummy/basic.xml")); + excludedRulesets.add(IOUtil.normalizePath("pmd-test/src/main/resources/rulesets/dummy/basic.xml")); } @Test diff --git a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/SidebarGeneratorTest.java b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/SidebarGeneratorTest.java index ea01604b3ce..190a607bb1a 100644 --- a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/SidebarGeneratorTest.java +++ b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/SidebarGeneratorTest.java @@ -15,7 +15,6 @@ import java.util.List; import java.util.Map; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.SystemUtils; import org.junit.Before; import org.junit.Test; @@ -28,6 +27,7 @@ import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.util.IOUtil; public class SidebarGeneratorTest { private MockedFileWriter writer = new MockedFileWriter(); @@ -56,7 +56,7 @@ public void testSidebar() throws IOException { String yaml = new Yaml(options).dump(result); String expected = MockedFileWriter.normalizeLineSeparators( - IOUtils.toString(SidebarGeneratorTest.class.getResourceAsStream("sidebar.yml"), StandardCharsets.UTF_8)); + IOUtil.readToString(SidebarGeneratorTest.class.getResourceAsStream("sidebar.yml"), StandardCharsets.UTF_8)); assertEquals(expected, yaml); } } From cfacfbbff2e56041275fcf9b742e09bfc4b7b411 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 15:18:03 +0200 Subject: [PATCH 32/54] Fix tests under Windows --- .../java/net/sourceforge/pmd/RuleSetTest.java | 3 +- .../net/sourceforge/pmd/util/IOUtilTest.java | 70 +++++++++++++------ 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java index 14f4db10726..3ff5ba5fb79 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java @@ -12,6 +12,7 @@ import static org.junit.Assert.assertTrue; import java.io.File; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -581,7 +582,7 @@ public void apply(List nodes, RuleContext ctx) { assertEquals("Wrong error message", "RuntimeException: Test exception while applying rule", processingError.getMsg()); assertTrue("Should be a RuntimeException", processingError.getError() instanceof RuntimeException); assertEquals("Wrong filename in processing error", - "net.sourceforge.pmd.RuleSetTest/ruleExceptionShouldBeReported.java", + Paths.get("net.sourceforge.pmd.RuleSetTest", "ruleExceptionShouldBeReported.java").toString(), IOUtil.normalizePath(processingError.getFile())); assertEquals("There should be a violation", 1, context.getReport().size()); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java index 35e772cfc9a..7b21230fb6a 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java @@ -80,30 +80,56 @@ public void testSkipFully2() throws IOException { @Test public void testNormalizePath() { - Assert.assertEquals("ab/cd.txt", IOUtil.normalizePath("ab/ef/../cd.txt")); - Assert.assertEquals("/a.txt", IOUtil.normalizePath("/x/../../a.txt")); - Assert.assertEquals("/foo", IOUtil.normalizePath("//../foo")); - Assert.assertEquals("/foo", IOUtil.normalizePath("/foo//")); - Assert.assertEquals("/foo", IOUtil.normalizePath("/foo/./")); - Assert.assertEquals("/bar", IOUtil.normalizePath("/foo/../bar")); - Assert.assertEquals("/bar", IOUtil.normalizePath("/foo/../bar/")); - Assert.assertEquals("/baz", IOUtil.normalizePath("/foo/../bar/../baz")); - Assert.assertEquals("/foo/bar", IOUtil.normalizePath("//foo//./bar")); - Assert.assertEquals("foo", IOUtil.normalizePath("foo/bar/..")); - Assert.assertEquals("bar", IOUtil.normalizePath("foo/../bar")); - Assert.assertEquals("/foo/baz", IOUtil.normalizePath("//foo/bar/../baz")); - Assert.assertEquals("~/bar", IOUtil.normalizePath("~/foo/../bar/")); - Assert.assertEquals("/", IOUtil.normalizePath("/../")); - Assert.assertEquals("bar", IOUtil.normalizePath("~/../bar")); - Assert.assertEquals("bar", IOUtil.normalizePath("./bar")); - - Assert.assertNull(IOUtil.normalizePath("../foo")); - Assert.assertNull(IOUtil.normalizePath("foo/../../bar")); - Assert.assertNull(IOUtil.normalizePath(".")); - - Assert.assertTrue(IOUtil.equalsNormalizedPaths("foo/../bar", "bar/./")); + if (SystemUtils.IS_OS_UNIX) { + Assert.assertEquals("ab/cd.txt", IOUtil.normalizePath("ab/ef/../cd.txt")); + Assert.assertEquals("/a.txt", IOUtil.normalizePath("/x/../../a.txt")); + Assert.assertEquals("/foo", IOUtil.normalizePath("//../foo")); + Assert.assertEquals("/foo", IOUtil.normalizePath("/foo//")); + Assert.assertEquals("/foo", IOUtil.normalizePath("/foo/./")); + Assert.assertEquals("/bar", IOUtil.normalizePath("/foo/../bar")); + Assert.assertEquals("/bar", IOUtil.normalizePath("/foo/../bar/")); + Assert.assertEquals("/baz", IOUtil.normalizePath("/foo/../bar/../baz")); + Assert.assertEquals("/foo/bar", IOUtil.normalizePath("//foo//./bar")); + Assert.assertEquals("foo", IOUtil.normalizePath("foo/bar/..")); + Assert.assertEquals("bar", IOUtil.normalizePath("foo/../bar")); + Assert.assertEquals("/foo/baz", IOUtil.normalizePath("//foo/bar/../baz")); + Assert.assertEquals("~/bar", IOUtil.normalizePath("~/foo/../bar/")); + Assert.assertEquals("/", IOUtil.normalizePath("/../")); + Assert.assertEquals("bar", IOUtil.normalizePath("~/../bar")); + Assert.assertEquals("bar", IOUtil.normalizePath("./bar")); + + Assert.assertNull(IOUtil.normalizePath("../foo")); + Assert.assertNull(IOUtil.normalizePath("foo/../../bar")); + Assert.assertNull(IOUtil.normalizePath(".")); + + Assert.assertTrue(IOUtil.equalsNormalizedPaths("foo/../bar", "bar/./")); + } if (SystemUtils.IS_OS_WINDOWS) { + Assert.assertEquals("ab\\cd.txt", IOUtil.normalizePath("ab\\ef\\..\\cd.txt")); + Assert.assertEquals("\\a.txt", IOUtil.normalizePath("\\x\\..\\..\\a.txt")); + Assert.assertEquals("\\foo", IOUtil.normalizePath("\\foo\\\\")); + Assert.assertEquals("\\foo", IOUtil.normalizePath("\\foo\\.\\")); + Assert.assertEquals("\\bar", IOUtil.normalizePath("\\foo\\..\\bar")); + Assert.assertEquals("\\bar", IOUtil.normalizePath("\\foo\\..\\bar\\")); + Assert.assertEquals("\\baz", IOUtil.normalizePath("\\foo\\..\\bar\\..\\baz")); + Assert.assertEquals("\\\\foo\\bar\\", IOUtil.normalizePath("\\\\foo\\bar")); + Assert.assertEquals("\\\\foo\\bar\\baz", IOUtil.normalizePath("\\\\foo\\bar\\..\\baz")); + Assert.assertEquals("foo", IOUtil.normalizePath("foo\\bar\\..")); + Assert.assertEquals("bar", IOUtil.normalizePath("foo\\..\\bar")); + Assert.assertEquals("\\foo\\baz", IOUtil.normalizePath("\\foo\\bar\\..\\baz")); + Assert.assertEquals("\\", IOUtil.normalizePath("\\..\\")); + Assert.assertEquals("bar", IOUtil.normalizePath(".\\bar")); + + Assert.assertNull(IOUtil.normalizePath("\\\\..\\foo")); + Assert.assertNull(IOUtil.normalizePath("..\\foo")); + Assert.assertNull(IOUtil.normalizePath("foo\\..\\..\\bar")); + Assert.assertNull(IOUtil.normalizePath(".")); + Assert.assertNull(IOUtil.normalizePath("\\\\foo\\\\.\\bar")); + Assert.assertNull(IOUtil.normalizePath("\\\\foo\\.\\bar")); + + Assert.assertTrue(IOUtil.equalsNormalizedPaths("foo\\..\\bar", "bar\\.\\")); + Assert.assertEquals("C:\\bar", IOUtil.normalizePath("C:\\..\\bar")); Assert.assertEquals("ab\\cd.txt", IOUtil.normalizePath("ab\\ef\\..\\cd.txt")); Assert.assertEquals("C:\\ab\\cd.txt", IOUtil.normalizePath("C:\\ab\\ef\\..\\.\\cd.txt")); From 1c9096809dd2cda3922c7cd0c98d0bed92c09202 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 15:25:24 +0200 Subject: [PATCH 33/54] [doc] Update release notes (#3942) --- docs/pages/release_notes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index c31a705241f..7ac4b956c87 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -15,7 +15,8 @@ This is a {{ site.pmd.release_type }} release. ### New and noteworthy ### Fixed Issues - +* core + * [#3942](https://github.com/pmd/pmd/issues/3942): \[core] common-io path traversal vulnerability (CVE-2021-29425) * javascript * [#3948](https://github.com/pmd/pmd/issues/3948): \[js] Invalid operator error for method property in object literal From 8addd05369b60e5169a7db304fc92fff6c08c018 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 16:43:17 +0200 Subject: [PATCH 34/54] Fix tests under Windows --- .../pmd/docs/RuleDocGenerator.java | 19 ++++--------------- .../sourceforge/pmd/docs/RuleSetUtils.java | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index a1e23965cd4..0cc2923649a 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -31,7 +31,6 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.SystemUtils; import org.apache.commons.text.StringEscapeUtils; import net.sourceforge.pmd.Rule; @@ -609,13 +608,13 @@ private void determineRuleClassSourceFiles(Map> sortedRu // is replaced by a correct path. for (List rulesets : sortedRulesets.values()) { for (RuleSet ruleset : rulesets) { - String rulesetFilename = normalizeForwardSlashes(StringUtils.chomp(ruleset.getFileName())); + String rulesetFilename = RuleSetUtils.normalizeForwardSlashes(StringUtils.chomp(ruleset.getFileName())); allRulesets.put(ruleset.getFileName(), rulesetFilename); for (Rule rule : ruleset.getRules()) { String ruleClass = rule.getRuleClass(); String relativeSourceFilename = ruleClass.replaceAll("\\.", Matcher.quoteReplacement(File.separator)) + ".java"; - allRules.put(ruleClass, normalizeForwardSlashes(relativeSourceFilename)); + allRules.put(ruleClass, RuleSetUtils.normalizeForwardSlashes(relativeSourceFilename)); } } } @@ -637,7 +636,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { } if (foundRuleClass != null) { Path foundPath = root.relativize(file); - allRules.put(foundRuleClass, normalizeForwardSlashes(foundPath.toString())); + allRules.put(foundRuleClass, RuleSetUtils.normalizeForwardSlashes(foundPath.toString())); } String foundRuleset = null; @@ -649,7 +648,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { } if (foundRuleset != null) { Path foundPath = root.relativize(file); - allRulesets.put(foundRuleset, normalizeForwardSlashes(foundPath.toString())); + allRulesets.put(foundRuleset, RuleSetUtils.normalizeForwardSlashes(foundPath.toString())); } } return FileVisitResult.CONTINUE; @@ -659,14 +658,4 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { throw new RuntimeException(e); } } - - private static String normalizeForwardSlashes(String path) { - String normalized = IOUtil.normalizePath(path); - if (SystemUtils.IS_OS_WINDOWS) { - // Note: windows path separators are changed to forward slashes, - // so that the editme link works - normalized = normalized.replaceAll(Pattern.quote(File.separator), "/"); - } - return normalized; - } } diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleSetUtils.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleSetUtils.java index a7afef7b5b0..0ab05a68bca 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleSetUtils.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleSetUtils.java @@ -5,8 +5,10 @@ package net.sourceforge.pmd.docs; import java.io.File; +import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.SystemUtils; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleSet; @@ -52,8 +54,8 @@ public static boolean isRuleSetDeprecated(RuleSet ruleset) { } public static String getRuleSetClasspath(RuleSet ruleset) { - final String RESOURCES_PATH = File.separator + "resources" + File.separator; - String filename = IOUtil.normalizePath(StringUtils.chomp(ruleset.getFileName())); + final String RESOURCES_PATH = "/resources/"; + String filename = normalizeForwardSlashes(StringUtils.chomp(ruleset.getFileName())); int startIndex = filename.lastIndexOf(RESOURCES_PATH); if (startIndex > -1) { return filename.substring(startIndex + RESOURCES_PATH.length()); @@ -62,6 +64,16 @@ public static String getRuleSetClasspath(RuleSet ruleset) { } } + public static String normalizeForwardSlashes(String path) { + String normalized = IOUtil.normalizePath(path); + if (SystemUtils.IS_OS_WINDOWS) { + // Note: windows path separators are changed to forward slashes, + // so that the editme link works + normalized = normalized.replaceAll(Pattern.quote(File.separator), "/"); + } + return normalized; + } + /** * Recursively resolves rule references until the last reference. * The last reference is returned. From a9219b7967ed1fbbc3029625c40823fd49e84a5f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 17:13:16 +0200 Subject: [PATCH 35/54] [core] Fix bug in IOUtil.fromReader --- .../java/net/sourceforge/pmd/util/IOUtil.java | 2 +- .../java/net/sourceforge/pmd/util/IOUtilTest.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java index 791561bc7ac..881bc7efa22 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java @@ -325,7 +325,7 @@ public int read() throws IOException { charBuffer.flip(); encoder.encode(charBuffer, byteBuffer, eof); byteBuffer.flip(); - charBuffer.flip(); + charBuffer.compact(); } if (byteBuffer.hasRemaining()) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java index 7b21230fb6a..b577de8f114 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/util/IOUtilTest.java @@ -193,6 +193,21 @@ public void testInputStreamFromReader() throws IOException { } } + @Test + public void testInputStreamFromReader2() throws IOException { + int size = 8192 + 8192 + 10; + char[] data = new char[size]; + for (int i = 0; i < size; i++) { + data[i] = 'A'; + } + data[8192] = 'ä'; // block size border - in UTF-8 these are two bytes. Decoding needs to take the bytes + // from previous block and new block + try (InputStream inputStream = IOUtil.fromReader(new StringReader(new String(data)))) { + byte[] bytes = IOUtil.toByteArray(inputStream); + Assert.assertEquals(new String(data), new String(bytes, StandardCharsets.UTF_8)); + } + } + @Test public void testCopyStream() throws IOException { int size = 8192 + 8192 + 10; From e8935523ed265eff42469c711ad3bd2ff7dd16fe Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 13 May 2022 20:07:18 +0200 Subject: [PATCH 36/54] Update pmd-java/src/main/resources/category/java/performance.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Clément Fournier --- pmd-java/src/main/resources/category/java/performance.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/performance.xml b/pmd-java/src/main/resources/category/java/performance.xml index 8411f356033..b93f71eb4a5 100644 --- a/pmd-java/src/main/resources/category/java/performance.xml +++ b/pmd-java/src/main/resources/category/java/performance.xml @@ -971,9 +971,9 @@ You must use `new ArrayList<>(Arrays.asList(...))` if that is inconvenient for y [count(Statement//StatementExpression)=1] [@Foreach = true() or ForInit//VariableInitializer//Literal[@IntLiteral= true() and @Image='0']] (: skip primitive types :) - [@Foreach = true() and Expression[not(pmd-java:typeIs('boolean[]') or pmd-java:typeIs('char[]') or pmd-java:typeIs('byte[]') or pmd-java:typeIs('short[]') or pmd-java:typeIs('int[]') or pmd-java:typeIs('long[]') or pmd-java:typeIs('float[]') or pmd-java:typeIs('double[]'))] + [@Foreach = true() and Expression[pmd-java:typeIs('java.lang.Object[]')] or Expression/RelationalExpression/PrimaryExpression/PrimaryPrefix/Name[substring-before(@Image, '.length') = - ancestor::MethodDeclaration[1]//VariableDeclaratorId[not(pmd-java:typeIs('boolean[]') or pmd-java:typeIs('char[]') or pmd-java:typeIs('byte[]') or pmd-java:typeIs('short[]') or pmd-java:typeIs('int[]') or pmd-java:typeIs('long[]') or pmd-java:typeIs('float[]') or pmd-java:typeIs('double[]'))] + ancestor::MethodDeclaration[1]//VariableDeclaratorId[pmd-java:typeIs('java.lang.Object[]')] /@Name] ] //StatementExpression From 7921e836b193df860a1866ac0415497711c4e531 Mon Sep 17 00:00:00 2001 From: Maikel Steneker Date: Mon, 16 May 2022 16:42:01 +0200 Subject: [PATCH 37/54] Add option to ignore C# attributes (annotations) --- .../java/net/sourceforge/pmd/cpd/GUI.java | 11 +- .../net/sourceforge/pmd/cpd/CsTokenizer.java | 45 +++- .../sourceforge/pmd/cpd/CsTokenizerTest.java | 21 +- .../pmd/lang/cs/cpd/testdata/attributes.cs | 42 ++++ .../pmd/lang/cs/cpd/testdata/attributes.txt | 229 ++++++++++++++++++ .../cs/cpd/testdata/attributes_ignored.txt | 109 +++++++++ 6 files changed, 441 insertions(+), 16 deletions(-) create mode 100644 pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes.cs create mode 100644 pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes.txt create mode 100644 pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes_ignored.txt diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/GUI.java b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/GUI.java index 540e9727595..b970880aa0e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cpd/GUI.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cpd/GUI.java @@ -147,7 +147,16 @@ public String[] extensions() { @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 diff --git a/pmd-cs/src/main/java/net/sourceforge/pmd/cpd/CsTokenizer.java b/pmd-cs/src/main/java/net/sourceforge/pmd/cpd/CsTokenizer.java index a48212290a9..7a8cfd09f67 100644 --- a/pmd-cs/src/main/java/net/sourceforge/pmd/cpd/CsTokenizer.java +++ b/pmd-cs/src/main/java/net/sourceforge/pmd/cpd/CsTokenizer.java @@ -20,6 +20,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. @@ -27,19 +28,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 @@ -50,7 +48,7 @@ protected AntlrTokenManager getLexerForSource(final SourceCode sourceCode) { @Override protected AntlrTokenFilter getTokenFilter(final AntlrTokenManager tokenManager) { - return new CsTokenFilter(tokenManager, ignoreUsings, ignoreLiteralSequences); + return new CsTokenFilter(tokenManager, ignoreUsings, ignoreLiteralSequences, ignoreAttributes); } /** @@ -69,15 +67,18 @@ private enum UsingState { 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 @@ -90,6 +91,7 @@ protected void analyzeTokens(final AntlrToken currentToken, final Iterable remainingTokens) { @@ -166,6 +168,25 @@ private void skipNewLines(final AntlrToken currentToken) { 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 remainingTokens) { if (ignoreLiteralSequences) { final int type = currentToken.getKind(); @@ -221,7 +242,7 @@ public boolean isDiscardingLiterals() { @Override protected boolean isLanguageSpecificDiscarding() { - return discardingUsings || discardingNL || isDiscardingLiterals() || discardCurrent; + return discardingUsings || discardingNL || isDiscardingAttribute || isDiscardingLiterals() || discardCurrent; } } } diff --git a/pmd-cs/src/test/java/net/sourceforge/pmd/cpd/CsTokenizerTest.java b/pmd-cs/src/test/java/net/sourceforge/pmd/cpd/CsTokenizerTest.java index 63c9cd5aeed..d05797d7260 100644 --- a/pmd-cs/src/test/java/net/sourceforge/pmd/cpd/CsTokenizerTest.java +++ b/pmd-cs/src/test/java/net/sourceforge/pmd/cpd/CsTokenizerTest.java @@ -105,18 +105,33 @@ public void testCSharp7And8Additions() { 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 skipAttributes() { + return properties(false, false, true); } - private Properties properties(boolean ignoreUsings, boolean ignoreLiteralSequences) { + 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; } } diff --git a/pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes.cs b/pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes.cs new file mode 100644 index 00000000000..811e1513624 --- /dev/null +++ b/pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes.cs @@ -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; } \ No newline at end of file diff --git a/pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes.txt b/pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes.txt new file mode 100644 index 00000000000..403064af389 --- /dev/null +++ b/pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes.txt @@ -0,0 +1,229 @@ + [Image] or [Truncated image[ Bcol Ecol +L1 + [\[] 1 1 + [Serializable] 2 13 + [\]] 14 14 +L2 + [public] 1 6 + [class] 8 12 + [SampleClass] 14 24 +L3 + [{] 1 1 +L5 + [}] 1 1 +L7 + [\[] 1 1 + [System] 2 7 + [.] 8 8 + [Runtime] 9 15 + [.] 16 16 + [InteropServices] 17 31 + [.] 32 32 + [DllImport] 33 41 + [(] 42 42 + ["user32.dll"] 43 54 + [)] 55 55 + [\]] 56 56 +L8 + [extern] 1 6 + [static] 8 13 + [void] 15 18 + [SampleMethod] 20 31 + [(] 32 32 + [)] 33 33 + [;] 34 34 +L10 + [void] 1 4 + [MethodA] 6 12 + [(] 13 13 + [\[] 14 14 + [In] 15 16 + [\]] 17 17 + [\[] 18 18 + [Out] 19 21 + [\]] 22 22 + [ref] 24 26 + [double] 28 33 + [x] 35 35 + [)] 36 36 + [{] 38 38 + [}] 40 40 +L11 + [void] 1 4 + [MethodB] 6 12 + [(] 13 13 + [\[] 14 14 + [Out] 15 17 + [\]] 18 18 + [\[] 19 19 + [In] 20 21 + [\]] 22 22 + [ref] 24 26 + [double] 28 33 + [x] 35 35 + [)] 36 36 + [{] 38 38 + [}] 40 40 +L12 + [void] 1 4 + [MethodC] 6 12 + [(] 13 13 + [\[] 14 14 + [In] 15 16 + [,] 17 17 + [Out] 19 21 + [\]] 22 22 + [ref] 24 26 + [double] 28 33 + [x] 35 35 + [)] 36 36 + [{] 38 38 + [}] 40 40 +L14 + [\[] 1 1 + [Conditional] 2 12 + [(] 13 13 + ["DEBUG"] 14 20 + [)] 21 21 + [,] 22 22 + [Conditional] 24 34 + [(] 35 35 + ["TEST1"] 36 42 + [)] 43 43 + [\]] 44 44 +L15 + [void] 1 4 + [TraceMethod] 6 16 + [(] 17 17 + [)] 18 18 +L16 + [{] 1 1 +L18 + [}] 1 1 +L20 + [\[] 1 1 + [DllImport] 2 10 + [(] 11 11 + ["user32.dll"] 12 23 + [)] 24 24 + [\]] 25 25 +L21 + [\[] 1 1 + [DllImport] 2 10 + [(] 11 11 + ["user32.dll"] 12 23 + [,] 24 24 + [SetLastError] 26 37 + [=] 38 38 + [false] 39 43 + [,] 44 44 + [ExactSpelling] 46 58 + [=] 59 59 + [false] 60 64 + [)] 65 65 + [\]] 66 66 +L22 + [\[] 1 1 + [DllImport] 2 10 + [(] 11 11 + ["user32.dll"] 12 23 + [,] 24 24 + [ExactSpelling] 26 38 + [=] 39 39 + [false] 40 44 + [,] 45 45 + [SetLastError] 47 58 + [=] 59 59 + [false] 60 64 + [)] 65 65 + [\]] 66 66 +L24 + [using] 1 5 + [System] 7 12 + [;] 13 13 +L25 + [using] 1 5 + [System] 7 12 + [.] 13 13 + [Reflection] 14 23 + [;] 24 24 +L26 + [\[] 1 1 + [assembly] 2 9 + [:] 10 10 + [AssemblyTitleAttribute] 12 33 + [(] 34 34 + ["Production assembly 4"] 35 57 + [)] 58 58 + [\]] 59 59 +L27 + [\[] 1 1 + [module] 2 7 + [:] 8 8 + [CLSCompliant] 10 21 + [(] 22 22 + [true] 23 26 + [)] 27 27 + [\]] 28 28 +L30 + [\[] 1 1 + [ValidatedContract] 2 18 + [\]] 19 19 +L31 + [int] 1 3 + [Method1] 5 11 + [(] 12 12 + [)] 13 13 + [{] 15 15 + [return] 17 22 + [0] 24 24 + [;] 25 25 + [}] 27 27 +L34 + [\[] 1 1 + [method] 2 7 + [:] 8 8 + [ValidatedContract] 10 26 + [\]] 27 27 +L35 + [int] 1 3 + [Method2] 5 11 + [(] 12 12 + [)] 13 13 + [{] 15 15 + [return] 17 22 + [0] 24 24 + [;] 25 25 + [}] 27 27 +L38 + [int] 1 3 + [Method3] 5 11 + [(] 12 12 + [\[] 13 13 + [ValidatedContract] 14 30 + [\]] 31 31 + [string] 33 38 + [contract] 40 47 + [)] 48 48 + [{] 50 50 + [return] 52 57 + [0] 59 59 + [;] 60 60 + [}] 62 62 +L41 + [\[] 1 1 + [return] 2 7 + [:] 8 8 + [ValidatedContract] 10 26 + [\]] 27 27 +L42 + [int] 1 3 + [Method4] 5 11 + [(] 12 12 + [)] 13 13 + [{] 15 15 + [return] 17 22 + [0] 24 24 + [;] 25 25 + [}] 27 27 +EOF diff --git a/pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes_ignored.txt b/pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes_ignored.txt new file mode 100644 index 00000000000..0796c4384c7 --- /dev/null +++ b/pmd-cs/src/test/resources/net/sourceforge/pmd/lang/cs/cpd/testdata/attributes_ignored.txt @@ -0,0 +1,109 @@ + [Image] or [Truncated image[ Bcol Ecol +L2 + [public] 1 6 + [class] 8 12 + [SampleClass] 14 24 +L3 + [{] 1 1 +L5 + [}] 1 1 +L8 + [extern] 1 6 + [static] 8 13 + [void] 15 18 + [SampleMethod] 20 31 + [(] 32 32 + [)] 33 33 + [;] 34 34 +L10 + [void] 1 4 + [MethodA] 6 12 + [(] 13 13 + [ref] 24 26 + [double] 28 33 + [x] 35 35 + [)] 36 36 + [{] 38 38 + [}] 40 40 +L11 + [void] 1 4 + [MethodB] 6 12 + [(] 13 13 + [ref] 24 26 + [double] 28 33 + [x] 35 35 + [)] 36 36 + [{] 38 38 + [}] 40 40 +L12 + [void] 1 4 + [MethodC] 6 12 + [(] 13 13 + [ref] 24 26 + [double] 28 33 + [x] 35 35 + [)] 36 36 + [{] 38 38 + [}] 40 40 +L15 + [void] 1 4 + [TraceMethod] 6 16 + [(] 17 17 + [)] 18 18 +L16 + [{] 1 1 +L18 + [}] 1 1 +L24 + [using] 1 5 + [System] 7 12 + [;] 13 13 +L25 + [using] 1 5 + [System] 7 12 + [.] 13 13 + [Reflection] 14 23 + [;] 24 24 +L31 + [int] 1 3 + [Method1] 5 11 + [(] 12 12 + [)] 13 13 + [{] 15 15 + [return] 17 22 + [0] 24 24 + [;] 25 25 + [}] 27 27 +L35 + [int] 1 3 + [Method2] 5 11 + [(] 12 12 + [)] 13 13 + [{] 15 15 + [return] 17 22 + [0] 24 24 + [;] 25 25 + [}] 27 27 +L38 + [int] 1 3 + [Method3] 5 11 + [(] 12 12 + [string] 33 38 + [contract] 40 47 + [)] 48 48 + [{] 50 50 + [return] 52 57 + [0] 59 59 + [;] 60 60 + [}] 62 62 +L42 + [int] 1 3 + [Method4] 5 11 + [(] 12 12 + [)] 13 13 + [{] 15 15 + [return] 17 22 + [0] 24 24 + [;] 25 25 + [}] 27 27 +EOF From c53a64c688d0d6d9811df886ea0bb24ece64f6e0 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 May 2022 08:51:52 +0200 Subject: [PATCH 38/54] Update pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Clément Fournier --- .../src/main/java/net/sourceforge/pmd/util/IOUtil.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java index 881bc7efa22..ebe98f9dbed 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/IOUtil.java @@ -180,6 +180,13 @@ public static void ensureClosed(List toClose, } } + + // The following methods are taken from Apache Commons IO. + // The dependency was removed from PMD 6 because it had a security issue, + // and upgrading was not possible without upgrading to Java 8. + // See https://github.com/pmd/pmd/pull/3968 + // TODO PMD 7: consider bringing back commons-io and cleaning this class up. + public static void closeQuietly(Closeable closeable) { try { closeable.close(); From 2daa3381b4f646ca0b862998d12bb598ebe62a34 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 May 2022 09:06:29 +0200 Subject: [PATCH 39/54] [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 c31a705241f..b8bd840b4c8 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 40/54] [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 2b645e9839f..b6f6bfb6875 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 41/54] 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 dcac68bf606..f5d880797e7 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 3f6b6213cf5..b2efb5841c0 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 91328436a01f33decb822f0bff10a0ef9ca19d31 Mon Sep 17 00:00:00 2001 From: Maikel Steneker Date: Fri, 20 May 2022 09:35:53 +0200 Subject: [PATCH 42/54] Clarify documentation on `--ignore-annotations` CLI option --- docs/pages/pmd/userdocs/cpd/cpd.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/pmd/userdocs/cpd/cpd.md b/docs/pages/pmd/userdocs/cpd/cpd.md index dc4577e41dc..d909eb4f2f0 100644 --- a/docs/pages/pmd/userdocs/cpd/cpd.md +++ b/docs/pages/pmd/userdocs/cpd/cpd.md @@ -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)" From 77369804755c5e328c4082744c755391c58fc0c4 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 20 May 2022 09:51:45 +0200 Subject: [PATCH 43/54] 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 702e6605d4e..4568a28d35d 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 ElementNode(DocumentNode document, } 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 Value atomize() { @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 44/54] [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 1a6272dab80..404b1102518 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 void selectTextNode() { 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 45/54] [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 404b1102518..1c9f81b1caa 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 void selectTextNode() { @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 46/54] [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 c31a705241f..d5657169260 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 From 01c48e1ca7686fec520a687d30b8bb2e74b09ce6 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 26 May 2022 10:26:03 +0200 Subject: [PATCH 47/54] [doc] Update release notes (#3960) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Clément Fournier --- docs/pages/release_notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index fb3f28f11f5..2c7c511a924 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -26,7 +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. +Please use theses new forms instead of using comma-separated lists as argument to these options. ### Fixed Issues From aef06d4b3a763d3a41f56111c2055554a464003b Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 26 May 2022 10:28:18 +0200 Subject: [PATCH 48/54] Add @vibhory2j as a contributor --- .all-contributorsrc | 9 ++++ docs/pages/pmd/projectdocs/credits.md | 59 ++++++++++++++------------- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index f5d880797e7..240441581c2 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -6648,6 +6648,15 @@ "contributions": [ "code" ] + }, + { + "login": "vibhory2j", + "name": "Vibhor Goyal", + "avatar_url": "https://avatars.githubusercontent.com/u/15845016?v=4", + "profile": "https://github.com/vibhory2j", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index b2efb5841c0..e243b5c134d 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -685,262 +685,263 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Valentin Brandl

🐛
Valeria

🐛
Vasily Anisimov

🐛 +
Vibhor Goyal

🐛
Vickenty Fesunov

🐛 -
Victor Noël

🐛 +
Victor Noël

🐛
Vincent Galloy

💻
Vincent HUYNH

🐛
Vincent Maurin

🐛
Vincent Privat

🐛
Vishhwas

🐛
Vitaly

🐛 -
Vitaly Polonetsky

🐛 +
Vitaly Polonetsky

🐛
Vojtech Polivka

🐛
Vsevolod Zholobov

🐛
Vyom Yadav

💻
Wang Shidong

🐛
Waqas Ahmed

🐛
Wayne J. Earl

🐛 -
Wchenghui

🐛 +
Wchenghui

🐛
Will Winder

🐛
William Brockhus

💻 🐛
Wilson Kurniawan

🐛
Wim Deblauwe

🐛
Woongsik Choi

🐛
XenoAmess

💻 🐛 -
Yang

💻 +
Yang

💻
YaroslavTER

🐛
Young Chan

💻 🐛
YuJin Kim

🐛
Yuri Dolzhenko

🐛
Yurii Dubinka

🐛
Zoltan Farkas

🐛 -
Zustin

🐛 +
Zustin

🐛
aaronhurst-google

🐛
alexmodis

🐛
andreoss

🐛
andrey81inmd

💻 🐛
anicoara

🐛
arunprasathav

🐛 -
asiercamara

🐛 +
asiercamara

🐛
astillich-igniti

💻
avesolovksyy

🐛
avishvat

🐛
avivmu

🐛
axelbarfod1

🐛
b-3-n

🐛 -
balbhadra9

🐛 +
balbhadra9

🐛
base23de

🐛
bergander

🐛
berkam

💻 🐛
breizh31

🐛
caesarkim

🐛
carolyujing

🐛 -
cesares-basilico

🐛 +
cesares-basilico

🐛
chrite

🐛
cobratbq

🐛
coladict

🐛
cosmoJFH

🐛
cristalp

🐛
crunsk

🐛 -
cwholmes

🐛 +
cwholmes

🐛
cyberjj999

🐛
cyw3

🐛
d1ss0nanz

🐛
danbrycefairsailcom

🐛
dariansanity

🐛
darrenmiliband

🐛 -
davidburstrom

🐛 +
davidburstrom

🐛
dbirkman-paloalto

🐛
deepak-patra

🐛
dependabot[bot]

💻 🐛
dinesh150

🐛
diziaq

🐛
dreaminpast123

🐛 -
duanyanan

🐛 +
duanyanan

🐛
dutt-sanjay

🐛
dylanleung

🐛
dzeigler

🐛
ekkirala

🐛
emersonmoura

🐛
fairy

🐛 -
filiprafalowicz

💻 +
filiprafalowicz

💻
foxmason

🐛
frankegabor

🐛
frankl

🐛
freafrea

🐛
fsapatin

🐛
gracia19

🐛 -
guo fei

🐛 +
guo fei

🐛
gurmsc5

🐛
gwilymatgearset

💻 🐛
haigsn

🐛
hemanshu070

🐛
henrik242

🐛
hongpuwu

🐛 -
hvbtup

💻 🐛 +
hvbtup

💻 🐛
igniti GmbH

🐛
ilovezfs

🐛
itaigilo

🐛
jakivey32

🐛
jbennett2091

🐛
jcamerin

🐛 -
jkeener1

🐛 +
jkeener1

🐛
jmetertea

🐛
johnra2

💻
josemanuelrolon

💻 🐛
kabroxiko

💻 🐛
karwer

🐛
kaulonline

🐛 -
kdaemonv

🐛 +
kdaemonv

🐛
kenji21

💻 🐛
kfranic

🐛
khalidkh

🐛
krzyk

🐛
lasselindqvist

🐛
lihuaib

🐛 -
lonelyma1021

🐛 +
lonelyma1021

🐛
lpeddy

🐛
lujiefsi

💻
lukelukes

💻
lyriccoder

🐛
marcelmore

🐛
matchbox

🐛 -
matthiaskraaz

🐛 +
matthiaskraaz

🐛
meandonlyme

🐛
mikesive

🐛
milossesic

🐛
mriddell95

🐛
mrlzh

🐛
msloan

🐛 -
mucharlaravalika

🐛 +
mucharlaravalika

🐛
mvenneman

🐛
nareshl119

🐛
nicolas-harraudeau-sonarsource

🐛
noerremark

🐛
novsirion

🐛
oggboy

🐛 -
oinume

🐛 +
oinume

🐛
orimarko

💻 🐛
pallavi agarwal

🐛
parksungrin

🐛
patpatpat123

🐛
patriksevallius

🐛
pbrajesh1

🐛 -
phoenix384

🐛 +
phoenix384

🐛
piotrszymanski-sc

💻
plan3d

🐛
poojasix

🐛
prabhushrikant

🐛
pujitha8783

🐛
r-r-a-j

🐛 -
raghujayjunk

🐛 +
raghujayjunk

🐛
rajeshveera

🐛
rajeswarreddy88

🐛
recdevs

🐛
reudismam

💻 🐛
rijkt

🐛
rillig-tk

🐛 -
rmohan20

💻 🐛 +
rmohan20

💻 🐛
rxmicro

🐛
ryan-gustafson

💻 🐛
sabi0

🐛
scais

🐛
sebbASF

🐛
sergeygorbaty

💻 -
shilko2013

🐛 +
shilko2013

🐛
simeonKondr

🐛
snajberk

🐛
sniperrifle2004

🐛
snuyanzin

🐛 💻
sratz

🐛
stonio

🐛 -
sturton

💻 🐛 +
sturton

💻 🐛
sudharmohan

🐛
suruchidawar

🐛
svenfinitiv

🐛
tashiscool

🐛
test-git-hook

🐛
testation21

💻 🐛 -
thanosa

🐛 +
thanosa

🐛
tiandiyixian

🐛
tobwoerk

🐛
tprouvot

🐛
trentchilders

🐛
triandicAnt

🐛
trishul14

🐛 -
tsui

🐛 +
tsui

🐛
winhkey

🐛
witherspore

🐛
wjljack

🐛
wuchiuwong

🐛
xingsong

🐛
xioayuge

🐛 -
xnYi9wRezm

💻 🐛 +
xnYi9wRezm

💻 🐛
xuanuy

🐛
xyf0921

🐛
yalechen-cyw3

🐛
yasuharu-sato

🐛
zenglian

🐛
zgrzyt93

💻 🐛 -
zh3ng

🐛 +
zh3ng

🐛
zt_soft

🐛
ztt79

🐛
zzzzfeng

🐛 From aae06c45ac2d2e07804dc7ab79fb26c55a51c091 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 26 May 2022 10:36:55 +0200 Subject: [PATCH 49/54] [doc] Update release notes (#3946, #3423, #2605, #2604, #2752) --- docs/pages/release_notes.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 2c7c511a924..e4855f3b663 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -32,12 +32,19 @@ Please use theses new forms instead of using comma-separated lists as argument t * cli * [#1445](https://github.com/pmd/pmd/issues/1445): \[core] Allow CLI to take globs as parameters +* 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-design * [#3874](https://github.com/pmd/pmd/issues/3874): \[java] ImmutableField reports fields annotated with @Autowired (Spring) and @Mock (Mockito) * javascript + * [#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 From d0873ff6fafa68a49910107426664eaf8caa8bfa Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 26 May 2022 10:57:08 +0200 Subject: [PATCH 50/54] [doc] Update release notes (#3974) --- docs/pages/release_notes.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index e4855f3b663..44874a9097c 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -28,10 +28,18 @@ 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 * 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 @@ -57,6 +65,7 @@ A new set of methods have been added, which use lists and do not rely on comma s ### External Contributions * [#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 %} From 11cda428f1092530408896d5d587ac20509ab152 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 26 May 2022 11:03:01 +0200 Subject: [PATCH 51/54] [doc] Update release notes (#3954, #3961) --- docs/pages/release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 44874a9097c..eca65c0e36a 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -46,6 +46,8 @@ the CPD GUI. See [#3974](https://github.com/pmd/pmd/pull/3974) for details. * [#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 @@ -64,6 +66,7 @@ A new set of methods have been added, which use lists and do not rely on comma s ### 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) From 95d6619a6b28a0bbf42c762aacb02f4e8a3c683e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 26 May 2022 11:03:20 +0200 Subject: [PATCH 52/54] Add @Ramel0921 as a contributor --- .all-contributorsrc | 9 +++ docs/pages/pmd/projectdocs/credits.md | 85 ++++++++++++++------------- 2 files changed, 52 insertions(+), 42 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 240441581c2..7a4c53bfd6d 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -6657,6 +6657,15 @@ "contributions": [ "bug" ] + }, + { + "login": "Ramel0921", + "name": "Ramel0921", + "avatar_url": "https://avatars.githubusercontent.com/u/104978096?v=4", + "profile": "https://github.com/Ramel0921", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index e243b5c134d..71ac04355be 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -569,378 +569,379 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
RaheemShaik999

🐛
RajeshR

💻 🐛
Ramachandra Mohan

🐛 -
Raquel Pau

🐛 +
Ramel0921

🐛 +
Raquel Pau

🐛
Ravikiran Janardhana

🐛
Reda Benhemmouche

🐛
Renato Oliveira

💻 🐛
Rich DiCroce

🐛
Riot R1cket

🐛
Rishabh Jain

🐛 -
RishabhDeep Singh

🐛 +
RishabhDeep Singh

🐛
Robbie Martinus

💻 🐛
Robert Henry

🐛
Robert Painsi

🐛
Robert Russell

🐛
Robert Sösemann

💻 📖 📢 🐛
Robert Whitebit

🐛 -
Robin Richtsfeld

🐛 +
Robin Richtsfeld

🐛
Robin Stocker

💻 🐛
Robin Wils

🐛
RochusOest

🐛
Rodolfo Noviski

🐛
Rodrigo Casara

🐛
Rodrigo Fernandes

🐛 -
Roman Salvador

💻 🐛 +
Roman Salvador

💻 🐛
Ronald Blaschke

🐛
Róbert Papp

🐛
Saikat Sengupta

🐛
Saksham Handu

🐛
Saladoc

🐛
Salesforce Bob Lightning

🐛 -
Sam Carlberg

🐛 +
Sam Carlberg

🐛
Satoshi Kubo

🐛
Scott Kennedy

🐛
Scott Wells

🐛 💻
Scrsloota

💻
Sebastian Bögl

🐛
Sebastian Schuberth

🐛 -
Sebastian Schwarz

🐛 +
Sebastian Schwarz

🐛
Sergey Gorbaty

🐛
Sergey Kozlov

🐛
Sergey Yanzin

💻 🐛
Seth Wilcox

💻
Shubham

💻 🐛
Simon Xiao

🐛 -
Srinivasan Venkatachalam

🐛 +
Srinivasan Venkatachalam

🐛
Stanislav Gromov

🐛
Stanislav Myachenkov

💻
Stefan Birkner

🐛
Stefan Bohn

🐛
Stefan Endrullis

🐛
Stefan Klöss-Schuster

🐛 -
Stefan Wolf

🐛 +
Stefan Wolf

🐛
Stephan H. Wissel

🐛
Stephen

🐛
Stephen Friedrich

🐛
Steve Babula

💻
Stexxe

🐛
Stian Lågstad

🐛 -
StuartClayton5

🐛 +
StuartClayton5

🐛
Supun Arunoda

🐛
Suren Abrahamyan

🐛
SwatiBGupta1110

🐛
SyedThoufich

🐛
Szymon Sasin

🐛
T-chuangxin

🐛 -
TERAI Atsuhiro

🐛 +
TERAI Atsuhiro

🐛
TIOBE Software

💻 🐛
Taylor Smock

🐛
Techeira Damián

💻 🐛
Ted Husted

🐛
TehBakker

🐛
The Gitter Badger

🐛 -
Theodoor

🐛 +
Theodoor

🐛
Thiago Henrique Hüpner

🐛
Thibault Meyer

🐛
Thomas Güttler

🐛
Thomas Jones-Low

🐛
Thomas Smith

💻 🐛
ThrawnCA

🐛 -
Thunderforge

💻 🐛 +
Thunderforge

💻 🐛
Tim van der Lippe

🐛
Tobias Weimer

💻 🐛
Tom Daly

🐛
Tomer Figenblat

🐛
Tomi De Lucca

💻 🐛
Torsten Kleiber

🐛 -
TrackerSB

🐛 +
TrackerSB

🐛
Ullrich Hafner

🐛
Utku Cuhadaroglu

💻 🐛
Valentin Brandl

🐛
Valeria

🐛
Vasily Anisimov

🐛
Vibhor Goyal

🐛 -
Vickenty Fesunov

🐛 +
Vickenty Fesunov

🐛
Victor Noël

🐛
Vincent Galloy

💻
Vincent HUYNH

🐛
Vincent Maurin

🐛
Vincent Privat

🐛
Vishhwas

🐛 -
Vitaly

🐛 +
Vitaly

🐛
Vitaly Polonetsky

🐛
Vojtech Polivka

🐛
Vsevolod Zholobov

🐛
Vyom Yadav

💻
Wang Shidong

🐛
Waqas Ahmed

🐛 -
Wayne J. Earl

🐛 +
Wayne J. Earl

🐛
Wchenghui

🐛
Will Winder

🐛
William Brockhus

💻 🐛
Wilson Kurniawan

🐛
Wim Deblauwe

🐛
Woongsik Choi

🐛 -
XenoAmess

💻 🐛 +
XenoAmess

💻 🐛
Yang

💻
YaroslavTER

🐛
Young Chan

💻 🐛
YuJin Kim

🐛
Yuri Dolzhenko

🐛
Yurii Dubinka

🐛 -
Zoltan Farkas

🐛 +
Zoltan Farkas

🐛
Zustin

🐛
aaronhurst-google

🐛
alexmodis

🐛
andreoss

🐛
andrey81inmd

💻 🐛
anicoara

🐛 -
arunprasathav

🐛 +
arunprasathav

🐛
asiercamara

🐛
astillich-igniti

💻
avesolovksyy

🐛
avishvat

🐛
avivmu

🐛
axelbarfod1

🐛 -
b-3-n

🐛 +
b-3-n

🐛
balbhadra9

🐛
base23de

🐛
bergander

🐛
berkam

💻 🐛
breizh31

🐛
caesarkim

🐛 -
carolyujing

🐛 +
carolyujing

🐛
cesares-basilico

🐛
chrite

🐛
cobratbq

🐛
coladict

🐛
cosmoJFH

🐛
cristalp

🐛 -
crunsk

🐛 +
crunsk

🐛
cwholmes

🐛
cyberjj999

🐛
cyw3

🐛
d1ss0nanz

🐛
danbrycefairsailcom

🐛
dariansanity

🐛 -
darrenmiliband

🐛 +
darrenmiliband

🐛
davidburstrom

🐛
dbirkman-paloalto

🐛
deepak-patra

🐛
dependabot[bot]

💻 🐛
dinesh150

🐛
diziaq

🐛 -
dreaminpast123

🐛 +
dreaminpast123

🐛
duanyanan

🐛
dutt-sanjay

🐛
dylanleung

🐛
dzeigler

🐛
ekkirala

🐛
emersonmoura

🐛 -
fairy

🐛 +
fairy

🐛
filiprafalowicz

💻
foxmason

🐛
frankegabor

🐛
frankl

🐛
freafrea

🐛
fsapatin

🐛 -
gracia19

🐛 +
gracia19

🐛
guo fei

🐛
gurmsc5

🐛
gwilymatgearset

💻 🐛
haigsn

🐛
hemanshu070

🐛
henrik242

🐛 -
hongpuwu

🐛 +
hongpuwu

🐛
hvbtup

💻 🐛
igniti GmbH

🐛
ilovezfs

🐛
itaigilo

🐛
jakivey32

🐛
jbennett2091

🐛 -
jcamerin

🐛 +
jcamerin

🐛
jkeener1

🐛
jmetertea

🐛
johnra2

💻
josemanuelrolon

💻 🐛
kabroxiko

💻 🐛
karwer

🐛 -
kaulonline

🐛 +
kaulonline

🐛
kdaemonv

🐛
kenji21

💻 🐛
kfranic

🐛
khalidkh

🐛
krzyk

🐛
lasselindqvist

🐛 -
lihuaib

🐛 +
lihuaib

🐛
lonelyma1021

🐛
lpeddy

🐛
lujiefsi

💻
lukelukes

💻
lyriccoder

🐛
marcelmore

🐛 -
matchbox

🐛 +
matchbox

🐛
matthiaskraaz

🐛
meandonlyme

🐛
mikesive

🐛
milossesic

🐛
mriddell95

🐛
mrlzh

🐛 -
msloan

🐛 +
msloan

🐛
mucharlaravalika

🐛
mvenneman

🐛
nareshl119

🐛
nicolas-harraudeau-sonarsource

🐛
noerremark

🐛
novsirion

🐛 -
oggboy

🐛 +
oggboy

🐛
oinume

🐛
orimarko

💻 🐛
pallavi agarwal

🐛
parksungrin

🐛
patpatpat123

🐛
patriksevallius

🐛 -
pbrajesh1

🐛 +
pbrajesh1

🐛
phoenix384

🐛
piotrszymanski-sc

💻
plan3d

🐛
poojasix

🐛
prabhushrikant

🐛
pujitha8783

🐛 -
r-r-a-j

🐛 +
r-r-a-j

🐛
raghujayjunk

🐛
rajeshveera

🐛
rajeswarreddy88

🐛
recdevs

🐛
reudismam

💻 🐛
rijkt

🐛 -
rillig-tk

🐛 +
rillig-tk

🐛
rmohan20

💻 🐛
rxmicro

🐛
ryan-gustafson

💻 🐛
sabi0

🐛
scais

🐛
sebbASF

🐛 -
sergeygorbaty

💻 +
sergeygorbaty

💻
shilko2013

🐛
simeonKondr

🐛
snajberk

🐛
sniperrifle2004

🐛
snuyanzin

🐛 💻
sratz

🐛 -
stonio

🐛 +
stonio

🐛
sturton

💻 🐛
sudharmohan

🐛
suruchidawar

🐛
svenfinitiv

🐛
tashiscool

🐛
test-git-hook

🐛 -
testation21

💻 🐛 +
testation21

💻 🐛
thanosa

🐛
tiandiyixian

🐛
tobwoerk

🐛
tprouvot

🐛
trentchilders

🐛
triandicAnt

🐛 -
trishul14

🐛 +
trishul14

🐛
tsui

🐛
winhkey

🐛
witherspore

🐛
wjljack

🐛
wuchiuwong

🐛
xingsong

🐛 -
xioayuge

🐛 +
xioayuge

🐛
xnYi9wRezm

💻 🐛
xuanuy

🐛
xyf0921

🐛
yalechen-cyw3

🐛
yasuharu-sato

🐛
zenglian

🐛 -
zgrzyt93

💻 🐛 +
zgrzyt93

💻 🐛
zh3ng

🐛
zt_soft

🐛
ztt79

🐛 From 6f234bab8dc174925d66423021ca44c2f455d679 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 26 May 2022 11:03:34 +0200 Subject: [PATCH 53/54] Add @flyhard as a contributor --- .all-contributorsrc | 9 +++ docs/pages/pmd/projectdocs/credits.md | 93 ++++++++++++++------------- 2 files changed, 57 insertions(+), 45 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 7a4c53bfd6d..6efd00a7798 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -6666,6 +6666,15 @@ "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, diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index 71ac04355be..b00de0e0d8b 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -540,413 +540,416 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Pedro Nuno Santos

🐛
Pedro Rijo

🐛
Pelisse Romain

💻 📖 🐛 +
Per Abich

💻
Pete Davids

🐛
Peter Bruin

🐛 -
Peter Chittum

💻 🐛 +
Peter Chittum

💻 🐛
Peter Cudmore

🐛
Peter Kasson

🐛
Peter Kofler

🐛
Pham Hai Trung

🐛
Philip Graf

💻 🐛
Philip Hachey

🐛 -
Philippe Ozil

🐛 +
Philippe Ozil

🐛
Phinehas Artemix

🐛
Phokham Nonava

🐛
Piotr Szymański

🐛
Piotrek Żygieło

💻 🐛
Pranay Jaiswal

🐛
Prasad Kamath

🐛 -
Prasanna

🐛 +
Prasanna

🐛
Presh-AR

🐛
Puneet1726

🐛
Rafael Cortês

🐛
RaheemShaik999

🐛
RajeshR

💻 🐛
Ramachandra Mohan

🐛 -
Ramel0921

🐛 +
Ramel0921

🐛
Raquel Pau

🐛
Ravikiran Janardhana

🐛
Reda Benhemmouche

🐛
Renato Oliveira

💻 🐛
Rich DiCroce

🐛
Riot R1cket

🐛 -
Rishabh Jain

🐛 +
Rishabh Jain

🐛
RishabhDeep Singh

🐛
Robbie Martinus

💻 🐛
Robert Henry

🐛
Robert Painsi

🐛
Robert Russell

🐛
Robert Sösemann

💻 📖 📢 🐛 -
Robert Whitebit

🐛 +
Robert Whitebit

🐛
Robin Richtsfeld

🐛
Robin Stocker

💻 🐛
Robin Wils

🐛
RochusOest

🐛
Rodolfo Noviski

🐛
Rodrigo Casara

🐛 -
Rodrigo Fernandes

🐛 +
Rodrigo Fernandes

🐛
Roman Salvador

💻 🐛
Ronald Blaschke

🐛
Róbert Papp

🐛
Saikat Sengupta

🐛
Saksham Handu

🐛
Saladoc

🐛 -
Salesforce Bob Lightning

🐛 +
Salesforce Bob Lightning

🐛
Sam Carlberg

🐛
Satoshi Kubo

🐛
Scott Kennedy

🐛
Scott Wells

🐛 💻
Scrsloota

💻
Sebastian Bögl

🐛 -
Sebastian Schuberth

🐛 +
Sebastian Schuberth

🐛
Sebastian Schwarz

🐛
Sergey Gorbaty

🐛
Sergey Kozlov

🐛
Sergey Yanzin

💻 🐛
Seth Wilcox

💻
Shubham

💻 🐛 -
Simon Xiao

🐛 +
Simon Xiao

🐛
Srinivasan Venkatachalam

🐛
Stanislav Gromov

🐛
Stanislav Myachenkov

💻
Stefan Birkner

🐛
Stefan Bohn

🐛
Stefan Endrullis

🐛 -
Stefan Klöss-Schuster

🐛 +
Stefan Klöss-Schuster

🐛
Stefan Wolf

🐛
Stephan H. Wissel

🐛
Stephen

🐛
Stephen Friedrich

🐛
Steve Babula

💻
Stexxe

🐛 -
Stian Lågstad

🐛 +
Stian Lågstad

🐛
StuartClayton5

🐛
Supun Arunoda

🐛
Suren Abrahamyan

🐛
SwatiBGupta1110

🐛
SyedThoufich

🐛
Szymon Sasin

🐛 -
T-chuangxin

🐛 +
T-chuangxin

🐛
TERAI Atsuhiro

🐛
TIOBE Software

💻 🐛
Taylor Smock

🐛
Techeira Damián

💻 🐛
Ted Husted

🐛
TehBakker

🐛 -
The Gitter Badger

🐛 +
The Gitter Badger

🐛
Theodoor

🐛
Thiago Henrique Hüpner

🐛
Thibault Meyer

🐛
Thomas Güttler

🐛
Thomas Jones-Low

🐛
Thomas Smith

💻 🐛 -
ThrawnCA

🐛 +
ThrawnCA

🐛
Thunderforge

💻 🐛
Tim van der Lippe

🐛
Tobias Weimer

💻 🐛
Tom Daly

🐛
Tomer Figenblat

🐛
Tomi De Lucca

💻 🐛 -
Torsten Kleiber

🐛 +
Torsten Kleiber

🐛
TrackerSB

🐛
Ullrich Hafner

🐛
Utku Cuhadaroglu

💻 🐛
Valentin Brandl

🐛
Valeria

🐛
Vasily Anisimov

🐛 -
Vibhor Goyal

🐛 +
Vibhor Goyal

🐛
Vickenty Fesunov

🐛
Victor Noël

🐛
Vincent Galloy

💻
Vincent HUYNH

🐛
Vincent Maurin

🐛
Vincent Privat

🐛 -
Vishhwas

🐛 +
Vishhwas

🐛
Vitaly

🐛
Vitaly Polonetsky

🐛
Vojtech Polivka

🐛
Vsevolod Zholobov

🐛
Vyom Yadav

💻
Wang Shidong

🐛 -
Waqas Ahmed

🐛 +
Waqas Ahmed

🐛
Wayne J. Earl

🐛
Wchenghui

🐛
Will Winder

🐛
William Brockhus

💻 🐛
Wilson Kurniawan

🐛
Wim Deblauwe

🐛 -
Woongsik Choi

🐛 +
Woongsik Choi

🐛
XenoAmess

💻 🐛
Yang

💻
YaroslavTER

🐛
Young Chan

💻 🐛
YuJin Kim

🐛
Yuri Dolzhenko

🐛 -
Yurii Dubinka

🐛 +
Yurii Dubinka

🐛
Zoltan Farkas

🐛
Zustin

🐛
aaronhurst-google

🐛
alexmodis

🐛
andreoss

🐛
andrey81inmd

💻 🐛 -
anicoara

🐛 +
anicoara

🐛
arunprasathav

🐛
asiercamara

🐛
astillich-igniti

💻
avesolovksyy

🐛
avishvat

🐛
avivmu

🐛 -
axelbarfod1

🐛 +
axelbarfod1

🐛
b-3-n

🐛
balbhadra9

🐛
base23de

🐛
bergander

🐛
berkam

💻 🐛
breizh31

🐛 -
caesarkim

🐛 +
caesarkim

🐛
carolyujing

🐛
cesares-basilico

🐛
chrite

🐛
cobratbq

🐛
coladict

🐛
cosmoJFH

🐛 -
cristalp

🐛 +
cristalp

🐛
crunsk

🐛
cwholmes

🐛
cyberjj999

🐛
cyw3

🐛
d1ss0nanz

🐛
danbrycefairsailcom

🐛 -
dariansanity

🐛 +
dariansanity

🐛
darrenmiliband

🐛
davidburstrom

🐛
dbirkman-paloalto

🐛
deepak-patra

🐛
dependabot[bot]

💻 🐛
dinesh150

🐛 -
diziaq

🐛 +
diziaq

🐛
dreaminpast123

🐛
duanyanan

🐛
dutt-sanjay

🐛
dylanleung

🐛
dzeigler

🐛
ekkirala

🐛 -
emersonmoura

🐛 +
emersonmoura

🐛
fairy

🐛
filiprafalowicz

💻
foxmason

🐛
frankegabor

🐛
frankl

🐛
freafrea

🐛 -
fsapatin

🐛 +
fsapatin

🐛
gracia19

🐛
guo fei

🐛
gurmsc5

🐛
gwilymatgearset

💻 🐛
haigsn

🐛
hemanshu070

🐛 -
henrik242

🐛 +
henrik242

🐛
hongpuwu

🐛
hvbtup

💻 🐛
igniti GmbH

🐛
ilovezfs

🐛
itaigilo

🐛
jakivey32

🐛 -
jbennett2091

🐛 +
jbennett2091

🐛
jcamerin

🐛
jkeener1

🐛
jmetertea

🐛
johnra2

💻
josemanuelrolon

💻 🐛
kabroxiko

💻 🐛 -
karwer

🐛 +
karwer

🐛
kaulonline

🐛
kdaemonv

🐛
kenji21

💻 🐛
kfranic

🐛
khalidkh

🐛
krzyk

🐛 -
lasselindqvist

🐛 +
lasselindqvist

🐛
lihuaib

🐛
lonelyma1021

🐛
lpeddy

🐛
lujiefsi

💻
lukelukes

💻
lyriccoder

🐛 -
marcelmore

🐛 +
marcelmore

🐛
matchbox

🐛
matthiaskraaz

🐛
meandonlyme

🐛
mikesive

🐛
milossesic

🐛
mriddell95

🐛 -
mrlzh

🐛 +
mrlzh

🐛
msloan

🐛
mucharlaravalika

🐛
mvenneman

🐛
nareshl119

🐛
nicolas-harraudeau-sonarsource

🐛
noerremark

🐛 -
novsirion

🐛 +
novsirion

🐛
oggboy

🐛
oinume

🐛
orimarko

💻 🐛
pallavi agarwal

🐛
parksungrin

🐛
patpatpat123

🐛 -
patriksevallius

🐛 +
patriksevallius

🐛
pbrajesh1

🐛
phoenix384

🐛
piotrszymanski-sc

💻
plan3d

🐛
poojasix

🐛
prabhushrikant

🐛 -
pujitha8783

🐛 +
pujitha8783

🐛
r-r-a-j

🐛
raghujayjunk

🐛
rajeshveera

🐛
rajeswarreddy88

🐛
recdevs

🐛
reudismam

💻 🐛 -
rijkt

🐛 +
rijkt

🐛
rillig-tk

🐛
rmohan20

💻 🐛
rxmicro

🐛
ryan-gustafson

💻 🐛
sabi0

🐛
scais

🐛 -
sebbASF

🐛 +
sebbASF

🐛
sergeygorbaty

💻
shilko2013

🐛
simeonKondr

🐛
snajberk

🐛
sniperrifle2004

🐛
snuyanzin

🐛 💻 -
sratz

🐛 +
sratz

🐛
stonio

🐛
sturton

💻 🐛
sudharmohan

🐛
suruchidawar

🐛
svenfinitiv

🐛
tashiscool

🐛 -
test-git-hook

🐛 +
test-git-hook

🐛
testation21

💻 🐛
thanosa

🐛
tiandiyixian

🐛
tobwoerk

🐛
tprouvot

🐛
trentchilders

🐛 -
triandicAnt

🐛 +
triandicAnt

🐛
trishul14

🐛
tsui

🐛
winhkey

🐛
witherspore

🐛
wjljack

🐛
wuchiuwong

🐛 -
xingsong

🐛 +
xingsong

🐛
xioayuge

🐛
xnYi9wRezm

💻 🐛
xuanuy

🐛
xyf0921

🐛
yalechen-cyw3

🐛
yasuharu-sato

🐛 -
zenglian

🐛 +
zenglian

🐛
zgrzyt93

💻 🐛
zh3ng

🐛
zt_soft

🐛
ztt79

🐛
zzzzfeng

🐛
Árpád Magosányi

🐛 + +
任贵杰

🐛 From 108b670268cef4e850bcc77027cd6e3293d5d661 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 26 May 2022 15:27:14 +0200 Subject: [PATCH 54/54] Add @filipponova as a contributor --- .all-contributorsrc | 9 ++ docs/pages/pmd/projectdocs/credits.md | 157 +++++++++++++------------- 2 files changed, 88 insertions(+), 78 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 6efd00a7798..85095b18fe4 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -6675,6 +6675,15 @@ "contributions": [ "code" ] + }, + { + "login": "filipponova", + "name": "Filippo Nova", + "avatar_url": "https://avatars.githubusercontent.com/u/12506636?v=4", + "profile": "https://github.com/filipponova", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index b00de0e0d8b..48913f3d001 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -252,704 +252,705 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Felix Lampe

🐛
Filip Golonka

🐛
Filipe Esperandio

💻 🐛 +
Filippo Nova

🐛
Francesco la Torre

🐛
Francisco Duarte

🐛 -
Frieder Bluemle

🐛 +
Frieder Bluemle

🐛
Frits Jalvingh

💻 🐛
G. Bazior

🐛
Gabe Henkes

🐛
Genoud Magloire

🐛
Geoffrey555

🐛
Georg Romstorfer

🐛 -
Gio

🐛 +
Gio

🐛
Gol

🐛
Gonzalo Exequiel Ibars Ingman

💻 🐛
GooDer

🐛
Gregor Riegler

🐛
Grzegorz Olszewski

🐛
Gunther Schrijvers

💻 🐛 -
Gustavo Krieger

🐛 +
Gustavo Krieger

🐛
Guy Elsmore-Paddock

🐛
Görkem Mülayim

🐛
Hanzel Godinez

🐛
Harsh Kukreja

🐛
Heber

🐛
Henning Schmiedehausen

💻 🐛 -
Henning von Bargen

💻 +
Henning von Bargen

💻
Hervé Boutemy

🐛
Himanshu Pandey

🐛
Hokwang Lee

🐛
Hooperbloob

💻
Hung PHAN

🐛
IDoCodingStuffs

💻 🐛 -
Iccen Gan

🐛 +
Iccen Gan

🐛
Ignacio Mariano Tirabasso

🐛
Igor Melnichenko

🐛
Igor Moreno

🐛
Intelesis-MS

🐛
Iroha_

🐛
Ishan Srivastava

🐛 -
Ivano Guerini

🐛 +
Ivano Guerini

🐛
Ivar Andreas Bonsaksen

🐛
Ivo Šmíd

🐛
JJengility

🐛
Jake Hemmerle

🐛
James Harrison

🐛
Jan

🐛 -
Jan Aertgeerts

💻 🐛 +
Jan Aertgeerts

💻 🐛
Jan Brümmer

🐛
Jan Tříska

🐛
Jan-Lukas Else

🐛
Jason Qiu

💻 📖
Jason Williams

🐛
Jean-Paul Mayer

🐛 -
Jean-Simon Larochelle

🐛 +
Jean-Simon Larochelle

🐛
Jeff Bartolotta

💻 🐛
Jeff Hube

💻 🐛
Jeff Jensen

🐛
Jeff May

🐛
Jens Gerdes

🐛
Jeroen Borgers

🐛 -
Jerome Russ

🐛 +
Jerome Russ

🐛
JerritEic

💻 📖
Jiri Pejchal

🐛
Jithin Sunny

🐛
Jiří Škorpil

🐛
Joao Machado

🐛
Jochen Krauss

🐛 -
Johan Hammar

🐛 +
Johan Hammar

🐛
John Karp

🐛
John Zhang

🐛
John-Teng

💻 🐛
Jon Moroney

💻 🐛
Jonas Geiregat

🐛
Jonathan Wiesel

💻 🐛 -
Jordan

🐛 +
Jordan

🐛
Jordi Llach

🐛
Jorge Solórzano

🐛
JorneVL

🐛
Jose Palafox

🐛
Jose Stovall

🐛
Joseph

💻 -
Joseph Heenan

🐛 +
Joseph Heenan

🐛
Josh Feingold

💻 🐛
Josh Holthaus

🐛
Joshua S Arquilevich

🐛
João Ferreira

💻 🐛
João Pedro Schmitt

🐛
Juan Martín Sotuyo Dodero

💻 📖 🐛 🚧 -
Juan Pablo Civile

🐛 +
Juan Pablo Civile

🐛
Julian Voronetsky

🐛
Julien

🐛
Julius

🐛
JustPRV

🐛
Jörn Huxhorn

🐛
KThompso

🐛 -
Kai Amundsen

🐛 +
Kai Amundsen

🐛
Karel Vervaeke

🐛
Karl-Andero Mere

🐛
Karl-Philipp Richter

🐛
Karsten Silz

🐛
Kazuma Watanabe

🐛
Kev

🐛 -
Keve Müller

🐛 +
Keve Müller

🐛
Kevin Guerra

💻
Kevin Jones

🐛
Kevin Wayne

🐛
Kieran Black

🐛
Kirill Zubov

🐛
Kirk Clemens

💻 🐛 -
Klaus Hartl

🐛 +
Klaus Hartl

🐛
Koen Van Looveren

🐛
Kris Scheibe

💻 🐛
Kunal Thanki

🐛
LaLucid

💻
Larry Diamond

💻 🐛
Lars Knickrehm

🐛 -
Leo Gutierrez

🐛 +
Leo Gutierrez

🐛
LiGaOg

💻
Lintsi

🐛
Linus Fernandes

🐛
Lixon Lookose

🐛
Logesh

🐛
Lorenzo Gabriele

🐛 -
Loïc Ledoyen

🐛 +
Loïc Ledoyen

🐛
Lucas Silva

🐛
Lucas Soncini

💻 🐛
Lukasz Slonina

🐛
Lukebray

🐛
Lyor Goldstein

🐛
MCMicS

🐛 -
Macarse

🐛 +
Macarse

🐛
Machine account for PMD

💻
Maciek Siemczyk

🐛
Maikel Steneker

💻 🐛
Maksim Moiseikin

🐛
Manfred Koch

🐛
Manuel Moya Ferrer

💻 🐛 -
Manuel Ryan

🐛 +
Manuel Ryan

🐛
Marat Vyshegorodtsev

🐛
Marcel Härle

🐛
Marcello Fialho

🐛
Marcin Rataj

🐛
Mark Adamcin

🐛
Mark Hall

💻 🐛 -
Mark Kolich

🐛 +
Mark Kolich

🐛
Mark Pritchard

🐛
Markus Rathgeb

🐛
Marquis Wang

🐛
Martin Feldsztejn

🐛
Martin Lehmann

🐛
Martin Spamer

🐛 -
Martin Tarjányi

🐛 +
Martin Tarjányi

🐛
MatFl

🐛
Mateusz Stefanski

🐛
Mathieu Gouin

🐛
MatiasComercio

💻 🐛
Matt Benson

🐛
Matt De Poorter

🐛 -
Matt Harrah

🐛 +
Matt Harrah

🐛
Matt Nelson

🐛
Matthew Amos

🐛
Matthew Duggan

🐛
Matthew Hall

🐛
Matías Fraga

💻 🐛
Maxime Robert

💻 🐛 -
MetaBF

🐛 +
MetaBF

🐛
Michael

🐛
Michael Bell

🐛
Michael Bernstein

🐛
Michael Clay

🐛
Michael Dombrowski

🐛
Michael Hausegger

🐛 -
Michael Hoefer

🐛 +
Michael Hoefer

🐛
Michael Möbius

🐛
Michael N. Lipp

🐛
Michael Pellegrini

🐛
Michal Kordas

🐛
Michał Borek

🐛
Michał Kuliński

🐛 -
Miguel Núñez Díaz-Montes

🐛 +
Miguel Núñez Díaz-Montes

🐛
Mihai Ionut

🐛
Mirek Hankus

🐛
Mladjan Gadzic

🐛
MrAngry52

🐛
Muminur Choudhury

🐛
Mykhailo Palahuta

💻 🐛 -
Nagendra Kumar Singh

🐛 +
Nagendra Kumar Singh

🐛
Nahuel Barrios

🐛
Nathan Braun

🐛
Nathan Reynolds

🐛
Nathan Reynolds

🐛
Nathanaël

🐛
Naveen

💻 -
Nazdravi

🐛 +
Nazdravi

🐛
Neha-Dhonde

🐛
Nicholas Doyle

🐛
Nick Butcher

🐛
Nico Gallinal

🐛
Nicola Dal Maso

🐛
Nicolas Filotto

💻 -
Nikita Chursin

🐛 +
Nikita Chursin

🐛
Niklas Baudy

🐛
Nikolas Havrikov

🐛
Nilesh Virkar

🐛
Nimit Patel

🐛
Niranjan Harpale

🐛
Noah Sussman

🐛 -
Noah0120

🐛 +
Noah0120

🐛
Noam Tamim

🐛
Noel Grandin

🐛
Olaf Haalstra

🐛
Oleg Pavlenko

🐛
Oleksii Dykov

💻
Oliver Eikemeier

🐛 -
Olivier Parent

💻 🐛 +
Olivier Parent

💻 🐛
Ollie Abbey

💻 🐛
OverDrone

🐛
Ozan Gulle

💻 🐛
PUNEET JAIN

🐛
Parbati Bose

🐛
Paul Berg

🐛 -
Pavel Bludov

🐛 +
Pavel Bludov

🐛
Pavel Mička

🐛
Pedro Nuno Santos

🐛
Pedro Rijo

🐛
Pelisse Romain

💻 📖 🐛
Per Abich

💻
Pete Davids

🐛 -
Peter Bruin

🐛 +
Peter Bruin

🐛
Peter Chittum

💻 🐛
Peter Cudmore

🐛
Peter Kasson

🐛
Peter Kofler

🐛
Pham Hai Trung

🐛
Philip Graf

💻 🐛 -
Philip Hachey

🐛 +
Philip Hachey

🐛
Philippe Ozil

🐛
Phinehas Artemix

🐛
Phokham Nonava

🐛
Piotr Szymański

🐛
Piotrek Żygieło

💻 🐛
Pranay Jaiswal

🐛 -
Prasad Kamath

🐛 +
Prasad Kamath

🐛
Prasanna

🐛
Presh-AR

🐛
Puneet1726

🐛
Rafael Cortês

🐛
RaheemShaik999

🐛
RajeshR

💻 🐛 -
Ramachandra Mohan

🐛 +
Ramachandra Mohan

🐛
Ramel0921

🐛
Raquel Pau

🐛
Ravikiran Janardhana

🐛
Reda Benhemmouche

🐛
Renato Oliveira

💻 🐛
Rich DiCroce

🐛 -
Riot R1cket

🐛 +
Riot R1cket

🐛
Rishabh Jain

🐛
RishabhDeep Singh

🐛
Robbie Martinus

💻 🐛
Robert Henry

🐛
Robert Painsi

🐛
Robert Russell

🐛 -
Robert Sösemann

💻 📖 📢 🐛 +
Robert Sösemann

💻 📖 📢 🐛
Robert Whitebit

🐛
Robin Richtsfeld

🐛
Robin Stocker

💻 🐛
Robin Wils

🐛
RochusOest

🐛
Rodolfo Noviski

🐛 -
Rodrigo Casara

🐛 +
Rodrigo Casara

🐛
Rodrigo Fernandes

🐛
Roman Salvador

💻 🐛
Ronald Blaschke

🐛
Róbert Papp

🐛
Saikat Sengupta

🐛
Saksham Handu

🐛 -
Saladoc

🐛 +
Saladoc

🐛
Salesforce Bob Lightning

🐛
Sam Carlberg

🐛
Satoshi Kubo

🐛
Scott Kennedy

🐛
Scott Wells

🐛 💻
Scrsloota

💻 -
Sebastian Bögl

🐛 +
Sebastian Bögl

🐛
Sebastian Schuberth

🐛
Sebastian Schwarz

🐛
Sergey Gorbaty

🐛
Sergey Kozlov

🐛
Sergey Yanzin

💻 🐛
Seth Wilcox

💻 -
Shubham

💻 🐛 +
Shubham

💻 🐛
Simon Xiao

🐛
Srinivasan Venkatachalam

🐛
Stanislav Gromov

🐛
Stanislav Myachenkov

💻
Stefan Birkner

🐛
Stefan Bohn

🐛 -
Stefan Endrullis

🐛 +
Stefan Endrullis

🐛
Stefan Klöss-Schuster

🐛
Stefan Wolf

🐛
Stephan H. Wissel

🐛
Stephen

🐛
Stephen Friedrich

🐛
Steve Babula

💻 -
Stexxe

🐛 +
Stexxe

🐛
Stian Lågstad

🐛
StuartClayton5

🐛
Supun Arunoda

🐛
Suren Abrahamyan

🐛
SwatiBGupta1110

🐛
SyedThoufich

🐛 -
Szymon Sasin

🐛 +
Szymon Sasin

🐛
T-chuangxin

🐛
TERAI Atsuhiro

🐛
TIOBE Software

💻 🐛
Taylor Smock

🐛
Techeira Damián

💻 🐛
Ted Husted

🐛 -
TehBakker

🐛 +
TehBakker

🐛
The Gitter Badger

🐛
Theodoor

🐛
Thiago Henrique Hüpner

🐛
Thibault Meyer

🐛
Thomas Güttler

🐛
Thomas Jones-Low

🐛 -
Thomas Smith

💻 🐛 +
Thomas Smith

💻 🐛
ThrawnCA

🐛
Thunderforge

💻 🐛
Tim van der Lippe

🐛
Tobias Weimer

💻 🐛
Tom Daly

🐛
Tomer Figenblat

🐛 -
Tomi De Lucca

💻 🐛 +
Tomi De Lucca

💻 🐛
Torsten Kleiber

🐛
TrackerSB

🐛
Ullrich Hafner

🐛
Utku Cuhadaroglu

💻 🐛
Valentin Brandl

🐛
Valeria

🐛 -
Vasily Anisimov

🐛 +
Vasily Anisimov

🐛
Vibhor Goyal

🐛
Vickenty Fesunov

🐛
Victor Noël

🐛
Vincent Galloy

💻
Vincent HUYNH

🐛
Vincent Maurin

🐛 -
Vincent Privat

🐛 +
Vincent Privat

🐛
Vishhwas

🐛
Vitaly

🐛
Vitaly Polonetsky

🐛
Vojtech Polivka

🐛
Vsevolod Zholobov

🐛
Vyom Yadav

💻 -
Wang Shidong

🐛 +
Wang Shidong

🐛
Waqas Ahmed

🐛
Wayne J. Earl

🐛
Wchenghui

🐛
Will Winder

🐛
William Brockhus

💻 🐛
Wilson Kurniawan

🐛 -
Wim Deblauwe

🐛 +
Wim Deblauwe

🐛
Woongsik Choi

🐛
XenoAmess

💻 🐛
Yang

💻
YaroslavTER

🐛
Young Chan

💻 🐛
YuJin Kim

🐛 -
Yuri Dolzhenko

🐛 +
Yuri Dolzhenko

🐛
Yurii Dubinka

🐛
Zoltan Farkas

🐛
Zustin

🐛
aaronhurst-google

🐛
alexmodis

🐛
andreoss

🐛 -
andrey81inmd

💻 🐛 +
andrey81inmd

💻 🐛
anicoara

🐛
arunprasathav

🐛
asiercamara

🐛
astillich-igniti

💻
avesolovksyy

🐛
avishvat

🐛 -
avivmu

🐛 +
avivmu

🐛
axelbarfod1

🐛
b-3-n

🐛
balbhadra9

🐛
base23de

🐛
bergander

🐛
berkam

💻 🐛 -
breizh31

🐛 +
breizh31

🐛
caesarkim

🐛
carolyujing

🐛
cesares-basilico

🐛
chrite

🐛
cobratbq

🐛
coladict

🐛 -
cosmoJFH

🐛 +
cosmoJFH

🐛
cristalp

🐛
crunsk

🐛
cwholmes

🐛
cyberjj999

🐛
cyw3

🐛
d1ss0nanz

🐛 -
danbrycefairsailcom

🐛 +
danbrycefairsailcom

🐛
dariansanity

🐛
darrenmiliband

🐛
davidburstrom

🐛
dbirkman-paloalto

🐛
deepak-patra

🐛
dependabot[bot]

💻 🐛 -
dinesh150

🐛 +
dinesh150

🐛
diziaq

🐛
dreaminpast123

🐛
duanyanan

🐛
dutt-sanjay

🐛
dylanleung

🐛
dzeigler

🐛 -
ekkirala

🐛 +
ekkirala

🐛
emersonmoura

🐛
fairy

🐛
filiprafalowicz

💻
foxmason

🐛
frankegabor

🐛
frankl

🐛 -
freafrea

🐛 +
freafrea

🐛
fsapatin

🐛
gracia19

🐛
guo fei

🐛
gurmsc5

🐛
gwilymatgearset

💻 🐛
haigsn

🐛 -
hemanshu070

🐛 +
hemanshu070

🐛
henrik242

🐛
hongpuwu

🐛
hvbtup

💻 🐛
igniti GmbH

🐛
ilovezfs

🐛
itaigilo

🐛 -
jakivey32

🐛 +
jakivey32

🐛
jbennett2091

🐛
jcamerin

🐛
jkeener1

🐛
jmetertea

🐛
johnra2

💻
josemanuelrolon

💻 🐛 -
kabroxiko

💻 🐛 +
kabroxiko

💻 🐛
karwer

🐛
kaulonline

🐛
kdaemonv

🐛
kenji21

💻 🐛
kfranic

🐛
khalidkh

🐛 -
krzyk

🐛 +
krzyk

🐛
lasselindqvist

🐛
lihuaib

🐛
lonelyma1021

🐛
lpeddy

🐛
lujiefsi

💻
lukelukes

💻 -
lyriccoder

🐛 +
lyriccoder

🐛
marcelmore

🐛
matchbox

🐛
matthiaskraaz

🐛
meandonlyme

🐛
mikesive

🐛
milossesic

🐛 -
mriddell95

🐛 +
mriddell95

🐛
mrlzh

🐛
msloan

🐛
mucharlaravalika

🐛
mvenneman

🐛
nareshl119

🐛
nicolas-harraudeau-sonarsource

🐛 -
noerremark

🐛 +
noerremark

🐛
novsirion

🐛
oggboy

🐛
oinume

🐛
orimarko

💻 🐛
pallavi agarwal

🐛
parksungrin

🐛 -
patpatpat123

🐛 +
patpatpat123

🐛
patriksevallius

🐛
pbrajesh1

🐛
phoenix384

🐛
piotrszymanski-sc

💻
plan3d

🐛
poojasix

🐛 -
prabhushrikant

🐛 +
prabhushrikant

🐛
pujitha8783

🐛
r-r-a-j

🐛
raghujayjunk

🐛
rajeshveera

🐛
rajeswarreddy88

🐛
recdevs

🐛 -
reudismam

💻 🐛 +
reudismam

💻 🐛
rijkt

🐛
rillig-tk

🐛
rmohan20

💻 🐛
rxmicro

🐛
ryan-gustafson

💻 🐛
sabi0

🐛 -
scais

🐛 +
scais

🐛
sebbASF

🐛
sergeygorbaty

💻
shilko2013

🐛
simeonKondr

🐛
snajberk

🐛
sniperrifle2004

🐛 -
snuyanzin

🐛 💻 +
snuyanzin

🐛 💻
sratz

🐛
stonio

🐛
sturton

💻 🐛
sudharmohan

🐛
suruchidawar

🐛
svenfinitiv

🐛 -
tashiscool

🐛 +
tashiscool

🐛
test-git-hook

🐛
testation21

💻 🐛
thanosa

🐛
tiandiyixian

🐛
tobwoerk

🐛
tprouvot

🐛 -
trentchilders

🐛 +
trentchilders

🐛
triandicAnt

🐛
trishul14

🐛
tsui

🐛
winhkey

🐛
witherspore

🐛
wjljack

🐛 -
wuchiuwong

🐛 +
wuchiuwong

🐛
xingsong

🐛
xioayuge

🐛
xnYi9wRezm

💻 🐛
xuanuy

🐛
xyf0921

🐛
yalechen-cyw3

🐛 -
yasuharu-sato

🐛 +
yasuharu-sato

🐛
zenglian

🐛
zgrzyt93

💻 🐛
zh3ng

🐛
zt_soft

🐛
ztt79

🐛
zzzzfeng

🐛 -
Árpád Magosányi

🐛 +
Árpád Magosányi

🐛
任贵杰

🐛