afv-library/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-method-calls.md

2.9 KiB

XPath Patterns for Method Calls and Annotations

← Back to XPath Patterns Index

Method Call Patterns

Ban System.debug (non-test classes)

//MethodCallExpression[@FullMethodName='System.debug']
  [not(ancestor::UserClass[ModifierNode[@Test = true()]])]

AST evidence: MethodCallExpression has @FullMethodName='System.debug'. Test classes have ModifierNode[@Test = true()].

Catches: System.debug('anything'); in production classes Does NOT catch (correct): Same call inside @IsTest classes

Ban Database.query (dynamic SOQL — SOQL injection risk)

//MethodCallExpression[@FullMethodName='Database.query']

AST evidence: MethodCallExpression[@FullMethodName='Database.query'] (line 118 of verified AST)

To exclude test classes:

//MethodCallExpression[@FullMethodName='Database.query']
  [not(ancestor::UserClass[ModifierNode[@Test = true()]])]

Ban Test.isRunningTest() in production code

//MethodCallExpression[@FullMethodName='Test.isRunningTest']
  [not(ancestor::UserClass[ModifierNode[@Test = true()]])]

Ban specific method calls (generic pattern)

//MethodCallExpression[@FullMethodName='ClassName.methodName']

Common examples:

  • @FullMethodName='System.debug'
  • @FullMethodName='Database.query'
  • @FullMethodName='Test.isRunningTest'
  • @FullMethodName='UserInfo.getUserId'
  • @FullMethodName='Limits.getQueries'

Annotation Patterns

@AuraEnabled without cacheable=true

//Method/ModifierNode/Annotation[@Name='AuraEnabled'
  and not(AnnotationParameter[@Name='cacheable' and @Value='true'])]

AST evidence: Annotation[@Name='AuraEnabled'] with child AnnotationParameter[@Name='cacheable'][@Value='true']

Catches: @AuraEnabled public static ... (no cacheable) Does NOT catch (correct): @AuraEnabled(cacheable=true) public static ...

@future methods (recommend Queueable instead)

//Method/ModifierNode/Annotation[@Name='Future']

AST evidence: Annotation @Name='Future' (note: PMD normalizes @futureFuture in the Name attribute, but @RawName='future')

@SuppressWarnings usage (audit/ban)

//Annotation[@Name='SuppressWarnings']

AST evidence: Annotation[@Name='SuppressWarnings'] with AnnotationParameter[@Name='value'][@Value='PMD.RuleName']

To flag specific suppressions:

//Annotation[@Name='SuppressWarnings']/AnnotationParameter[contains(@Value, 'ApexCRUDViolation')]

@IsTest without testFor parameter

From GitHub issue #2008:

//UserClass/ModifierNode/Annotation[
  @Name='IsTest'
  and not(AnnotationParameter[@Name='testFor'])
]

@IsTest class without System.runAs

//UserClass[ModifierNode[@Test = true()]]
  /Method[ModifierNode[@Test = true()]]
  /BlockStatement[not(.//RunAsBlockStatement)]

AST evidence: RunAsBlockStatement is the node for System.runAs(...) { } blocks.