Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Expose collections from getters as XPath sequence attributes #4969

Merged
merged 29 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
53246d5
Support sequences in XPath Attributes
jsotuyod Apr 12, 2024
a01481a
Add test for collection attributes
jsotuyod Apr 19, 2024
f307e6e
Update changelog
jsotuyod Apr 19, 2024
8db0c80
Restrict exposed attributes based on element types
jsotuyod Apr 19, 2024
ce5e229
Produce deprecation warnings when atomize is used
jsotuyod Apr 19, 2024
8d51a2f
Just do it once per attribute
jsotuyod Apr 19, 2024
b74b6e5
Revert. Different rules on the same node report separately
jsotuyod Apr 19, 2024
0d6f196
Fix broken tests
jsotuyod Apr 19, 2024
3a4abd7
Schema awareness changes the produced queries
jsotuyod Apr 19, 2024
02e7a71
Update Apex tree dumps with the new attributes
jsotuyod Apr 19, 2024
d769336
Have the NodePrinter show collections as sequences
jsotuyod Apr 19, 2024
d9e146d
Update Java parser test to show modifiers properly
jsotuyod Apr 19, 2024
ca7e15c
update output to sequences
jsotuyod Apr 19, 2024
0d32ac8
Update more tree dump tests
jsotuyod Apr 19, 2024
62443a4
Update tree export test
jsotuyod Apr 19, 2024
1231a54
Remove unsused imports
jsotuyod Apr 19, 2024
346d7fd
Do not warn for List being deprecated by default
jsotuyod Apr 19, 2024
3650622
Remove unused imports
jsotuyod Apr 19, 2024
28c5cd7
Remove `@Names` attribute from ASTReferenceExpression
jsotuyod Apr 28, 2024
56f12d4
Update docs/pages/release_notes.md
jsotuyod Apr 28, 2024
11e6cc5
Update docs on writing xpath rules
jsotuyod Apr 28, 2024
124f908
Properly log when the impossible happens
jsotuyod Apr 28, 2024
fbb4648
Update pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/int…
jsotuyod Apr 28, 2024
6660664
Merge branch 'master' into xpath-seq-attributes
jsotuyod Apr 28, 2024
458405e
Use spaces
jsotuyod Apr 28, 2024
4bb533b
Ignore type variables
jsotuyod Apr 28, 2024
895cfbf
Update docs/pages/release_notes.md
jsotuyod May 2, 2024
6fd230e
Update docs/pages/release_notes.md
jsotuyod May 2, 2024
722f25b
Merge branch 'master' into xpath-seq-attributes
jsotuyod May 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/pages/release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ This is a {{ site.pmd.release_type }} release.

### 🚀 New and noteworthy

#### Collections exposed as XPath attributes

Up to now, all AST node getters would be exposed to XPath, as long as the return type was a primitive (boxed or unboxed), String or Enum. That meant that collections, even of these basic types, were not exposed, so for instance accessing Apex's `ASTUserClass.getInterfaceNames()` to list the interfaces implemented by a class was impossible from XPath, and would require writing a Java rule to check it.
jsotuyod marked this conversation as resolved.
Show resolved Hide resolved

Since this release, PMD will also expose any getter returning a collection of any supported type as a sequence through an XPath attribute. They would require to use apropriate XQuery functions to manipulate the sequence. So for instance, to detect any given `ASTUserClass` that implements `Queueable`, it is now possible to write:
jsotuyod marked this conversation as resolved.
Show resolved Hide resolved

```xml
/UserClass[not(empty(index-of(@InterfaceNames, 'Queueable')))]
jsotuyod marked this conversation as resolved.
Show resolved Hide resolved
```

### ✨ New rules

- The new Java rule {%rule java/bestpractices/UnnecessaryVarargsArrayCreation %} reports explicit array creation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
+- ApexFile[@DefiningType = "InnerClassLocations", @RealLoc = true]
+- UserClass[@DefiningType = "InnerClassLocations", @Image = "InnerClassLocations", @RealLoc = true, @SimpleName = "InnerClassLocations", @SuperClassName = ""]
+- UserClass[@DefiningType = "InnerClassLocations", @Image = "InnerClassLocations", @InterfaceNames = (), @RealLoc = true, @SimpleName = "InnerClassLocations", @SuperClassName = ""]
+- ModifierNode[@Abstract = false, @DefiningType = "InnerClassLocations", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- UserClass[@DefiningType = "InnerClassLocations.bar1", @Image = "bar1", @RealLoc = true, @SimpleName = "bar1", @SuperClassName = ""]
+- UserClass[@DefiningType = "InnerClassLocations.bar1", @Image = "bar1", @InterfaceNames = (), @RealLoc = true, @SimpleName = "bar1", @SuperClassName = ""]
| +- ModifierNode[@Abstract = false, @DefiningType = "InnerClassLocations.bar1", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- Method[@Arity = 0, @CanonicalName = "m", @Constructor = false, @DefiningType = "InnerClassLocations.bar1", @Image = "m", @RealLoc = true, @ReturnType = "void", @StaticInitializer = false]
| +- ModifierNode[@Abstract = false, @DefiningType = "InnerClassLocations.bar1", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- BlockStatement[@CurlyBrace = true, @DefiningType = "InnerClassLocations.bar1", @RealLoc = true]
| +- ExpressionStatement[@DefiningType = "InnerClassLocations.bar1", @RealLoc = true]
| | +- MethodCallExpression[@DefiningType = "InnerClassLocations.bar1", @FullMethodName = "System.out.println", @InputParametersSize = 1, @MethodName = "println", @RealLoc = true]
| | +- ReferenceExpression[@DefiningType = "InnerClassLocations.bar1", @Image = "System", @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
| | +- ReferenceExpression[@DefiningType = "InnerClassLocations.bar1", @Image = "System", @Names = ("System", "out"), @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
jsotuyod marked this conversation as resolved.
Show resolved Hide resolved
| | +- LiteralExpression[@Boolean = false, @Decimal = false, @DefiningType = "InnerClassLocations.bar1", @Double = false, @Image = "foo", @Integer = false, @LiteralType = LiteralType.STRING, @Long = false, @Name = null, @Null = false, @RealLoc = true, @String = true]
| +- ExpressionStatement[@DefiningType = "InnerClassLocations.bar1", @RealLoc = true]
| +- MethodCallExpression[@DefiningType = "InnerClassLocations.bar1", @FullMethodName = "System.out.println", @InputParametersSize = 1, @MethodName = "println", @RealLoc = true]
| +- ReferenceExpression[@DefiningType = "InnerClassLocations.bar1", @Image = "System", @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
| +- ReferenceExpression[@DefiningType = "InnerClassLocations.bar1", @Image = "System", @Names = ("System", "out"), @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
| +- LiteralExpression[@Boolean = false, @Decimal = false, @DefiningType = "InnerClassLocations.bar1", @Double = false, @Image = "foo", @Integer = false, @LiteralType = LiteralType.STRING, @Long = false, @Name = null, @Null = false, @RealLoc = true, @String = true]
+- UserClass[@DefiningType = "InnerClassLocations.bar2", @Image = "bar2", @RealLoc = true, @SimpleName = "bar2", @SuperClassName = ""]
+- UserClass[@DefiningType = "InnerClassLocations.bar2", @Image = "bar2", @InterfaceNames = (), @RealLoc = true, @SimpleName = "bar2", @SuperClassName = ""]
+- ModifierNode[@Abstract = false, @DefiningType = "InnerClassLocations.bar2", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- Method[@Arity = 0, @CanonicalName = "m", @Constructor = false, @DefiningType = "InnerClassLocations.bar2", @Image = "m", @RealLoc = true, @ReturnType = "void", @StaticInitializer = false]
+- ModifierNode[@Abstract = false, @DefiningType = "InnerClassLocations.bar2", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- BlockStatement[@CurlyBrace = true, @DefiningType = "InnerClassLocations.bar2", @RealLoc = true]
+- ExpressionStatement[@DefiningType = "InnerClassLocations.bar2", @RealLoc = true]
| +- MethodCallExpression[@DefiningType = "InnerClassLocations.bar2", @FullMethodName = "System.out.println", @InputParametersSize = 1, @MethodName = "println", @RealLoc = true]
| +- ReferenceExpression[@DefiningType = "InnerClassLocations.bar2", @Image = "System", @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
| +- ReferenceExpression[@DefiningType = "InnerClassLocations.bar2", @Image = "System", @Names = ("System", "out"), @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
| +- LiteralExpression[@Boolean = false, @Decimal = false, @DefiningType = "InnerClassLocations.bar2", @Double = false, @Image = "foo", @Integer = false, @LiteralType = LiteralType.STRING, @Long = false, @Name = null, @Null = false, @RealLoc = true, @String = true]
+- ExpressionStatement[@DefiningType = "InnerClassLocations.bar2", @RealLoc = true]
+- MethodCallExpression[@DefiningType = "InnerClassLocations.bar2", @FullMethodName = "System.out.println", @InputParametersSize = 1, @MethodName = "println", @RealLoc = true]
+- ReferenceExpression[@DefiningType = "InnerClassLocations.bar2", @Image = "System", @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
+- ReferenceExpression[@DefiningType = "InnerClassLocations.bar2", @Image = "System", @Names = ("System", "out"), @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
+- LiteralExpression[@Boolean = false, @Decimal = false, @DefiningType = "InnerClassLocations.bar2", @Double = false, @Image = "foo", @Integer = false, @LiteralType = LiteralType.STRING, @Long = false, @Name = null, @Null = false, @RealLoc = true, @String = true]
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
+- ApexFile[@DefiningType = "NullCoalescingOperator", @RealLoc = true]
+- UserClass[@DefiningType = "NullCoalescingOperator", @Image = "NullCoalescingOperator", @RealLoc = true, @SimpleName = "NullCoalescingOperator", @SuperClassName = ""]
+- UserClass[@DefiningType = "NullCoalescingOperator", @Image = "NullCoalescingOperator", @InterfaceNames = (), @RealLoc = true, @SimpleName = "NullCoalescingOperator", @SuperClassName = ""]
+- ModifierNode[@Abstract = false, @DefiningType = "NullCoalescingOperator", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- Method[@Arity = 2, @CanonicalName = "leftOrRight", @Constructor = false, @DefiningType = "NullCoalescingOperator", @Image = "leftOrRight", @RealLoc = true, @ReturnType = "String", @StaticInitializer = false]
+- ModifierNode[@Abstract = false, @DefiningType = "NullCoalescingOperator", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
Expand Down