0
# PMD Apex
1
2
PMD Apex provides comprehensive static code analysis capabilities for Salesforce Apex programming language as part of the PMD static code analyzer ecosystem. It integrates with apex-parser and Summit AST libraries to parse Apex source code and generate abstract syntax trees (AST) for rule-based analysis, enabling automated code quality checks, security vulnerability detection, and adherence to coding standards within Apex development workflows.
3
4
## Package Information
5
6
- **Package Name**: pmd-apex
7
- **Package Type**: maven
8
- **Group ID**: net.sourceforge.pmd
9
- **Artifact ID**: pmd-apex
10
- **Language**: Java/Kotlin
11
- **Installation**: Add to Maven: `<dependency><groupId>net.sourceforge.pmd</groupId><artifactId>pmd-apex</artifactId><version>7.13.0</version></dependency>`
12
13
## Core Imports
14
15
```java
16
import net.sourceforge.pmd.lang.apex.ApexLanguageModule;
17
import net.sourceforge.pmd.lang.apex.ast.*;
18
import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule;
19
import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics;
20
import net.sourceforge.pmd.lang.apex.multifile.ApexMultifileAnalysis;
21
```
22
23
## Basic Usage
24
25
```java
26
// Register language module
27
ApexLanguageModule apexModule = ApexLanguageModule.getInstance();
28
29
// Parse Apex code into AST
30
ApexParser parser = new ApexParser();
31
ASTApexFile apexFile = parser.parse(parserTask);
32
33
// Create custom rule
34
public class MyApexRule extends AbstractApexRule {
35
@Override
36
public Object visit(ASTUserClass node, Object data) {
37
// Rule logic for class analysis
38
String className = node.getQualifiedName().getClassName();
39
return super.visit(node, data);
40
}
41
42
@Override
43
public Object visit(ASTMethod node, Object data) {
44
// Rule logic for method analysis
45
int complexity = MetricsUtil.computeMetric(ApexMetrics.CYCLO, node);
46
return super.visit(node, data);
47
}
48
}
49
50
// Multifile analysis
51
ApexMultifileAnalysis analysis = processor.getMultiFileState();
52
List<Issue> issues = analysis.getFileIssues("MyClass.cls");
53
```
54
55
## Architecture
56
57
PMD Apex is built around several key components:
58
59
- **Language Module**: Main entry point (`ApexLanguageModule`) for PMD integration and language registration
60
- **AST Framework**: Complete Abstract Syntax Tree representation with 95+ node types covering all Apex language constructs
61
- **Visitor Pattern**: `ApexVisitor` interface with traversal methods for each AST node type
62
- **Rule Engine**: Base classes and built-in rules across 6 categories (40+ rules total)
63
- **Metrics System**: Built-in complexity and quality metrics (cyclomatic, cognitive complexity, weighted method count)
64
- **Multifile Analysis**: Cross-file dependency analysis using ApexLink integration
65
- **CPD Integration**: Copy-paste detection capabilities for code duplication analysis
66
67
## Capabilities
68
69
### Language Module and Registration
70
71
Core language module registration and configuration for PMD integration. Provides entry points for parser creation, language properties, and violation suppression handling.
72
73
```java { .api }
74
public class ApexLanguageModule {
75
public static ApexLanguageModule getInstance();
76
public ApexLanguageProcessor createProcessor(LanguagePropertyBundle bundle);
77
public ApexLanguageProperties newPropertyBundle();
78
public CpdLexer createCpdLexer(LanguagePropertyBundle bundle);
79
}
80
81
public class ApexLanguageProcessor {
82
public LanguageVersionHandler services();
83
public ApexMultifileAnalysis getMultiFileState();
84
}
85
```
86
87
[Language Module](./language-module.md)
88
89
### AST Parsing and Navigation
90
91
Complete Abstract Syntax Tree representation for Apex code with 95+ node types covering all language constructs. Includes parser, root nodes, and visitor pattern for tree traversal.
92
93
```java { .api }
94
public class ApexParser {
95
public ASTApexFile parse(ParserTask task);
96
}
97
98
public interface ApexNode<T> {
99
boolean hasRealLoc();
100
String getDefiningType();
101
ASTApexFile getRoot();
102
}
103
104
public interface ApexVisitor<P, R> {
105
R visit(ASTUserClass node, P data);
106
R visit(ASTMethod node, P data);
107
R visit(ASTVariableExpression node, P data);
108
// 80+ additional visit methods for all AST node types
109
}
110
```
111
112
[AST Parsing and Navigation](./ast.md)
113
114
### Built-in Metrics
115
116
Complexity and quality metrics calculation for Apex code analysis. Provides cyclomatic complexity, cognitive complexity, and weighted method count metrics.
117
118
```java { .api }
119
public class ApexMetrics {
120
public static final Metric<ASTMethod, Integer> CYCLO;
121
public static final Metric<ASTMethod, Integer> COGNITIVE_COMPLEXITY;
122
public static final Metric<ASTUserClass, Integer> WEIGHED_METHOD_COUNT;
123
}
124
```
125
126
[Metrics](./metrics.md)
127
128
### Multifile Analysis
129
130
Cross-file analysis capabilities using ApexLink for analyzing dependencies and relationships across multiple Apex files in a Salesforce project.
131
132
```java { .api }
133
public class ApexMultifileAnalysis {
134
public boolean isFailed();
135
public List<Issue> getFileIssues(String fileName);
136
}
137
```
138
139
[Multifile Analysis](./multifile.md)
140
141
### Rule Development Framework
142
143
Base classes and framework for creating custom PMD rules. Includes abstract base rule class with visitor pattern integration and access to AST traversal.
144
145
```java { .api }
146
public abstract class AbstractApexRule implements ApexVisitor<Object, Object> {
147
public void apply(Node target, RuleContext ctx);
148
// Inherits 80+ visit methods from ApexVisitor
149
}
150
```
151
152
[Rule Development](./rules.md)
153
154
### Copy-Paste Detection
155
156
Lexical analysis for detecting code duplication within Apex codebases. Integrates with PMD's Copy-Paste Detection (CPD) framework.
157
158
```java { .api }
159
public class ApexCpdLexer {
160
public void tokenize(TextDocument textDocument, TokenFactory tokenFactory);
161
}
162
```
163
164
[Copy-Paste Detection](./cpd.md)
165
166
## Types
167
168
### Core Interfaces
169
170
```java { .api }
171
public interface ApexNode<T> {
172
boolean hasRealLoc();
173
String getDefiningType();
174
ASTApexFile getRoot();
175
}
176
177
public interface ApexVisitor<P, R> {
178
R visit(ASTApexFile node, P data);
179
R visit(ASTUserClass node, P data);
180
R visit(ASTUserInterface node, P data);
181
R visit(ASTUserEnum node, P data);
182
R visit(ASTUserTrigger node, P data);
183
R visit(ASTMethod node, P data);
184
R visit(ASTField node, P data);
185
R visit(ASTProperty node, P data);
186
R visit(ASTParameter node, P data);
187
R visit(ASTBlockStatement node, P data);
188
R visit(ASTIfBlockStatement node, P data);
189
R visit(ASTWhileLoopStatement node, P data);
190
R visit(ASTForLoopStatement node, P data);
191
R visit(ASTVariableExpression node, P data);
192
R visit(ASTMethodCallExpression node, P data);
193
R visit(ASTBinaryExpression node, P data);
194
R visit(ASTAssignmentExpression node, P data);
195
R visit(ASTSoqlExpression node, P data);
196
R visit(ASTSoslExpression node, P data);
197
// 70+ additional visit methods for remaining AST node types
198
}
199
200
public interface ApexQualifiableNode {
201
ApexQualifiedName getQualifiedName();
202
}
203
204
public interface AccessNode {
205
// Access modifier related methods
206
}
207
```
208
209
### Operator Enums
210
211
```java { .api }
212
public enum BinaryOperator {
213
ADDITION, SUBTRACTION, MULTIPLICATION, DIVISION,
214
LEFT_SHIFT, RIGHT_SHIFT_SIGNED, RIGHT_SHIFT_UNSIGNED,
215
BITWISE_AND, BITWISE_OR, BITWISE_XOR, NULL_COALESCING
216
}
217
218
public enum BooleanOperator {
219
EQUAL, NOT_EQUAL, ALT_NOT_EQUAL, EXACTLY_EQUAL, EXACTLY_NOT_EQUAL,
220
LESS_THAN, GREATER_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN_OR_EQUAL,
221
LOGICAL_AND, LOGICAL_OR
222
}
223
224
public enum AssignmentOperator {
225
EQUALS, ADDITION_EQUALS, SUBTRACTION_EQUALS, MULTIPLICATION_EQUALS,
226
DIVISION_EQUALS, LEFT_SHIFT_EQUALS, RIGHT_SHIFT_SIGNED_EQUALS,
227
RIGHT_SHIFT_UNSIGNED_EQUALS, BITWISE_AND_EQUALS, BITWISE_OR_EQUALS,
228
BITWISE_XOR_EQUALS
229
}
230
231
public enum PrefixOperator {
232
POSITIVE, NEGATIVE, LOGICAL_NOT, BITWISE_NOT, INCREMENT, DECREMENT
233
}
234
235
public enum PostfixOperator {
236
INCREMENT, DECREMENT
237
}
238
239
public enum ReferenceType {
240
LOAD, STORE, METHOD, CLASS, NONE
241
}
242
243
public enum TriggerUsage {
244
AFTER_DELETE, AFTER_INSERT, AFTER_UNDELETE, AFTER_UPDATE,
245
BEFORE_DELETE, BEFORE_INSERT, BEFORE_UNDELETE, BEFORE_UPDATE
246
}
247
```
248
249
### Utility Classes
250
251
```java { .api }
252
public class ApexQualifiedName {
253
public boolean isClass();
254
public boolean isOperation();
255
public String getClassName();
256
public static ApexQualifiedName ofString(String qualifiedName);
257
}
258
```