or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-nodes.mdbuiltin-rules.mdindex.mdlanguage-integration.mdparsing.mdrule-development.md

builtin-rules.mddocs/

0

# Built-in Static Analysis Rules

1

2

Production-ready rules for detecting common issues in Velocity templates including best practices violations, design problems, and error-prone patterns. These rules are organized by category and ready for use in PMD rulesets.

3

4

## Capabilities

5

6

### Best Practices Rules

7

8

Rules that enforce Velocity template best practices and coding standards.

9

10

#### Avoid Reassigning Parameters

11

12

Detects reassignment of macro parameters, which can lead to confusion and unexpected behavior.

13

14

```java { .api }

15

/**

16

* Rule that detects reassignment of macro parameters.

17

* Parameter reassignment can make templates harder to understand and debug.

18

* Location: net.sourceforge.pmd.lang.vm.rule.bestpractices.AvoidReassigningParametersRule

19

*/

20

public class AvoidReassigningParametersRule extends AbstractVmRule {

21

// Implementation analyzes #set directives and macro parameter usage

22

// Reports violations when macro parameters are reassigned

23

}

24

```

25

26

**What it detects:**

27

- Reassignment of macro parameters using `#set` directive

28

- Modification of parameter values within macro body

29

- Potential confusion between parameter names and local variables

30

31

**Example violations:**

32

```velocity

33

#macro(processUser $userName $userAge)

34

#set($userName = "Modified") ## Violation: reassigning parameter

35

#set($userAge = $userAge + 1) ## Violation: reassigning parameter

36

<p>User: $userName, Age: $userAge</p>

37

#end

38

```

39

40

**Recommended fix:**

41

```velocity

42

#macro(processUser $userName $userAge)

43

#set($displayName = "Modified") ## Use different variable name

44

#set($calculatedAge = $userAge + 1) ## Use different variable name

45

<p>User: $displayName, Age: $calculatedAge</p>

46

#end

47

```

48

49

#### Unused Macro Parameter

50

51

Identifies macro parameters that are declared but never used, indicating potential dead code or missing implementation.

52

53

```java { .api }

54

/**

55

* Rule that detects unused macro parameters.

56

* Unused parameters suggest incomplete implementation or unnecessary complexity.

57

* Location: net.sourceforge.pmd.lang.vm.rule.bestpractices.UnusedMacroParameterRule

58

*/

59

public class UnusedMacroParameterRule extends AbstractVmRule {

60

// Implementation tracks macro parameter declarations and usage

61

// Reports violations for parameters that are never referenced

62

}

63

```

64

65

**What it detects:**

66

- Macro parameters that are declared but never referenced

67

- Parameters that may have been used in earlier template versions

68

- Potential API cleanup opportunities

69

70

**Example violations:**

71

```velocity

72

#macro(displayUser $userName $userAge $userEmail)

73

<p>Welcome $userName!</p>

74

<p>Age: $userAge</p>

75

## $userEmail is never used - violation

76

#end

77

```

78

79

**Recommended fix:**

80

```velocity

81

#macro(displayUser $userName $userAge) ## Remove unused parameter

82

<p>Welcome $userName!</p>

83

<p>Age: $userAge</p>

84

#end

85

```

86

87

### Design Rules

88

89

Rules that identify design issues and structural problems in Velocity templates.

90

91

#### Avoid Deeply Nested If Statements

92

93

Detects excessive nesting of if statements, which reduces readability and maintainability.

94

95

```java { .api }

96

/**

97

* Statistical rule that detects deeply nested if statements.

98

* Deep nesting makes templates difficult to read and maintain.

99

* Location: net.sourceforge.pmd.lang.vm.rule.design.AvoidDeeplyNestedIfStmtsRule

100

*/

101

public class AvoidDeeplyNestedIfStmtsRule extends AbstractStatisticalVmRule {

102

// Implementation tracks nesting depth of if statements

103

// Default threshold typically set to 3-4 levels

104

}

105

```

106

107

**What it detects:**

108

- If statements nested beyond configurable threshold (default: 3 levels)

109

- Complex conditional logic that may benefit from refactoring

110

- Templates that are difficult to test and maintain

111

112

**Example violations:**

113

```velocity

114

#if($user)

115

#if($user.isActive)

116

#if($user.hasPermission)

117

#if($user.inGroup) ## Violation: 4th level nesting

118

<p>User has access</p>

119

#end

120

#end

121

#end

122

#end

123

```

124

125

**Recommended fix:**

126

```velocity

127

#if($user && $user.isActive && $user.hasPermission && $user.inGroup)

128

<p>User has access</p>

129

#end

130

131

## Or use a macro to encapsulate complex logic

132

#macro(hasFullAccess $user)

133

#if($user && $user.isActive && $user.hasPermission && $user.inGroup)

134

true

135

#else

136

false

137

#end

138

#end

139

```

140

141

#### Collapsible If Statements

142

143

Identifies adjacent if statements that can be combined into a single conditional.

144

145

```java { .api }

146

/**

147

* Rule that detects if statements that can be collapsed into a single condition.

148

* Collapsible if statements indicate opportunities for simplification.

149

* Location: net.sourceforge.pmd.lang.vm.rule.design.CollapsibleIfStatementsRule

150

*/

151

public class CollapsibleIfStatementsRule extends AbstractVmRule {

152

// Implementation analyzes nested if statements with same conditional logic

153

// Reports violations when inner if can be combined with outer if

154

}

155

```

156

157

**What it detects:**

158

- Nested if statements that can be combined with logical operators

159

- Sequential if statements with related conditions

160

- Opportunities to simplify conditional logic

161

162

**Example violations:**

163

```velocity

164

#if($user)

165

#if($user.isActive) ## Violation: can be collapsed

166

<p>Active user: $user.name</p>

167

#end

168

#end

169

```

170

171

**Recommended fix:**

172

```velocity

173

#if($user && $user.isActive)

174

<p>Active user: $user.name</p>

175

#end

176

```

177

178

#### Excessive Template Length

179

180

Measures template length and flags templates that exceed reasonable size limits.

181

182

```java { .api }

183

/**

184

* Statistical rule that detects excessively long templates.

185

* Long templates are difficult to maintain and may indicate design issues.

186

* Location: net.sourceforge.pmd.lang.vm.rule.design.ExcessiveTemplateLengthRule

187

*/

188

public class ExcessiveTemplateLengthRule extends AbstractStatisticalVmRule {

189

// Implementation counts lines or AST nodes in template

190

// Default threshold typically set to 500-1000 lines

191

}

192

```

193

194

**What it detects:**

195

- Templates exceeding configurable line count threshold

196

- Templates that may benefit from decomposition

197

- Potential maintenance and testing challenges

198

199

**Configuration:**

200

- `maxLines`: Maximum allowed lines (default: 500)

201

- `countBlankLines`: Whether to include blank lines in count

202

203

**Recommended fixes:**

204

- Break large templates into smaller, focused templates

205

- Extract reusable sections into macros

206

- Use template inheritance or composition patterns

207

208

#### No Inline JavaScript

209

210

Detects inline JavaScript code within Velocity templates, promoting separation of concerns.

211

212

```java { .api }

213

/**

214

* Rule that detects inline JavaScript in Velocity templates.

215

* Inline JavaScript violates separation of concerns and complicates maintenance.

216

* Location: net.sourceforge.pmd.lang.vm.rule.design.NoInlineJavaScriptRule

217

*/

218

public class NoInlineJavaScriptRule extends AbstractVmRule {

219

// Implementation analyzes text content for JavaScript patterns

220

// Reports violations when <script> tags or JavaScript code detected

221

}

222

```

223

224

**What it detects:**

225

- `<script>` tags with JavaScript content

226

- Inline event handlers (`onclick`, `onload`, etc.)

227

- JavaScript code mixed with template markup

228

229

**Example violations:**

230

```velocity

231

<div onclick="alert('Hello')">Click me</div> ## Violation: inline JS

232

<script>

233

function doSomething() { ## Violation: inline script block

234

alert('Action performed');

235

}

236

</script>

237

```

238

239

**Recommended fix:**

240

```velocity

241

<div class="clickable-element">Click me</div>

242

## Move JavaScript to separate .js files

243

## Use CSS classes and external event handlers

244

```

245

246

#### No Inline Styles

247

248

Detects inline CSS styles within Velocity templates, promoting separation of concerns and maintainable styling.

249

250

```java { .api }

251

/**

252

* XPath-based rule that detects inline CSS styles in Velocity templates.

253

* Inline styles violate separation of concerns and complicate maintenance.

254

* Location: Implemented as XPath rule in category/vm/design.xml

255

*/

256

// XPath Rule: //Text[matches(@literal, "<[^>]+\s[sS][tT][yY][lL][eE]\s*=")]

257

// Rule Class: net.sourceforge.pmd.lang.rule.XPathRule

258

```

259

260

**What it detects:**

261

- `style` attributes on HTML elements

262

- Inline CSS declarations mixed with template markup

263

- CSS code that should be externalized to CSS files

264

265

**Example violations:**

266

```velocity

267

<div style="color: red; font-size: 14px;">Styled text</div> ## Violation: inline style

268

<p style="margin: 10px;">Content</p> ## Violation: inline style

269

<span style="background-color: #fff;">Text</span> ## Violation: inline style

270

```

271

272

**Recommended fix:**

273

```velocity

274

<div class="error-text">Styled text</div>

275

<p class="content-paragraph">Content</p>

276

<span class="highlighted-text">Text</span>

277

## Move styles to separate .css files

278

## Use CSS classes and external stylesheets

279

```

280

281

### Error-Prone Rules

282

283

Rules that detect patterns likely to cause runtime errors or unexpected behavior.

284

285

#### Empty Foreach Statement

286

287

Detects foreach loops with empty bodies, which may indicate incomplete implementation.

288

289

```java { .api }

290

/**

291

* Rule that detects empty foreach statements.

292

* Empty foreach loops suggest incomplete implementation or missing content.

293

* Location: net.sourceforge.pmd.lang.vm.rule.errorprone.EmptyForeachStmtRule

294

*/

295

public class EmptyForeachStmtRule extends AbstractVmRule {

296

// Implementation analyzes foreach statement bodies

297

// Reports violations when body contains no meaningful content

298

}

299

```

300

301

**What it detects:**

302

- Foreach loops with completely empty bodies

303

- Foreach loops containing only whitespace or comments

304

- Potentially incomplete loop implementations

305

306

**Example violations:**

307

```velocity

308

#foreach($item in $items)

309

## Empty loop body - violation

310

#end

311

312

#foreach($user in $users)

313

<!-- TODO: implement user display -->

314

## Only comments - violation

315

#end

316

```

317

318

**Recommended fix:**

319

```velocity

320

#foreach($item in $items)

321

<p>Item: $item</p>

322

#end

323

324

## Or remove the loop if not needed

325

```

326

327

#### Empty If Statement

328

329

Identifies if statements with empty bodies, indicating incomplete conditional logic.

330

331

```java { .api }

332

/**

333

* Rule that detects empty if statements.

334

* Empty if statements suggest incomplete implementation or unnecessary conditions.

335

* Location: net.sourceforge.pmd.lang.vm.rule.errorprone.EmptyIfStmtRule

336

*/

337

public class EmptyIfStmtRule extends AbstractVmRule {

338

// Implementation analyzes if statement bodies

339

// Reports violations when body contains no meaningful content

340

}

341

```

342

343

**What it detects:**

344

- If statements with completely empty bodies

345

- If statements containing only whitespace or comments

346

- Conditional logic that may be incomplete

347

348

**Example violations:**

349

```velocity

350

#if($user.isAdmin)

351

## Empty if body - violation

352

#end

353

354

#if($showSpecialContent)

355

<!-- Content will be added later -->

356

## Only comments - violation

357

#end

358

```

359

360

**Recommended fix:**

361

```velocity

362

#if($user.isAdmin)

363

<p>Admin panel access granted</p>

364

#end

365

366

## Or remove the condition if not needed

367

```

368

369

## Rule Configuration Examples

370

371

### PMD Ruleset Configuration

372

373

```xml

374

<?xml version="1.0"?>

375

<ruleset name="velocity-rules"

376

xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"

377

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

378

xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0

379

http://pmd.sourceforge.net/ruleset_2_0_0.xsd">

380

381

<description>Custom Velocity template rules</description>

382

383

<!-- Best Practices Rules -->

384

<rule ref="category/vm/bestpractices.xml/AvoidReassigningParameters"/>

385

<rule ref="category/vm/bestpractices.xml/UnusedMacroParameter"/>

386

387

<!-- Design Rules with Custom Configuration -->

388

<rule ref="category/vm/design.xml/ExcessiveTemplateLength">

389

<properties>

390

<property name="maxLines" value="300"/>

391

</properties>

392

</rule>

393

394

<rule ref="category/vm/design.xml/AvoidDeeplyNestedIfStmts">

395

<properties>

396

<property name="maxNesting" value="3"/>

397

</properties>

398

</rule>

399

400

<rule ref="category/vm/design.xml/CollapsibleIfStatements"/>

401

<rule ref="category/vm/design.xml/NoInlineJavaScript"/>

402

403

<!-- Error-Prone Rules -->

404

<rule ref="category/vm/errorprone.xml/EmptyIfStmt"/>

405

<rule ref="category/vm/errorprone.xml/EmptyForeachStmt"/>

406

</ruleset>

407

```

408

409

### Programmatic Rule Usage

410

411

```java

412

import net.sourceforge.pmd.PMD;

413

import net.sourceforge.pmd.PMDConfiguration;

414

import net.sourceforge.pmd.RuleSet;

415

import net.sourceforge.pmd.RuleSetFactory;

416

417

// Configure PMD for Velocity analysis

418

PMDConfiguration config = new PMDConfiguration();

419

config.setInputPaths("src/main/resources/templates");

420

config.setReportFormat("text");

421

422

// Load built-in Velocity rules

423

RuleSetFactory factory = new RuleSetFactory();

424

RuleSet ruleSet = factory.createRuleSet("category/vm/bestpractices.xml");

425

426

// Run analysis

427

PMD.runPMD(config);

428

```

429

430

### Custom Rule Integration

431

432

```java

433

import net.sourceforge.pmd.lang.vm.rule.AbstractVmRule;

434

435

// Custom rule extending built-in functionality

436

public class EnhancedUnusedParameterRule extends UnusedMacroParameterRule {

437

438

@Override

439

public Object visit(ASTReference node, Object data) {

440

// Call parent implementation

441

Object result = super.visit(node, data);

442

443

// Add custom analysis

444

analyzeReferencePattern(node, data);

445

446

return result;

447

}

448

449

private void analyzeReferencePattern(ASTReference node, Object data) {

450

// Custom pattern analysis

451

String refName = node.getRootString();

452

if (refName != null && refName.matches("^unused.*")) {

453

addViolation(data, node, "Reference suggests unused parameter: " + refName);

454

}

455

}

456

}

457

```

458

459

## Rule Suppression

460

461

### In-Template Suppression

462

463

```velocity

464

## Suppress specific rule for next directive

465

## NOPMD: AvoidReassigningParameters

466

#set($userName = "Modified")

467

468

## Suppress multiple rules

469

## NOPMD: EmptyIfStmt, UnusedMacroParameter

470

#if($condition)

471

#end

472

```

473

474

### External Suppression

475

476

```xml

477

<!-- PMD suppression file -->

478

<suppressions>

479

<suppress files="legacy-template.vm"

480

checks="ExcessiveTemplateLength"/>

481

<suppress files="generated-.*\.vm"

482

checks=".*"/>

483

</suppressions>

484

```