Mercurial > hg > truffle
comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/OrganizedImports.java @ 7291:a748e4d44694
Truffle API to specify type-specalized Node classes; annotation processor for automatic code generation of the type-specialized Node classes during the build process
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Fri, 21 Dec 2012 10:44:31 -0800 |
parents | |
children | 6343a09b2ec1 |
comparison
equal
deleted
inserted
replaced
7290:a81db08fe930 | 7291:a748e4d44694 |
---|---|
1 /* | |
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.truffle.codegen.processor.codewriter; | |
24 | |
25 import static com.oracle.truffle.codegen.processor.Utils.*; | |
26 | |
27 import java.util.*; | |
28 | |
29 import javax.lang.model.element.*; | |
30 import javax.lang.model.type.*; | |
31 import javax.lang.model.util.*; | |
32 | |
33 import com.oracle.truffle.codegen.processor.*; | |
34 import com.oracle.truffle.codegen.processor.ast.*; | |
35 | |
36 public final class OrganizedImports { | |
37 | |
38 private final Map<TypeMirror, Integer> importUsage = new HashMap<>(); | |
39 private final Map<TypeMirror, Integer> staticImportUsage = new HashMap<>(); | |
40 | |
41 private final Map<String, TypeMirror> simpleNamesUsed = new HashMap<>(); | |
42 | |
43 private final Set<String> declaredStaticMethods = new HashSet<>(); | |
44 private final Set<String> declaredStaticFields = new HashSet<>(); | |
45 private final Set<String> ambiguousStaticMethods = new HashSet<>(); | |
46 private final Set<String> ambiguousStaticFields = new HashSet<>(); | |
47 | |
48 private final CodeTypeElement topLevelClass; | |
49 | |
50 private OrganizedImports(CodeTypeElement topLevelClass) { | |
51 this.topLevelClass = topLevelClass; | |
52 } | |
53 | |
54 public static OrganizedImports organize(CodeTypeElement topLevelClass) { | |
55 OrganizedImports organized = new OrganizedImports(topLevelClass); | |
56 | |
57 OrganizedImports.ReferenceCollector reference = new ReferenceCollector(); | |
58 topLevelClass.accept(reference, null); | |
59 | |
60 OrganizedImports.ImportResolver resolver = new ImportResolver(reference, organized); | |
61 topLevelClass.accept(resolver, null); | |
62 return organized; | |
63 } | |
64 | |
65 public String useImport(TypeMirror type) { | |
66 String simpleName = getSimpleName(type); | |
67 TypeMirror usedByType = simpleNamesUsed.get(type); | |
68 if (usedByType == null) { | |
69 simpleNamesUsed.put(simpleName, type); | |
70 usedByType = type; | |
71 } else if (!typeEquals(type, usedByType)) { | |
72 // we need a qualified name | |
73 return getQualifiedName(type); | |
74 } | |
75 | |
76 // we can use the simple name | |
77 addUsage(type, importUsage); | |
78 return simpleName; | |
79 } | |
80 | |
81 public String useStaticFieldImport(TypeMirror type, String fieldName) { | |
82 return useStaticImport(type, fieldName, ambiguousStaticFields, declaredStaticFields); | |
83 } | |
84 | |
85 public String useStaticMethodImport(TypeMirror type, String methodName) { | |
86 return useStaticImport(type, methodName, ambiguousStaticMethods, declaredStaticMethods); | |
87 } | |
88 | |
89 private String useStaticImport(TypeMirror type, String name, Set<String> ambiguousSymbols, Set<String> declaredSymbols) { | |
90 if (ambiguousSymbols.contains(name)) { | |
91 // ambiguous import | |
92 return useImport(type) + "." + name; | |
93 } else if (!declaredSymbols.contains(name)) { | |
94 // not imported at all | |
95 return useImport(type) + "." + name; | |
96 } else { | |
97 // import declared and not ambiguous | |
98 addUsage(type, staticImportUsage); | |
99 return name; | |
100 } | |
101 } | |
102 | |
103 public Set<CodeImport> generateImports() { | |
104 Set<CodeImport> imports = new HashSet<>(); | |
105 | |
106 imports.addAll(generateImports(topLevelClass, importUsage.keySet())); | |
107 imports.addAll(generateStaticImports(topLevelClass, staticImportUsage.keySet())); | |
108 | |
109 return imports; | |
110 } | |
111 | |
112 void clearStaticImports() { | |
113 declaredStaticFields.clear(); | |
114 declaredStaticMethods.clear(); | |
115 ambiguousStaticFields.clear(); | |
116 ambiguousStaticMethods.clear(); | |
117 } | |
118 | |
119 boolean processStaticImports(TypeElement element) { | |
120 Set<String> importedMethods = new HashSet<>(); | |
121 List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements()); | |
122 for (ExecutableElement method : methods) { | |
123 if (method.getModifiers().contains(Modifier.STATIC)) { | |
124 importedMethods.add(method.getSimpleName().toString()); | |
125 } | |
126 } | |
127 | |
128 boolean allMethodsAmbiguous = processStaticImportElements(importedMethods, this.ambiguousStaticMethods, this.declaredStaticMethods); | |
129 | |
130 Set<String> importedFields = new HashSet<>(); | |
131 List<VariableElement> fields = ElementFilter.fieldsIn(element.getEnclosedElements()); | |
132 for (VariableElement field : fields) { | |
133 if (field.getModifiers().contains(Modifier.STATIC)) { | |
134 importedFields.add(field.getSimpleName().toString()); | |
135 } | |
136 } | |
137 | |
138 boolean allFieldsAmbiguous = processStaticImportElements(importedFields, this.ambiguousStaticFields, this.declaredStaticFields); | |
139 | |
140 return allMethodsAmbiguous && allFieldsAmbiguous; | |
141 } | |
142 | |
143 private static boolean processStaticImportElements(Set<String> newElements, Set<String> ambiguousElements, Set<String> declaredElements) { | |
144 boolean allAmbiguous = false; | |
145 if (declaredElements.containsAll(newElements)) { | |
146 // all types already declared -> we can remove the import completely -> they will all get ambiguous | |
147 allAmbiguous = true; | |
148 } | |
149 Set<String> newAmbiguous = new HashSet<>(); | |
150 Set<String> newDeclared = new HashSet<>(); | |
151 | |
152 for (String newElement : newElements) { | |
153 if (declaredElements.contains(newElement)) { | |
154 newAmbiguous.add(newElement); | |
155 } else if (ambiguousElements.contains(newElement)) { | |
156 // nothing to do | |
157 } else { | |
158 newDeclared.add(newElement); | |
159 } | |
160 } | |
161 | |
162 ambiguousElements.addAll(newAmbiguous); | |
163 declaredElements.addAll(newDeclared); | |
164 return allAmbiguous; | |
165 } | |
166 | |
167 private static Set<CodeImport> generateImports(CodeTypeElement e, Set<TypeMirror> toGenerate) { | |
168 Set<String> autoImportedTypes = new HashSet<>(); | |
169 | |
170 // if type is declared inside a super type of this class -> no import | |
171 collectSuperTypeImports(e, autoImportedTypes); | |
172 collectInnerTypeImports(e, autoImportedTypes); | |
173 | |
174 TreeSet<CodeImport> importObjects = new TreeSet<>(); | |
175 for (TypeMirror importType : toGenerate) { | |
176 String importTypePackageName = getPackageName(importType); | |
177 if (importTypePackageName == null) { | |
178 continue; // no package name -> no import | |
179 } | |
180 | |
181 if (importTypePackageName.equals("java.lang")) { | |
182 continue; // java.lang is automatically imported | |
183 } | |
184 | |
185 if (importTypePackageName.equals(getPackageName(e))) { | |
186 continue; // same package name -> no import | |
187 } | |
188 | |
189 String qualifiedName = getQualifiedName(importType); | |
190 | |
191 if (autoImportedTypes.contains(qualifiedName)) { | |
192 continue; | |
193 } | |
194 | |
195 importObjects.add(new CodeImport(importType, getQualifiedName(importType), false)); | |
196 } | |
197 | |
198 return importObjects; | |
199 } | |
200 | |
201 private static void collectInnerTypeImports(TypeElement e, Set<String> autoImportedTypes) { | |
202 for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) { | |
203 collectSuperTypeImports(innerClass, autoImportedTypes); | |
204 collectInnerTypeImports(innerClass, autoImportedTypes); | |
205 } | |
206 } | |
207 | |
208 private static void collectSuperTypeImports(TypeElement e, Set<String> autoImportedTypes) { | |
209 List<TypeElement> superTypes = getSuperTypes(e); | |
210 for (TypeElement superType : superTypes) { | |
211 List<TypeElement> declaredTypes = getDeclaredTypes(superType); | |
212 for (TypeElement declaredType : declaredTypes) { | |
213 autoImportedTypes.add(getQualifiedName(declaredType)); | |
214 } | |
215 } | |
216 } | |
217 | |
218 private static Set<CodeImport> generateStaticImports(CodeTypeElement e, Set<TypeMirror> toGenerate) { | |
219 Set<String> autoImportedStaticTypes = new HashSet<>(); | |
220 | |
221 // if type is declared inside a super type of this class -> no import | |
222 autoImportedStaticTypes.add(getQualifiedName(e)); | |
223 autoImportedStaticTypes.addAll(getQualifiedSuperTypeNames(e)); | |
224 | |
225 TreeSet<CodeImport> importObjects = new TreeSet<>(); | |
226 for (TypeMirror importType : toGenerate) { | |
227 if (getPackageName(importType) == null) { | |
228 continue; // no package name -> no import | |
229 } | |
230 | |
231 String qualifiedName = getQualifiedName(importType); | |
232 if (autoImportedStaticTypes.contains(qualifiedName)) { | |
233 continue; | |
234 } | |
235 | |
236 importObjects.add(new CodeImport(importType, qualifiedName + ".*", true)); | |
237 } | |
238 | |
239 return importObjects; | |
240 } | |
241 | |
242 private static void addUsage(TypeMirror type, Map<TypeMirror, Integer> usageMap) { | |
243 if (type != null) { | |
244 Integer value = usageMap.get(type); | |
245 if (value == null) { | |
246 usageMap.put(type, 1); | |
247 } else { | |
248 usageMap.put(type, value + 1); | |
249 } | |
250 } | |
251 } | |
252 | |
253 private static class ReferenceCollector extends CodeElementScanner<Void, Void> { | |
254 | |
255 final Map<TypeMirror, Integer> typeReferences = new HashMap<>(); | |
256 final Map<TypeMirror, Integer> staticTypeReferences = new HashMap<>(); | |
257 | |
258 @Override | |
259 public void visitTree(CodeTree e, Void p) { | |
260 if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { | |
261 addStaticImport(e.getType()); | |
262 } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { | |
263 addStaticImport(e.getType()); | |
264 } else { | |
265 addImport(e.getType()); | |
266 } | |
267 super.visitTree(e, p); | |
268 } | |
269 | |
270 @Override | |
271 public Void visitExecutable(CodeExecutableElement e, Void p) { | |
272 visitAnnotations(e.getAnnotationMirrors()); | |
273 if (e.getReturnType() != null) { | |
274 addImport(e.getReturnType()); | |
275 } | |
276 for (TypeMirror type : e.getThrownTypes()) { | |
277 addImport(type); | |
278 } | |
279 return super.visitExecutable(e, p); | |
280 } | |
281 | |
282 @Override | |
283 public Void visitType(CodeTypeElement e, Void p) { | |
284 visitAnnotations(e.getAnnotationMirrors()); | |
285 | |
286 addImport(e.getSuperclass()); | |
287 for (TypeMirror type : e.getImplements()) { | |
288 addImport(type); | |
289 } | |
290 | |
291 return super.visitType(e, p); | |
292 } | |
293 | |
294 @Override | |
295 public Void visitVariable(VariableElement f, Void p) { | |
296 visitAnnotations(f.getAnnotationMirrors()); | |
297 addImport(f.asType()); | |
298 return super.visitVariable(f, p); | |
299 } | |
300 | |
301 private void visitAnnotations(List<? extends AnnotationMirror> mirrors) { | |
302 for (AnnotationMirror mirror : mirrors) { | |
303 visitAnnotation(mirror); | |
304 } | |
305 } | |
306 | |
307 public void visitAnnotation(AnnotationMirror e) { | |
308 addImport(e.getAnnotationType()); | |
309 } | |
310 | |
311 @Override | |
312 public void visitImport(CodeImport e, Void p) { | |
313 } | |
314 | |
315 private void addStaticImport(TypeMirror type) { | |
316 addUsage(type, staticTypeReferences); | |
317 } | |
318 | |
319 private void addImport(TypeMirror type) { | |
320 addUsage(type, typeReferences); | |
321 } | |
322 | |
323 } | |
324 | |
325 private static class ImportResolver extends CodeElementScanner<Void, Void> { | |
326 | |
327 private final ReferenceCollector collector; | |
328 private final OrganizedImports organizedImports; | |
329 | |
330 public ImportResolver(OrganizedImports.ReferenceCollector collector, OrganizedImports organizedImports) { | |
331 this.collector = collector; | |
332 this.organizedImports = organizedImports; | |
333 } | |
334 | |
335 @Override | |
336 public Void visitType(CodeTypeElement e, Void p) { | |
337 if (e.isTopLevelClass()) { | |
338 organizedImports.clearStaticImports(); | |
339 | |
340 organizedImports.processStaticImports(e); | |
341 List<TypeElement> types = Utils.getSuperTypes(e); | |
342 for (TypeElement typeElement : types) { | |
343 organizedImports.processStaticImports(typeElement); | |
344 } | |
345 | |
346 for (TypeMirror type : collector.staticTypeReferences.keySet()) { | |
347 TypeElement element = fromTypeMirror(type); | |
348 if (element != null) { | |
349 // already processed by supertype | |
350 if (types.contains(element)) { | |
351 continue; | |
352 } | |
353 organizedImports.processStaticImports(element); | |
354 } | |
355 } | |
356 | |
357 for (TypeMirror imp : collector.typeReferences.keySet()) { | |
358 organizedImports.useImport(imp); | |
359 } | |
360 } | |
361 return super.visitType(e, p); | |
362 } | |
363 | |
364 @Override | |
365 public void visitTree(CodeTree e, Void p) { | |
366 if (e.getCodeKind() == CodeTreeKind.TYPE) { | |
367 organizedImports.useImport(e.getType()); | |
368 } else if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) { | |
369 organizedImports.useStaticFieldImport(e.getType(), e.getString()); | |
370 } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) { | |
371 organizedImports.useStaticMethodImport(e.getType(), e.getString()); | |
372 } | |
373 super.visitTree(e, p); | |
374 } | |
375 } | |
376 | |
377 } |