or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-navigation.mdconfiguration.mdindex.mdparsing.mdprinting.mdserialization.mdsymbol-resolution.mdvisitors.md

visitors.mddocs/

0

# Visitor Pattern

1

2

JavaParser implements the visitor pattern to provide flexible and efficient traversal of AST nodes. The visitor pattern allows you to define operations on AST nodes without modifying the node classes themselves.

3

4

## Capabilities

5

6

### Generic Visitor Interface

7

8

The GenericVisitor interface allows visitors that return values of type R and accept arguments of type A.

9

10

```java { .api }

11

/**

12

* Generic visitor interface for AST traversal with return values

13

* @param <R> Return type of visit methods

14

* @param <A> Argument type passed to visit methods

15

*/

16

public interface GenericVisitor<R, A> {

17

18

// Compilation unit and imports

19

R visit(CompilationUnit n, A arg);

20

R visit(PackageDeclaration n, A arg);

21

R visit(ImportDeclaration n, A arg);

22

23

// Type declarations

24

R visit(ClassOrInterfaceDeclaration n, A arg);

25

R visit(EnumDeclaration n, A arg);

26

R visit(AnnotationDeclaration n, A arg);

27

R visit(RecordDeclaration n, A arg);

28

29

// Members

30

R visit(MethodDeclaration n, A arg);

31

R visit(ConstructorDeclaration n, A arg);

32

R visit(FieldDeclaration n, A arg);

33

R visit(EnumConstantDeclaration n, A arg);

34

R visit(AnnotationMemberDeclaration n, A arg);

35

R visit(InitializerDeclaration n, A arg);

36

R visit(Parameter n, A arg);

37

38

// Expressions

39

R visit(ArrayAccessExpr n, A arg);

40

R visit(ArrayCreationExpr n, A arg);

41

R visit(ArrayInitializerExpr n, A arg);

42

R visit(AssignExpr n, A arg);

43

R visit(BinaryExpr n, A arg);

44

R visit(BooleanLiteralExpr n, A arg);

45

R visit(CastExpr n, A arg);

46

R visit(CharLiteralExpr n, A arg);

47

R visit(ClassExpr n, A arg);

48

R visit(ConditionalExpr n, A arg);

49

R visit(DoubleLiteralExpr n, A arg);

50

R visit(EnclosedExpr n, A arg);

51

R visit(FieldAccessExpr n, A arg);

52

R visit(InstanceOfExpr n, A arg);

53

R visit(IntegerLiteralExpr n, A arg);

54

R visit(LambdaExpr n, A arg);

55

R visit(LongLiteralExpr n, A arg);

56

R visit(MethodCallExpr n, A arg);

57

R visit(MethodReferenceExpr n, A arg);

58

R visit(NameExpr n, A arg);

59

R visit(NullLiteralExpr n, A arg);

60

R visit(ObjectCreationExpr n, A arg);

61

R visit(StringLiteralExpr n, A arg);

62

R visit(SuperExpr n, A arg);

63

R visit(ThisExpr n, A arg);

64

R visit(UnaryExpr n, A arg);

65

R visit(VariableDeclarationExpr n, A arg);

66

67

// Statements

68

R visit(AssertStmt n, A arg);

69

R visit(BlockStmt n, A arg);

70

R visit(BreakStmt n, A arg);

71

R visit(ContinueStmt n, A arg);

72

R visit(DoStmt n, A arg);

73

R visit(ExpressionStmt n, A arg);

74

R visit(ForEachStmt n, A arg);

75

R visit(ForStmt n, A arg);

76

R visit(IfStmt n, A arg);

77

R visit(LabeledStmt n, A arg);

78

R visit(ReturnStmt n, A arg);

79

R visit(SwitchStmt n, A arg);

80

R visit(SynchronizedStmt n, A arg);

81

R visit(ThrowStmt n, A arg);

82

R visit(TryStmt n, A arg);

83

R visit(WhileStmt n, A arg);

84

85

// Types

86

R visit(ArrayType n, A arg);

87

R visit(ClassOrInterfaceType n, A arg);

88

R visit(IntersectionType n, A arg);

89

R visit(PrimitiveType n, A arg);

90

R visit(TypeParameter n, A arg);

91

R visit(UnionType n, A arg);

92

R visit(VoidType n, A arg);

93

R visit(WildcardType n, A arg);

94

95

// Modern Java language features (Java 9+)

96

R visit(ModuleDeclaration n, A arg);

97

R visit(ModuleExportsDirective n, A arg);

98

R visit(ModuleOpensDirective n, A arg);

99

R visit(ModuleProvidesDirective n, A arg);

100

R visit(ModuleRequiresDirective n, A arg);

101

R visit(ModuleUsesDirective n, A arg);

102

103

// Records (Java 14+)

104

R visit(RecordDeclaration n, A arg);

105

R visit(CompactConstructorDeclaration n, A arg);

106

107

// Pattern matching and newer expressions (Java 14+)

108

R visit(SwitchExpr n, A arg);

109

R visit(YieldStmt n, A arg);

110

R visit(TextBlockLiteralExpr n, A arg);

111

R visit(TypePatternExpr n, A arg);

112

R visit(RecordPatternExpr n, A arg);

113

114

// Additional statement types

115

R visit(LocalClassDeclarationStmt n, A arg);

116

R visit(LocalRecordDeclarationStmt n, A arg);

117

R visit(SwitchEntry n, A arg);

118

R visit(UnparsableStmt n, A arg);

119

120

// Additional type and modifier support

121

R visit(VarType n, A arg);

122

R visit(ReceiverParameter n, A arg);

123

R visit(Modifier n, A arg);

124

R visit(ArrayCreationLevel n, A arg)

125

}

126

```

127

128

### Void Visitor Interface

129

130

The VoidVisitor interface is for visitors that perform side effects without returning values.

131

132

```java { .api }

133

/**

134

* Void visitor interface for AST traversal with side effects only

135

* @param <A> Argument type passed to visit methods

136

*/

137

public interface VoidVisitor<A> {

138

139

// Same visit method signatures as GenericVisitor but returning void

140

void visit(CompilationUnit n, A arg);

141

void visit(ClassOrInterfaceDeclaration n, A arg);

142

void visit(MethodDeclaration n, A arg);

143

void visit(FieldDeclaration n, A arg);

144

// ... all other visit methods returning void

145

}

146

```

147

148

### Visitor Adapter Classes

149

150

JavaParser provides adapter classes that implement default behavior for all visit methods, allowing you to override only the methods you need.

151

152

```java { .api }

153

/**

154

* Adapter providing default implementations for GenericVisitor

155

* @param <R> Return type

156

* @param <A> Argument type

157

*/

158

public abstract class GenericVisitorAdapter<R, A> implements GenericVisitor<R, A> {

159

160

/**

161

* Default visit behavior - visits all child nodes and returns null

162

* Override specific visit methods to provide custom behavior

163

*/

164

// Default implementations for all visit methods...

165

}

166

167

/**

168

* Adapter providing default implementations for VoidVisitor

169

* @param <A> Argument type

170

*/

171

public abstract class VoidVisitorAdapter<A> implements VoidVisitor<A> {

172

173

/**

174

* Default visit behavior - visits all child nodes

175

* Override specific visit methods to provide custom behavior

176

*/

177

// Default implementations for all visit methods...

178

}

179

```

180

181

**Usage Examples:**

182

183

```java

184

import com.github.javaparser.ast.visitor.VoidVisitorAdapter;

185

import com.github.javaparser.ast.body.MethodDeclaration;

186

import com.github.javaparser.ast.body.FieldDeclaration;

187

188

// Count methods and fields

189

CompilationUnit cu = StaticJavaParser.parse(code);

190

191

cu.accept(new VoidVisitorAdapter<Void>() {

192

private int methodCount = 0;

193

private int fieldCount = 0;

194

195

@Override

196

public void visit(MethodDeclaration n, Void arg) {

197

methodCount++;

198

System.out.println("Found method: " + n.getNameAsString());

199

super.visit(n, arg); // Continue traversal

200

}

201

202

@Override

203

public void visit(FieldDeclaration n, Void arg) {

204

fieldCount++;

205

n.getVariables().forEach(var ->

206

System.out.println("Found field: " + var.getNameAsString()));

207

super.visit(n, arg);

208

}

209

}, null);

210

```

211

212

### Specialized Visitor Implementations

213

214

JavaParser includes several built-in visitor implementations for common tasks.

215

216

```java { .api }

217

/**

218

* Visitor for modifying AST nodes during traversal

219

* @param <A> Argument type

220

*/

221

public class ModifierVisitor<A> implements GenericVisitor<Visitable, A> {

222

223

/**

224

* Visit and potentially modify nodes

225

* Return the same node to keep it, return a different node to replace it,

226

* return null to remove it

227

*/

228

// Implementation allows modification during traversal

229

}

230

231

/**

232

* Visitor for deep cloning AST nodes

233

*/

234

public class CloneVisitor implements GenericVisitor<Visitable, Object> {

235

236

/**

237

* Creates deep copies of visited nodes

238

* @param n Node to clone

239

* @param arg Clone context

240

* @return Cloned node

241

*/

242

// Implementation for deep cloning

243

}

244

245

/**

246

* Visitor for comparing AST nodes for equality

247

*/

248

public class EqualsVisitor implements GenericVisitor<Boolean, Visitable> {

249

250

/**

251

* Compare two AST nodes for structural equality

252

* @param n First node

253

* @param other Second node to compare against

254

* @return true if nodes are structurally equal

255

*/

256

// Implementation for equality comparison

257

}

258

259

/**

260

* Visitor for computing hash codes of AST nodes

261

*/

262

public class HashCodeVisitor implements GenericVisitor<Integer, Void> {

263

264

/**

265

* Compute hash code for AST node

266

* @param n Node to hash

267

* @param arg Not used

268

* @return Hash code of the node

269

*/

270

// Implementation for hash code computation

271

}

272

```

273

274

**Usage Examples:**

275

276

```java

277

// Clone an AST node

278

Node original = cu.findFirst(ClassOrInterfaceDeclaration.class).get();

279

Node cloned = original.accept(new CloneVisitor(), null);

280

281

// Compare two nodes for equality

282

boolean equal = original.accept(new EqualsVisitor(), cloned);

283

284

// Modify AST during traversal

285

cu.accept(new ModifierVisitor<Void>() {

286

@Override

287

public Visitable visit(MethodDeclaration n, Void arg) {

288

// Make all methods public

289

n.setPublic(true);

290

return super.visit(n, arg);

291

}

292

293

@Override

294

public Visitable visit(FieldDeclaration n, Void arg) {

295

// Remove private fields

296

if (n.isPrivate()) {

297

return null; // Remove this node

298

}

299

return super.visit(n, arg);

300

}

301

}, null);

302

```

303

304

### Custom Visitor Development

305

306

Create custom visitors by extending the adapter classes and overriding specific visit methods.

307

308

```java { .api }

309

/**

310

* Example: Collect all method names in a class

311

*/

312

public class MethodNameCollector extends VoidVisitorAdapter<List<String>> {

313

314

@Override

315

public void visit(MethodDeclaration n, List<String> collector) {

316

collector.add(n.getNameAsString());

317

super.visit(n, collector); // Continue to child nodes

318

}

319

}

320

321

/**

322

* Example: Calculate complexity metrics

323

*/

324

public class ComplexityCalculator extends GenericVisitorAdapter<Integer, Void> {

325

326

@Override

327

public Integer visit(IfStmt n, Void arg) {

328

int complexity = 1; // Base complexity for if statement

329

complexity += visit(n.getThenStmt(), arg);

330

if (n.getElseStmt().isPresent()) {

331

complexity += visit(n.getElseStmt().get(), arg);

332

}

333

return complexity;

334

}

335

336

@Override

337

public Integer visit(ForStmt n, Void arg) {

338

int complexity = 1; // Base complexity for loop

339

complexity += visit(n.getBody(), arg);

340

return complexity;

341

}

342

343

// Override other control flow visit methods...

344

}

345

```

346

347

**Usage Examples:**

348

349

```java

350

// Use custom visitors

351

CompilationUnit cu = StaticJavaParser.parse(code);

352

353

// Collect method names

354

List<String> methodNames = new ArrayList<>();

355

cu.accept(new MethodNameCollector(), methodNames);

356

System.out.println("Methods found: " + methodNames);

357

358

// Calculate complexity

359

Integer complexity = cu.accept(new ComplexityCalculator(), null);

360

System.out.println("Cyclomatic complexity: " + complexity);

361

```

362

363

### Visitor with Context

364

365

Pass context information through visitor traversal using the argument parameter.

366

367

```java { .api }

368

/**

369

* Context class for tracking traversal state

370

*/

371

public class VisitorContext {

372

private String currentClassName;

373

private int depth;

374

private Map<String, Object> properties;

375

376

// Context management methods

377

public void enterClass(String name) { this.currentClassName = name; }

378

public void exitClass() { this.currentClassName = null; }

379

public void incrementDepth() { depth++; }

380

public void decrementDepth() { depth--; }

381

}

382

```

383

384

**Usage Examples:**

385

386

```java

387

// Visitor with context tracking

388

cu.accept(new VoidVisitorAdapter<VisitorContext>() {

389

@Override

390

public void visit(ClassOrInterfaceDeclaration n, VisitorContext ctx) {

391

ctx.enterClass(n.getNameAsString());

392

System.out.println("Entering class: " + n.getNameAsString() +

393

" at depth " + ctx.getDepth());

394

395

super.visit(n, ctx); // Visit children

396

397

ctx.exitClass();

398

System.out.println("Exiting class: " + n.getNameAsString());

399

}

400

401

@Override

402

public void visit(MethodDeclaration n, VisitorContext ctx) {

403

System.out.println("Method " + n.getNameAsString() +

404

" in class " + ctx.getCurrentClassName());

405

super.visit(n, ctx);

406

}

407

}, new VisitorContext());

408

```

409

410

## Visitor Pattern Benefits

411

412

The visitor pattern in JavaParser provides several advantages:

413

414

- **Separation of Concerns**: Analysis logic is separate from AST node structure

415

- **Extensibility**: Add new operations without modifying AST classes

416

- **Type Safety**: Compile-time checking of visitor method signatures

417

- **Performance**: Efficient traversal with minimal overhead

418

- **Flexibility**: Support for both value-returning and side-effect visitors

419

- **Composition**: Easy to combine multiple visitor behaviors