1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.themis.xanalysis.solver;
18
19 import com.github.javaparser.ast.Node;
20 import io.github.tonywasher.joceanus.themis.xanalysis.parser.base.ThemisXAnalysisInstance;
21 import io.github.tonywasher.joceanus.themis.xanalysis.parser.base.ThemisXAnalysisInstance.ThemisXAnalysisClassInstance;
22 import io.github.tonywasher.joceanus.themis.xanalysis.parser.base.ThemisXAnalysisInstance.ThemisXAnalysisNodeInstance;
23 import io.github.tonywasher.joceanus.themis.xanalysis.parser.node.ThemisXAnalysisNode;
24 import io.github.tonywasher.joceanus.themis.xanalysis.parser.node.ThemisXAnalysisNodeImport;
25 import io.github.tonywasher.joceanus.themis.xanalysis.parser.node.ThemisXAnalysisNodeName;
26 import io.github.tonywasher.joceanus.themis.xanalysis.parser.type.ThemisXAnalysisType;
27 import io.github.tonywasher.joceanus.themis.xanalysis.parser.type.ThemisXAnalysisTypeClassInterface;
28 import io.github.tonywasher.joceanus.themis.xanalysis.solver.proj.ThemisXAnalysisSolverClass;
29 import io.github.tonywasher.joceanus.themis.xanalysis.solver.proj.ThemisXAnalysisSolverFile;
30 import io.github.tonywasher.joceanus.themis.xanalysis.solver.proj.ThemisXAnalysisSolverModule;
31 import io.github.tonywasher.joceanus.themis.xanalysis.solver.proj.ThemisXAnalysisSolverPackage;
32 import io.github.tonywasher.joceanus.themis.xanalysis.solver.proj.ThemisXAnalysisSolverProject;
33 import io.github.tonywasher.joceanus.themis.xanalysis.solver.reflect.ThemisXAnalysisReflectExternal;
34
35 import java.util.ArrayList;
36 import java.util.LinkedHashMap;
37 import java.util.List;
38 import java.util.Map;
39
40
41
42
43 public class ThemisXAnalysisSolverProjectState {
44
45
46
47 private final Map<String, ThemisXAnalysisReflectExternal> theJavaLang;
48
49
50
51
52 private final Map<String, ThemisXAnalysisSolverClass> theProjectClasses;
53
54
55
56
57 private final Map<String, ThemisXAnalysisReflectExternal> theExternalClasses;
58
59
60
61
62 private final Map<String, ThemisXAnalysisClassInstance> theKnownClasses;
63
64
65
66
67 private final List<ThemisXAnalysisSolverClass> theReferenced;
68
69
70
71
72
73
74 ThemisXAnalysisSolverProjectState(final ThemisXAnalysisSolverProject pProject) {
75
76 theJavaLang = ThemisXAnalysisReflectExternal.getJavaLangMap();
77
78
79 theProjectClasses = new LinkedHashMap<>();
80 buildProjectClassMap(pProject);
81
82
83 theExternalClasses = new LinkedHashMap<>();
84 buildExternalClassMap(pProject);
85
86
87 theKnownClasses = new LinkedHashMap<>();
88 theReferenced = new ArrayList<>();
89 }
90
91
92
93
94
95
96 Map<String, ThemisXAnalysisReflectExternal> getExternalClassMap() {
97 return theExternalClasses;
98 }
99
100
101
102
103
104
105 private void buildProjectClassMap(final ThemisXAnalysisSolverProject pProject) {
106
107 for (ThemisXAnalysisSolverModule myModule : pProject.getModules()) {
108
109 for (ThemisXAnalysisSolverPackage myPackage : myModule.getPackages()) {
110 buildProjectClassMap(myPackage);
111 }
112 }
113 }
114
115
116
117
118
119
120 private void buildProjectClassMap(final ThemisXAnalysisSolverPackage pPackage) {
121
122 for (ThemisXAnalysisSolverFile myFile : pPackage.getFiles()) {
123
124 for (ThemisXAnalysisSolverClass myClass : myFile.getClasses()) {
125 final ThemisXAnalysisClassInstance myInstance = myClass.getUnderlyingClass();
126
127 if (!myInstance.isLocalDeclaration() && !myInstance.isAnonClass()) {
128 theProjectClasses.put(myClass.getFullName(), myClass);
129 }
130 }
131 }
132 }
133
134
135
136
137
138
139 private void buildExternalClassMap(final ThemisXAnalysisSolverProject pProject) {
140
141 for (ThemisXAnalysisReflectExternal myClass : theJavaLang.values()) {
142 theExternalClasses.put(myClass.getFullName(), myClass);
143 }
144
145
146 for (ThemisXAnalysisSolverModule myModule : pProject.getModules()) {
147
148 for (ThemisXAnalysisSolverPackage myPackage : myModule.getPackages()) {
149 buildExternalClassMap(myPackage);
150 }
151 }
152 }
153
154
155
156
157
158
159 private void buildExternalClassMap(final ThemisXAnalysisSolverPackage pPackage) {
160
161 for (ThemisXAnalysisSolverFile myFile : pPackage.getFiles()) {
162
163 for (ThemisXAnalysisNodeInstance myInstance : myFile.getUnderlyingFile().getContents().getImports()) {
164
165 final ThemisXAnalysisNodeImport myImport = (ThemisXAnalysisNodeImport) myInstance;
166 final String myFullName = myImport.getFullName();
167
168
169 if (!theProjectClasses.containsKey(myFullName)) {
170
171 theExternalClasses.computeIfAbsent(myFullName, n -> new ThemisXAnalysisReflectExternal(myImport));
172 }
173 }
174 }
175 }
176
177
178
179
180
181
182
183 private ThemisXAnalysisClassInstance lookUpImport(final ThemisXAnalysisNodeImport pImport) {
184
185 final String myFullName = pImport.getFullName();
186
187
188 final ThemisXAnalysisSolverClass myClass = theProjectClasses.get(myFullName);
189 return myClass != null
190 ? myClass.getUnderlyingClass()
191 : theExternalClasses.get(myFullName);
192 }
193
194
195
196
197
198
199 void processPackage(final ThemisXAnalysisSolverPackage pPackage) {
200
201 for (ThemisXAnalysisSolverFile myFile : pPackage.getFiles()) {
202
203 determineKnownClasses(myFile);
204
205
206 detectClassOrInterfaceTypes(myFile);
207 detectNameReferences(myFile);
208
209
210 myFile.setReferenced(theReferenced);
211 }
212
213
214 for (ThemisXAnalysisSolverFile myFile : pPackage.getFiles()) {
215
216 myFile.processLocalReferences();
217 }
218 }
219
220
221
222
223
224
225 private void determineKnownClasses(final ThemisXAnalysisSolverFile pFile) {
226
227 theKnownClasses.clear();
228 theReferenced.clear();
229 for (ThemisXAnalysisClassInstance myClass : theJavaLang.values()) {
230 theKnownClasses.put(myClass.getName(), myClass);
231 }
232
233
234 final ThemisXAnalysisSolverPackage myPackage = (ThemisXAnalysisSolverPackage) pFile.getOwningPackage();
235 for (ThemisXAnalysisSolverFile myFile : myPackage.getFiles()) {
236 final ThemisXAnalysisSolverClass myClass = myFile.getTopLevel();
237 if (myClass != null) {
238 theKnownClasses.put(myClass.getName(), myClass.getUnderlyingClass());
239 }
240 }
241
242
243 for (ThemisXAnalysisNodeInstance myNode : pFile.getUnderlyingFile().getContents().getImports()) {
244
245 final ThemisXAnalysisClassInstance myImport = lookUpImport((ThemisXAnalysisNodeImport) myNode);
246 theKnownClasses.put(myImport.getName(), myImport);
247 }
248
249
250 for (ThemisXAnalysisSolverClass myClass : pFile.getClasses()) {
251 if (!myClass.getUnderlyingClass().isAnonClass()) {
252 theKnownClasses.put(myClass.getName(), myClass.getUnderlyingClass());
253 }
254 }
255 }
256
257
258
259
260
261
262 private void detectClassOrInterfaceTypes(final ThemisXAnalysisSolverFile pFile) {
263
264 final ThemisXAnalysisInstance myClass = (ThemisXAnalysisInstance) pFile.getTopLevel().getUnderlyingClass();
265
266
267 final List<ThemisXAnalysisInstance> myReferences = myClass.discoverNodes(ThemisXAnalysisType.CLASSINTERFACE);
268
269
270 for (ThemisXAnalysisInstance myNode : myReferences) {
271 final ThemisXAnalysisTypeClassInterface myReference = (ThemisXAnalysisTypeClassInterface) myNode;
272 final ThemisXAnalysisClassInstance myResolved = processPossibleReference(myReference.getName());
273 if (myResolved != null) {
274 myReference.setClassInstance(myResolved);
275 } else {
276 System.out.println(myReference.getName() + ":" + pFile);
277 }
278 }
279 }
280
281
282
283
284
285
286 private void detectNameReferences(final ThemisXAnalysisSolverFile pFile) {
287
288 final ThemisXAnalysisInstance myClass = (ThemisXAnalysisInstance) pFile.getTopLevel().getUnderlyingClass();
289
290
291 final List<ThemisXAnalysisInstance> myReferences = myClass.discoverNodes(ThemisXAnalysisNode.NAME);
292
293
294 for (ThemisXAnalysisInstance myNode : myReferences) {
295 final ThemisXAnalysisNodeName myReference = (ThemisXAnalysisNodeName) myNode;
296 if (myReference.getQualifier() == null) {
297 final ThemisXAnalysisClassInstance myResolved = processPossibleReference(myReference.getName());
298 if (myResolved == null) {
299 look4Name(myReference);
300 }
301 }
302 }
303 }
304
305
306
307
308
309
310 private void look4Name(final ThemisXAnalysisNodeName pName) {
311 final String myName = pName.getName();
312 final Node myParent = pName.getNode().getParentNode().orElse(null);
313
314
315
316 }
317
318
319
320
321
322
323
324 private ThemisXAnalysisClassInstance processPossibleReference(final String pReference) {
325
326 final ThemisXAnalysisClassInstance myReference = theKnownClasses.get(pReference);
327 if (myReference != null) {
328 declareReferencedClass(myReference);
329 }
330 return myReference;
331 }
332
333
334
335
336
337
338 private void declareReferencedClass(final ThemisXAnalysisClassInstance pClass) {
339
340 ThemisXAnalysisSolverClass myClass = theProjectClasses.get(pClass.getFullName());
341 if (myClass == null) {
342 return;
343 }
344
345
346 if (!myClass.isTopLevel()) {
347 myClass = ((ThemisXAnalysisSolverFile) myClass.getOwningFile()).getTopLevel();
348 }
349
350
351 if (myClass != null && !theReferenced.contains(myClass)) {
352
353 theReferenced.add(myClass);
354 }
355 }
356 }