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
```