0
# Rule Development Framework
1
2
Infrastructure for creating custom PMD rules to analyze Visualforce code quality and security issues. This capability provides the foundation for building static analysis rules specific to Visualforce development patterns and security concerns.
3
4
## Capabilities
5
6
### AbstractVfRule
7
8
Base class for all Visualforce PMD rules, providing visitor pattern integration and rule execution framework.
9
10
```java { .api }
11
/**
12
* Abstract base class for Visualforce PMD rules
13
* Extends PMD's AbstractRule and implements VfVisitor for AST traversal
14
* All custom Visualforce rules should extend this class
15
*/
16
public abstract class AbstractVfRule extends AbstractRule implements VfVisitor<Object, Object> {
17
/**
18
* Apply this rule to an AST node and its descendants
19
* Entry point called by PMD framework for rule execution
20
* @param target Root AST node to analyze (typically ASTCompilationUnit)
21
* @param ctx Rule context containing reporting and configuration
22
*/
23
@Override
24
public void apply(Node target, RuleContext ctx);
25
26
/**
27
* Default visitor implementation that traverses all child nodes
28
* Override specific visit methods to implement rule logic
29
* @param node AST node being visited
30
* @param param Context parameter (typically RuleContext)
31
* @return Parameter passed through (typically unchanged RuleContext)
32
*/
33
@Override
34
public Object visitNode(Node node, Object param);
35
}
36
```
37
38
**Usage Example:**
39
40
```java
41
import net.sourceforge.pmd.lang.visualforce.rule.AbstractVfRule;
42
import net.sourceforge.pmd.lang.visualforce.ast.*;
43
44
/**
45
* Example rule that checks for hardcoded strings in Visualforce pages
46
*/
47
public class NoHardcodedStringsRule extends AbstractVfRule {
48
49
@Override
50
public Object visit(ASTLiteral literal, Object data) {
51
String value = literal.getImage();
52
53
// Check for hardcoded user-facing strings
54
if (value != null && value.length() > 1 &&
55
value.startsWith("'") && value.endsWith("'")) {
56
57
String content = value.substring(1, value.length() - 1);
58
if (isUserFacingString(content)) {
59
addViolation(data, literal,
60
"Hardcoded user-facing string should use labels or custom settings");
61
}
62
}
63
64
return super.visit(literal, data);
65
}
66
67
private boolean isUserFacingString(String content) {
68
// Implementation logic to detect user-facing strings
69
return content.length() > 10 && !content.matches("^[A-Z_]+$");
70
}
71
}
72
```
73
74
### VfVisitor Interface
75
76
Core visitor interface for traversing Visualforce AST nodes with type-safe visit methods.
77
78
```java { .api }
79
/**
80
* Visitor interface for Visualforce AST traversal
81
* Provides visit methods for all AST node types
82
* @param <P> Parameter type passed through visitation
83
* @param <R> Return type from visit methods
84
*/
85
public interface VfVisitor<P, R> {
86
// Root and compilation nodes
87
R visit(ASTCompilationUnit node, P data);
88
89
// Element and structure nodes
90
R visit(ASTElement node, P data);
91
R visit(ASTAttribute node, P data);
92
R visit(ASTAttributeValue node, P data);
93
R visit(ASTContent node, P data);
94
95
// Expression nodes
96
R visit(ASTElExpression node, P data);
97
R visit(ASTExpression node, P data);
98
R visit(ASTDotExpression node, P data);
99
R visit(ASTNegationExpression node, P data);
100
R visit(ASTIdentifier node, P data);
101
R visit(ASTLiteral node, P data);
102
R visit(ASTArguments node, P data);
103
104
// Text and content nodes
105
R visit(ASTText node, P data);
106
R visit(ASTCData node, P data);
107
R visit(ASTHtmlScript node, P data);
108
109
// Document structure nodes
110
R visit(ASTDeclaration node, P data);
111
R visit(ASTDoctypeDeclaration node, P data);
112
R visit(ASTDoctypeExternalId node, P data);
113
114
// Default visitor behavior for unhandled nodes
115
R visitNode(Node node, P data);
116
}
117
```
118
119
### VfVisitorBase
120
121
Abstract base implementation of VfVisitor providing common traversal patterns.
122
123
```java { .api }
124
/**
125
* Abstract base visitor for Visualforce AST traversal
126
* Extends PMD's AstVisitorBase with Visualforce-specific functionality
127
* Provides default implementations that delegate to visitNode()
128
*/
129
public abstract class VfVisitorBase<P, R> extends AstVisitorBase<P, R> implements VfVisitor<P, R> {
130
/**
131
* Default implementation for all visit methods
132
* Override specific visit methods to implement custom logic
133
* @param node AST node being visited
134
* @param data Context data
135
* @return Result from processing
136
*/
137
@Override
138
public R visitNode(Node node, P data);
139
}
140
```
141
142
**Usage Example:**
143
144
```java
145
import net.sourceforge.pmd.lang.visualforce.ast.VfVisitorBase;
146
147
/**
148
* Visitor to collect all EL expressions in a Visualforce page
149
*/
150
public class ElExpressionCollector extends VfVisitorBase<List<ASTElExpression>, List<ASTElExpression>> {
151
152
@Override
153
public List<ASTElExpression> visit(ASTElExpression expression, List<ASTElExpression> expressions) {
154
// Add this expression to collection
155
expressions.add(expression);
156
157
// Continue traversing children
158
return super.visit(expression, expressions);
159
}
160
161
public static List<ASTElExpression> collectExpressions(ASTCompilationUnit root) {
162
List<ASTElExpression> expressions = new ArrayList<>();
163
ElExpressionCollector collector = new ElExpressionCollector();
164
collector.visit(root, expressions);
165
return expressions;
166
}
167
}
168
```
169
170
### Built-in Security Rules
171
172
Pre-implemented security rules that demonstrate rule development patterns and provide immediate value for Visualforce security analysis.
173
174
```java { .api }
175
/**
176
* Rule to detect CSRF vulnerabilities in Visualforce pages
177
* Checks for missing or improperly configured CSRF protection
178
*/
179
public class VfCsrfRule extends AbstractVfRule {
180
/**
181
* Visit apex:page elements to check CSRF configuration
182
* @param node ASTElement representing apex:page
183
* @param data Rule context
184
* @return Rule context (unchanged)
185
*/
186
@Override
187
public Object visit(ASTElement node, Object data);
188
}
189
190
/**
191
* Rule to detect XSS vulnerabilities in HTML style tags
192
* Identifies potentially dangerous style tag content and attributes
193
*/
194
public class VfHtmlStyleTagXssRule extends AbstractVfRule {
195
/**
196
* Visit HTML style elements and attributes for XSS risks
197
* @param node ASTElement representing style elements
198
* @param data Rule context
199
* @return Rule context (unchanged)
200
*/
201
@Override
202
public Object visit(ASTElement node, Object data);
203
}
204
205
/**
206
* Rule to detect unescaped Expression Language that could lead to XSS
207
* Analyzes EL expressions for proper escaping based on context and data types
208
*/
209
public class VfUnescapeElRule extends AbstractVfRule {
210
/**
211
* Visit EL expressions to check for proper escaping
212
* @param node ASTElExpression to analyze
213
* @param data Rule context
214
* @return Rule context (unchanged)
215
*/
216
@Override
217
public Object visit(ASTElExpression node, Object data);
218
219
/**
220
* Visit elements that contain EL expressions
221
* @param node ASTElement that may contain expressions
222
* @param data Rule context
223
* @return Rule context (unchanged)
224
*/
225
@Override
226
public Object visit(ASTElement node, Object data);
227
}
228
```
229
230
**Usage Example:**
231
232
```java
233
import net.sourceforge.pmd.lang.visualforce.rule.security.*;
234
235
// Security rules are typically configured in PMD ruleset XML files
236
// and applied automatically by the PMD engine:
237
238
/*
239
<rule ref="category/visualforce/security.xml/VfCsrfRule" />
240
<rule ref="category/visualforce/security.xml/VfUnescapeElRule" />
241
<rule ref="category/visualforce/security.xml/VfHtmlStyleTagXssRule" />
242
*/
243
244
// Rules can also be instantiated and applied programmatically:
245
public void analyzeSecurityIssues(ASTCompilationUnit ast, RuleContext ctx) {
246
VfCsrfRule csrfRule = new VfCsrfRule();
247
VfUnescapeElRule xssRule = new VfUnescapeElRule();
248
249
csrfRule.apply(ast, ctx);
250
xssRule.apply(ast, ctx);
251
}
252
```
253
254
### Custom Rule Development Pattern
255
256
Standard pattern for developing custom Visualforce analysis rules.
257
258
**Complete Custom Rule Example:**
259
260
```java
261
/**
262
* Rule to enforce naming conventions for Visualforce components
263
*/
264
public class ComponentNamingConventionRule extends AbstractVfRule {
265
266
private static final Pattern VALID_COMPONENT_NAME =
267
Pattern.compile("^[A-Z][a-zA-Z0-9]*$");
268
269
@Override
270
public Object visit(ASTElement element, Object data) {
271
// Check custom component usage
272
if (element.isHasNamespacePrefix() &&
273
"c".equals(element.getNamespacePrefix())) {
274
275
String componentName = element.getLocalName();
276
if (!VALID_COMPONENT_NAME.matcher(componentName).matches()) {
277
addViolation(data, element,
278
"Custom component name '" + componentName +
279
"' should use PascalCase naming convention");
280
}
281
}
282
283
return super.visit(element, data);
284
}
285
286
@Override
287
public Object visit(ASTAttribute attribute, Object data) {
288
// Check attribute naming for custom attributes
289
String attrName = attribute.getName();
290
if (attrName.startsWith("data-") &&
291
!attrName.toLowerCase().equals(attrName)) {
292
293
addViolation(data, attribute,
294
"Data attributes should use lowercase with hyphens");
295
}
296
297
return super.visit(attribute, data);
298
}
299
}
300
```
301
302
## Integration with PMD Framework
303
304
Visualforce rules integrate seamlessly with PMD's rule execution engine:
305
306
1. **Rule Registration**: Rules are registered through PMD's rule discovery mechanism
307
2. **Rule Configuration**: Rules can be configured via PMD configuration files
308
3. **Report Integration**: Rule violations are reported through PMD's standard reporting system
309
4. **Rule Categories**: Rules are organized into categories (e.g., security, design, performance)
310
311
The rule framework provides the foundation for comprehensive static analysis of Visualforce applications within Salesforce development workflows.