or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-parsing.mdindex.mdlanguage-module.mdrule-development.mdtype-analysis.md

rule-development.mddocs/

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.