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

symbol-resolution.mddocs/

0

# Symbol Resolution and Type Analysis

1

2

JavaParser provides advanced symbol resolution capabilities for resolving references to their declarations and performing comprehensive type analysis. This enables sophisticated code analysis, refactoring tools, and IDE-like features.

3

4

## Capabilities

5

6

### Symbol Resolution Configuration

7

8

Enable symbol resolution by configuring a SymbolResolver in the ParserConfiguration.

9

10

```java { .api }

11

/**

12

* Interface for resolving symbols to their declarations

13

*/

14

public interface SymbolResolver {

15

16

/**

17

* Resolve a node to its declaration

18

* @param node Node to resolve

19

* @param resultClass Expected type of resolved declaration

20

* @return Resolved declaration

21

* @throws UnsolvedSymbolException if symbol cannot be resolved

22

*/

23

<T> T resolveDeclaration(Node node, Class<T> resultClass);

24

25

/**

26

* Resolve a reference expression to its declaration

27

* @param nameExpr Name expression to resolve

28

* @return Resolved value declaration

29

*/

30

ResolvedValueDeclaration resolveDeclaration(NameExpr nameExpr);

31

32

/**

33

* Resolve a method call to its declaration

34

* @param methodCallExpr Method call expression to resolve

35

* @return Resolved method declaration

36

*/

37

ResolvedMethodDeclaration resolveDeclaration(MethodCallExpr methodCallExpr);

38

39

/**

40

* Resolve a type to its declaration

41

* @param type Type to resolve

42

* @return Resolved type declaration

43

*/

44

ResolvedReferenceTypeDeclaration resolveDeclaration(ClassOrInterfaceType type);

45

}

46

47

/**

48

* Configure parser with symbol resolution

49

*/

50

public class ParserConfiguration {

51

52

/**

53

* Set symbol resolver for type analysis

54

* @param symbolResolver Symbol resolver implementation

55

* @return This configuration for chaining

56

*/

57

public ParserConfiguration setSymbolResolver(SymbolResolver symbolResolver);

58

}

59

```

60

61

**Usage Examples:**

62

63

```java

64

import com.github.javaparser.symbolsolver.JavaSymbolSolver;

65

import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;

66

import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;

67

import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;

68

69

// Configure symbol resolution

70

CombinedTypeSolver typeSolver = new CombinedTypeSolver();

71

typeSolver.add(new ReflectionTypeSolver()); // For JDK classes

72

typeSolver.add(new JavaParserTypeSolver(new File("src/main/java"))); // For project classes

73

74

JavaSymbolSolver symbolResolver = new JavaSymbolSolver(typeSolver);

75

ParserConfiguration config = new ParserConfiguration()

76

.setSymbolResolver(symbolResolver);

77

78

// Parse with symbol resolution enabled

79

JavaParser parser = new JavaParser(config);

80

CompilationUnit cu = parser.parse(code).getResult().get();

81

82

// Now you can resolve symbols

83

for (NameExpr nameExpr : cu.findAll(NameExpr.class)) {

84

try {

85

ResolvedValueDeclaration resolved = nameExpr.resolve();

86

System.out.println("Resolved: " + resolved.getName() + " -> " + resolved.getType());

87

} catch (UnsolvedSymbolException e) {

88

System.out.println("Could not resolve: " + nameExpr.getNameAsString());

89

}

90

}

91

```

92

93

### Type Solving

94

95

TypeSolver implementations provide the foundation for symbol resolution by locating type definitions.

96

97

```java { .api }

98

/**

99

* Interface for solving/locating type declarations

100

*/

101

public interface TypeSolver {

102

103

/**

104

* Try to solve a type by name

105

* @param name Fully qualified or simple type name

106

* @return SymbolReference to the type declaration

107

*/

108

SymbolReference<ResolvedReferenceTypeDeclaration> tryToSolveType(String name);

109

110

/**

111

* Get parent type solver if this is a chained solver

112

* @return Parent type solver or null

113

*/

114

TypeSolver getParent();

115

116

/**

117

* Set parent type solver for chaining

118

* @param parent Parent type solver

119

*/

120

void setParent(TypeSolver parent);

121

}

122

123

/**

124

* Combined type solver that chains multiple solvers

125

*/

126

public class CombinedTypeSolver implements TypeSolver {

127

128

/**

129

* Create empty combined solver

130

*/

131

public CombinedTypeSolver();

132

133

/**

134

* Create with initial solvers

135

* @param solvers Initial type solvers

136

*/

137

public CombinedTypeSolver(TypeSolver... solvers);

138

139

/**

140

* Add a type solver to the chain

141

* @param typeSolver Type solver to add

142

*/

143

public void add(TypeSolver typeSolver);

144

}

145

146

/**

147

* Reflection-based type solver for JDK and classpath classes

148

*/

149

public class ReflectionTypeSolver implements TypeSolver {

150

151

/**

152

* Create reflection solver for current JRE

153

*/

154

public ReflectionTypeSolver();

155

156

/**

157

* Create reflection solver with explicit classloader

158

* @param classLoader ClassLoader to use for type resolution

159

*/

160

public ReflectionTypeSolver(ClassLoader classLoader);

161

162

/**

163

* Create reflection solver with filtering

164

* @param exploreJDK true to include JDK classes

165

*/

166

public ReflectionTypeSolver(boolean exploreJDK);

167

}

168

169

/**

170

* JavaParser-based type solver for source code

171

*/

172

public class JavaParserTypeSolver implements TypeSolver {

173

174

/**

175

* Create solver for source directory

176

* @param srcDir Source root directory

177

*/

178

public JavaParserTypeSolver(File srcDir);

179

180

/**

181

* Create solver for source directory with parser configuration

182

* @param srcDir Source root directory

183

* @param parserConfiguration Parser configuration to use

184

*/

185

public JavaParserTypeSolver(File srcDir, ParserConfiguration parserConfiguration);

186

}

187

```

188

189

**Usage Examples:**

190

191

```java

192

// Set up comprehensive type resolution

193

CombinedTypeSolver typeSolver = new CombinedTypeSolver();

194

195

// Add JDK classes

196

typeSolver.add(new ReflectionTypeSolver());

197

198

// Add project source code

199

typeSolver.add(new JavaParserTypeSolver(new File("src/main/java")));

200

typeSolver.add(new JavaParserTypeSolver(new File("src/test/java")));

201

202

// Add JAR dependencies

203

typeSolver.add(new JarTypeSolver(new File("lib/dependency.jar")));

204

205

// Use in symbol resolver

206

JavaSymbolSolver symbolResolver = new JavaSymbolSolver(typeSolver);

207

```

208

209

### Resolved Declarations

210

211

Symbol resolution produces resolved declaration objects that provide detailed type information.

212

213

```java { .api }

214

/**

215

* Base interface for resolved declarations

216

*/

217

public interface ResolvedDeclaration {

218

219

/**

220

* Get declaration name

221

* @return Name of the declaration

222

*/

223

String getName();

224

225

/**

226

* Check if this is a field declaration

227

* @return true if this is a field

228

*/

229

default boolean isField() { return false; }

230

231

/**

232

* Check if this is a parameter declaration

233

* @return true if this is a parameter

234

*/

235

default boolean isParameter() { return false; }

236

237

/**

238

* Check if this is a variable declaration

239

* @return true if this is a variable

240

*/

241

default boolean isVariable() { return false; }

242

243

/**

244

* Check if this is a method declaration

245

* @return true if this is a method

246

*/

247

default boolean isMethod() { return false; }

248

249

/**

250

* Check if this is a type declaration

251

* @return true if this is a type

252

*/

253

default boolean isType() { return false; }

254

}

255

256

/**

257

* Resolved value declaration (fields, parameters, variables)

258

*/

259

public interface ResolvedValueDeclaration extends ResolvedDeclaration {

260

261

/**

262

* Get the type of this value

263

* @return Resolved type

264

*/

265

ResolvedType getType();

266

}

267

268

/**

269

* Resolved method declaration

270

*/

271

public interface ResolvedMethodDeclaration extends ResolvedDeclaration {

272

273

/**

274

* Get return type

275

* @return Resolved return type

276

*/

277

ResolvedType getReturnType();

278

279

/**

280

* Get method parameters

281

* @return List of resolved parameters

282

*/

283

List<ResolvedParameterDeclaration> getParams();

284

285

/**

286

* Get number of parameters

287

* @return Parameter count

288

*/

289

int getNumberOfParams();

290

291

/**

292

* Get parameter at index

293

* @param i Parameter index

294

* @return Resolved parameter declaration

295

*/

296

ResolvedParameterDeclaration getParam(int i);

297

298

/**

299

* Check if method is static

300

* @return true if static

301

*/

302

boolean isStatic();

303

304

/**

305

* Get declaring type

306

* @return Type that declares this method

307

*/

308

ResolvedReferenceTypeDeclaration declaringType();

309

}

310

311

/**

312

* Resolved type declaration (classes, interfaces, enums)

313

*/

314

public interface ResolvedTypeDeclaration extends ResolvedDeclaration {

315

316

/**

317

* Get qualified name

318

* @return Fully qualified name

319

*/

320

String getQualifiedName();

321

322

/**

323

* Get package name

324

* @return Package name

325

*/

326

String getPackageName();

327

328

/**

329

* Get class name without package

330

* @return Simple class name

331

*/

332

String getClassName();

333

334

/**

335

* Check if this is a class

336

* @return true if this is a class

337

*/

338

default boolean isClass() { return false; }

339

340

/**

341

* Check if this is an interface

342

* @return true if this is an interface

343

*/

344

default boolean isInterface() { return false; }

345

346

/**

347

* Check if this is an enum

348

* @return true if this is an enum

349

*/

350

default boolean isEnum() { return false; }

351

}

352

```

353

354

**Usage Examples:**

355

356

```java

357

// Resolve method calls

358

for (MethodCallExpr methodCall : cu.findAll(MethodCallExpr.class)) {

359

try {

360

ResolvedMethodDeclaration resolved = methodCall.resolve();

361

System.out.println("Method: " + resolved.getQualifiedSignature());

362

System.out.println("Return type: " + resolved.getReturnType());

363

System.out.println("Declaring class: " + resolved.declaringType().getQualifiedName());

364

365

for (int i = 0; i < resolved.getNumberOfParams(); i++) {

366

ResolvedParameterDeclaration param = resolved.getParam(i);

367

System.out.println("Param " + i + ": " + param.getType());

368

}

369

} catch (UnsolvedSymbolException e) {

370

System.out.println("Could not resolve method: " + methodCall);

371

}

372

}

373

374

// Resolve field access

375

for (FieldAccessExpr fieldAccess : cu.findAll(FieldAccessExpr.class)) {

376

try {

377

ResolvedValueDeclaration resolved = fieldAccess.resolve();

378

System.out.println("Field: " + resolved.getName());

379

System.out.println("Type: " + resolved.getType());

380

} catch (UnsolvedSymbolException e) {

381

System.out.println("Could not resolve field: " + fieldAccess);

382

}

383

}

384

```

385

386

### Type Analysis

387

388

Analyze and work with resolved types for comprehensive type information.

389

390

```java { .api }

391

/**

392

* Base interface for resolved types

393

*/

394

public interface ResolvedType {

395

396

/**

397

* Get type description

398

* @return Human-readable type description

399

*/

400

String describe();

401

402

/**

403

* Check if this is a reference type

404

* @return true if reference type

405

*/

406

boolean isReferenceType();

407

408

/**

409

* Check if this is a primitive type

410

* @return true if primitive type

411

*/

412

boolean isPrimitive();

413

414

/**

415

* Check if this is an array type

416

* @return true if array type

417

*/

418

boolean isArray();

419

420

/**

421

* Check if this is assignable to another type

422

* @param other Target type

423

* @return true if assignable

424

*/

425

boolean isAssignableBy(ResolvedType other);

426

}

427

428

/**

429

* Resolved reference type (classes, interfaces)

430

*/

431

public interface ResolvedReferenceType extends ResolvedType {

432

433

/**

434

* Get type declaration

435

* @return Type declaration

436

*/

437

ResolvedReferenceTypeDeclaration getTypeDeclaration();

438

439

/**

440

* Get type parameters

441

* @return List of type parameters

442

*/

443

List<ResolvedType> getTypeParametersMap();

444

445

/**

446

* Check if this type is assignable to another

447

* @param other Target type

448

* @return true if assignable

449

*/

450

boolean isAssignableBy(ResolvedType other);

451

}

452

453

/**

454

* Resolved primitive type

455

*/

456

public interface ResolvedPrimitiveType extends ResolvedType {

457

458

/**

459

* Get primitive type kind

460

* @return Primitive type

461

*/

462

ResolvedPrimitiveType.Primitive getType();

463

464

public enum Primitive {

465

BOOLEAN, CHAR, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE

466

}

467

}

468

```

469

470

**Usage Examples:**

471

472

```java

473

// Analyze expression types

474

for (Expression expr : cu.findAll(Expression.class)) {

475

try {

476

ResolvedType type = expr.calculateResolvedType();

477

System.out.println("Expression: " + expr);

478

System.out.println("Type: " + type.describe());

479

480

if (type.isPrimitive()) {

481

ResolvedPrimitiveType primitive = type.asPrimitive();

482

System.out.println("Primitive: " + primitive.getType());

483

} else if (type.isReferenceType()) {

484

ResolvedReferenceType refType = type.asReferenceType();

485

System.out.println("Class: " + refType.getQualifiedName());

486

}

487

} catch (UnsolvedSymbolException e) {

488

System.out.println("Could not resolve type for: " + expr);

489

}

490

}

491

492

// Check type compatibility

493

ResolvedType stringType = ...; // resolved String type

494

ResolvedType objectType = ...; // resolved Object type

495

496

boolean assignable = objectType.isAssignableBy(stringType); // true

497

```

498

499

### Context and Navigation

500

501

Navigate the symbol resolution context and access scope information.

502

503

```java { .api }

504

/**

505

* Resolution context for symbol lookup

506

*/

507

public class Context {

508

509

/**

510

* Solve symbol in this context

511

* @param name Symbol name to resolve

512

* @return Symbol reference

513

*/

514

public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name);

515

516

/**

517

* Solve method in this context

518

* @param name Method name

519

* @param argumentTypes Argument types

520

* @return Method reference

521

*/

522

public SymbolReference<ResolvedMethodDeclaration> solveMethod(

523

String name, List<ResolvedType> argumentTypes);

524

525

/**

526

* Get parent context

527

* @return Parent context or null

528

*/

529

public Context getParent();

530

}

531

532

/**

533

* Utility for navigating symbol resolution

534

*/

535

public class Navigator {

536

537

/**

538

* Get local variables in scope at a node

539

* @param node AST node

540

* @return List of local variables

541

*/

542

public static List<ResolvedValueDeclaration> getLocalVariables(Node node);

543

544

/**

545

* Find method declarations in a type

546

* @param type Type to search

547

* @param name Method name

548

* @return List of matching methods

549

*/

550

public static List<ResolvedMethodDeclaration> findMethods(

551

ResolvedReferenceTypeDeclaration type, String name);

552

}

553

```

554

555

## Error Handling

556

557

```java { .api }

558

/**

559

* Exception thrown when symbol cannot be resolved

560

*/

561

public class UnsolvedSymbolException extends RuntimeException {

562

563

/**

564

* Get the unresolved symbol name

565

* @return Symbol name

566

*/

567

public String getName();

568

569

/**

570

* Get context where resolution failed

571

* @return Resolution context

572

*/

573

public Context getContext();

574

}

575

576

/**

577

* Exception for method resolution ambiguity

578

*/

579

public class MethodAmbiguityException extends RuntimeException {

580

581

/**

582

* Get candidate methods

583

* @return List of candidate methods

584

*/

585

public List<ResolvedMethodDeclaration> getCandidates();

586

}

587

```