Skip to content

Commit e5cf4a9

Browse files
Merge pull request #2 from bldl/use-symbol-solver
Migrate to using javaparsers symbol solver
2 parents 0aaa8dd + a8be75f commit e5cf4a9

File tree

3 files changed

+169
-194
lines changed

3 files changed

+169
-194
lines changed

src/main/java/io/github/bldl/astParsing/AstManipulator.java

Lines changed: 23 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
import com.github.javaparser.ast.type.TypeParameter;
1212
import com.github.javaparser.ast.visitor.ModifierVisitor;
1313
import com.github.javaparser.ast.visitor.Visitable;
14+
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
15+
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
16+
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
17+
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
1418
import com.github.javaparser.utils.CodeGenerationUtils;
1519
import com.github.javaparser.utils.SourceRoot;
1620
import io.github.bldl.annotationProcessing.annotations.MyVariance;
@@ -46,9 +50,14 @@ public class AstManipulator {
4650
public AstManipulator(Messager messager, String sourceFolder) {
4751
this.messager = messager;
4852
this.sourceFolder = sourceFolder;
53+
CombinedTypeSolver typeSolver = new CombinedTypeSolver();
54+
typeSolver.add(new ReflectionTypeSolver());
55+
typeSolver.add(new JavaParserTypeSolver(Paths.get("src/main/java")));
56+
JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver);
4957
sourceRoot = new SourceRoot(
5058
CodeGenerationUtils.mavenModuleRoot(AstManipulator.class).resolve(sourceFolder));
51-
classHierarchy = computeClassHierarchy();
59+
sourceRoot.getParserConfiguration().setSymbolResolver(symbolSolver);
60+
classHierarchy = (new ClassHierarchyComputer(sourceRoot, messager, sourceFolder)).computeClassHierarchy();
5261
}
5362

5463
public void applyChanges() {
@@ -110,13 +119,6 @@ public Visitable visit(TypeParameter n, Void arg) {
110119
}, null);
111120
}
112121

113-
public ClassHierarchyGraph<String> computeClassHierarchy() {
114-
ClassHierarchyGraph<String> g = new ClassHierarchyGraph<>();
115-
g.addVertex("Object");
116-
computeClassHierarchyRec(g, Paths.get(sourceFolder).toFile(), "");
117-
return g;
118-
}
119-
120122
private ClassData computeClassData(String cls, String packageName, Map<String, MyVariance> mp) {
121123
CompilationUnit cu = sourceRoot.parse(packageName, cls);
122124
Map<String, ParamData> indexAndBound = new HashMap<>();
@@ -151,9 +153,7 @@ private void changeAST(File dir, ClassData classData, Map<String, MethodData> me
151153
Set<Pair<String, ClassOrInterfaceType>> varsToWatch = new HashSet<>();
152154
cu.accept(new VariableCollector(classData), varsToWatch);
153155
cu.accept(
154-
new SubtypingCheckVisitor(collectMethodParams(cu, classData), collectMethodTypes(cu), messager,
155-
varsToWatch, classData,
156-
classHierarchy),
156+
new SubtypingCheckVisitor(collectMethodParams(cu, classData), messager, classData, classHierarchy),
157157
null);
158158
cu.accept(new TypeEraserVisitor(classData), null);
159159
for (Pair<String, ClassOrInterfaceType> var : varsToWatch) {
@@ -163,35 +163,7 @@ private void changeAST(File dir, ClassData classData, Map<String, MethodData> me
163163
}
164164
}
165165

166-
private void computeClassHierarchyRec(ClassHierarchyGraph<String> g, File dir, String packageName) {
167-
for (File file : dir.listFiles()) {
168-
String fileName = file.getName();
169-
if (file.isDirectory()) {
170-
if (!fileName.equals(OUTPUT_NAME))
171-
computeClassHierarchyRec(g, file, appendPackageDeclaration(packageName, fileName));
172-
continue;
173-
}
174-
if (!isJavaFile(file))
175-
continue;
176-
177-
CompilationUnit cu = sourceRoot.parse(packageName, fileName);
178-
179-
cu.findAll(ClassOrInterfaceDeclaration.class).forEach(cls -> {
180-
NodeList<ClassOrInterfaceType> supertypes = cls.getExtendedTypes();
181-
supertypes.addAll(cls.getImplementedTypes());
182-
g.addVertex(cls.getNameAsString());
183-
for (ClassOrInterfaceType supertype : supertypes) {
184-
if (!g.containsVertex(supertype.getNameAsString()))
185-
g.addVertex(supertype.getNameAsString());
186-
g.addEdge(supertype.getNameAsString(), cls.getNameAsString());
187-
}
188-
if (supertypes.isEmpty())
189-
g.addEdge("Object", cls.getNameAsString());
190-
});
191-
}
192-
}
193-
194-
private boolean isJavaFile(File file) {
166+
public static boolean isJavaFile(File file) {
195167
return file.getName().endsWith(".java");
196168
}
197169

@@ -200,38 +172,27 @@ private void changePackageDeclaration(CompilationUnit cu) {
200172
cu.setPackageDeclaration(new PackageDeclaration(new Name(newPackageName)));
201173
}
202174

203-
private String appendPackageDeclaration(String existing, String toAppend) {
175+
public static String appendPackageDeclaration(String existing, String toAppend) {
204176
if (existing.equals(""))
205177
return toAppend;
206178
return existing + "." + toAppend;
207179
}
208180

209181
private Map<String, Map<Integer, Type>> collectMethodParams(CompilationUnit cu, ClassData classData) {
210-
Map<String, Map<Integer, Type>> mp = new HashMap<>();
182+
Map<String, Map<Integer, Type>> methodParams = new HashMap<>();
211183
cu.findAll(MethodDeclaration.class).forEach(dec -> {
184+
String methodName = dec.getNameAsString();
185+
if (methodParams.containsKey(methodName)) {
186+
messager.printMessage(Kind.ERROR, "Duplicate methods inside a class. Can't handle polymorphism.");
187+
return;
188+
}
189+
methodParams.put(methodName, new HashMap<>());
212190
NodeList<Parameter> params = dec.getParameters();
213191
for (int i = 0; i < params.size(); ++i) {
214-
Parameter param = params.get(i);
215-
if (!(param.getType() instanceof ClassOrInterfaceType))
216-
continue;
217-
ClassOrInterfaceType type = ((ClassOrInterfaceType) param.getType());
218-
String methodName = dec.getNameAsString();
219-
if (type.getNameAsString().equals(classData.className())) {
220-
mp.putIfAbsent(methodName, new HashMap<>());
221-
mp.get(methodName).put(i,
222-
type);
223-
}
192+
Type type = params.get(i).getType();
193+
methodParams.get(methodName).put(i, type);
224194
}
225195
});
226-
return mp;
227-
}
228-
229-
private Map<String, Type> collectMethodTypes(CompilationUnit cu) {
230-
Map<String, Type> mp = new HashMap<>();
231-
cu.findAll(MethodDeclaration.class).forEach(dec -> {
232-
String methodName = dec.getNameAsString();
233-
mp.put(methodName, dec.getType());
234-
});
235-
return mp;
196+
return methodParams;
236197
}
237198
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package io.github.bldl.astParsing;
2+
3+
import java.io.File;
4+
import java.nio.file.Paths;
5+
6+
import javax.annotation.processing.Messager;
7+
8+
import com.github.javaparser.ast.CompilationUnit;
9+
import com.github.javaparser.ast.NodeList;
10+
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
11+
import com.github.javaparser.ast.body.EnumDeclaration;
12+
import com.github.javaparser.ast.body.RecordDeclaration;
13+
import com.github.javaparser.ast.body.TypeDeclaration;
14+
import com.github.javaparser.ast.type.ClassOrInterfaceType;
15+
import com.github.javaparser.utils.SourceRoot;
16+
17+
import io.github.bldl.graph.ClassHierarchyGraph;
18+
19+
public class ClassHierarchyComputer {
20+
21+
private SourceRoot sourceRoot;
22+
private Messager messager;
23+
private String sourceFolder;
24+
25+
public ClassHierarchyComputer(SourceRoot sourceRoot, Messager messager, String sourceFolder) {
26+
this.sourceRoot = sourceRoot;
27+
this.messager = messager;
28+
this.sourceFolder = sourceFolder;
29+
}
30+
31+
public ClassHierarchyGraph<String> computeClassHierarchy() {
32+
ClassHierarchyGraph<String> g = new ClassHierarchyGraph<>();
33+
g.addVertex("Object");
34+
computeClassHierarchyRec(g, Paths.get(sourceFolder).toFile(), "");
35+
return g;
36+
}
37+
38+
private void computeClassHierarchyRec(ClassHierarchyGraph<String> g, File dir, String packageName) {
39+
for (File file : dir.listFiles()) {
40+
String fileName = file.getName();
41+
if (file.isDirectory()) {
42+
if (!fileName.equals(AstManipulator.OUTPUT_NAME))
43+
computeClassHierarchyRec(g, file, AstManipulator.appendPackageDeclaration(packageName, fileName));
44+
continue;
45+
}
46+
if (!AstManipulator.isJavaFile(file))
47+
continue;
48+
49+
CompilationUnit cu = sourceRoot.parse(packageName, fileName);
50+
51+
cu.findAll(RecordDeclaration.class).forEach(record -> {
52+
NodeList<ClassOrInterfaceType> supertypes = record.getImplementedTypes();
53+
handleDeclaration(packageName, g, supertypes, record);
54+
});
55+
56+
cu.findAll(EnumDeclaration.class).forEach(enm -> {
57+
NodeList<ClassOrInterfaceType> supertypes = enm.getImplementedTypes();
58+
handleDeclaration(packageName, g, supertypes, enm);
59+
});
60+
61+
cu.findAll(ClassOrInterfaceDeclaration.class).forEach(cls -> {
62+
NodeList<ClassOrInterfaceType> supertypes = cls.getExtendedTypes();
63+
supertypes.addAll(cls.getImplementedTypes());
64+
handleDeclaration(packageName, g, supertypes, cls);
65+
});
66+
}
67+
}
68+
69+
private void handleDeclaration(String packageName, ClassHierarchyGraph<String> g,
70+
NodeList<ClassOrInterfaceType> supertypes,
71+
TypeDeclaration<?> declaration) {
72+
g.addVertex(getQualifiedName(packageName, declaration.getNameAsString()));
73+
for (ClassOrInterfaceType supertype : supertypes) {
74+
if (!g.containsVertex(supertype.getNameAsString()))
75+
g.addVertex(supertype.getNameAsString());
76+
g.addEdge(supertype.getNameAsString(), declaration.getNameAsString());
77+
}
78+
if (supertypes.isEmpty())
79+
g.addEdge("Object", declaration.getNameAsString());
80+
}
81+
82+
private String getQualifiedName(String packageName, String typeName) {
83+
return packageName + "." + typeName;
84+
}
85+
}

0 commit comments

Comments
 (0)