comparison truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java @ 21951:9c8c0937da41

Moving all sources into truffle subdirectory
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Wed, 17 Jun 2015 10:58:08 +0200
parents graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java@0ec5f5a2e720
children dc83cc1f94f2
comparison
equal deleted inserted replaced
21950:2a5011c7e641 21951:9c8c0937da41
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.dsl.processor.java.transform;
24
25 import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
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.dsl.processor.java.*;
34 import com.oracle.truffle.dsl.processor.java.model.*;
35
36 public final class OrganizedImports {
37
38 private final Map<String, String> classImportUsage = new HashMap<>();
39 private final Map<String, Set<String>> autoImportCache = new HashMap<>();
40
41 private final CodeTypeElement topLevelClass;
42
43 private OrganizedImports(CodeTypeElement topLevelClass) {
44 this.topLevelClass = topLevelClass;
45 }
46
47 public static OrganizedImports organize(CodeTypeElement topLevelClass) {
48 OrganizedImports organized = new OrganizedImports(topLevelClass);
49 organized.organizeImpl();
50 return organized;
51 }
52
53 private void organizeImpl() {
54 ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor();
55 topLevelClass.accept(reference, null);
56 }
57
58 public String createTypeReference(Element enclosedElement, TypeMirror type) {
59 switch (type.getKind()) {
60 case BOOLEAN:
61 case BYTE:
62 case CHAR:
63 case DOUBLE:
64 case FLOAT:
65 case SHORT:
66 case INT:
67 case LONG:
68 case VOID:
69 return ElementUtils.getSimpleName(type);
70 case DECLARED:
71 return createDeclaredTypeName(enclosedElement, (DeclaredType) type);
72 case ARRAY:
73 return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]";
74 case WILDCARD:
75 return createWildcardName(enclosedElement, (WildcardType) type);
76 case TYPEVAR:
77 return "?";
78 default:
79 throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
80 }
81 }
82
83 public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) {
84 return createStaticReference(enclosedElement, type, fieldName);
85 }
86
87 public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) {
88 return createStaticReference(enclosedElement, type, methodName);
89 }
90
91 private String createStaticReference(Element enclosedElement, TypeMirror type, String name) {
92 // ambiguous import
93 return createTypeReference(enclosedElement, type) + "." + name;
94 }
95
96 private String createWildcardName(Element enclosedElement, WildcardType type) {
97 StringBuilder b = new StringBuilder();
98 if (type.getExtendsBound() != null) {
99 b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
100 } else if (type.getSuperBound() != null) {
101 b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
102 } else {
103 b.append("?");
104 }
105 return b.toString();
106 }
107
108 private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) {
109 String name = ElementUtils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString());
110 if (classImportUsage.containsKey(name)) {
111 String qualifiedImport = classImportUsage.get(name);
112 String qualifiedName = ElementUtils.getEnclosedQualifiedName(type);
113
114 if (!qualifiedName.equals(qualifiedImport)) {
115 name = qualifiedName;
116 }
117 }
118
119 List<? extends TypeMirror> genericTypes = type.getTypeArguments();
120 if (genericTypes.size() == 0) {
121 return name;
122 }
123
124 StringBuilder b = new StringBuilder(name);
125 b.append("<");
126 for (int i = 0; i < genericTypes.size(); i++) {
127 TypeMirror genericType = i < genericTypes.size() ? genericTypes.get(i) : null;
128 if (genericType != null) {
129 b.append(createTypeReference(enclosedElement, genericType));
130 } else {
131 b.append("?");
132 }
133
134 if (i < genericTypes.size() - 1) {
135 b.append(", ");
136 }
137 }
138 b.append(">");
139 return b.toString();
140 }
141
142 public Set<CodeImport> generateImports() {
143 Set<CodeImport> imports = new HashSet<>();
144
145 imports.addAll(generateImports(classImportUsage));
146
147 return imports;
148 }
149
150 private boolean needsImport(Element enclosed, TypeMirror importType) {
151 String importPackagName = getPackageName(importType);
152 TypeElement enclosedElement = findNearestEnclosingType(enclosed);
153 if (importPackagName == null) {
154 return false;
155 } else if (importPackagName.equals("java.lang")) {
156 return false;
157 } else if (importPackagName.equals(getPackageName(topLevelClass)) && ElementUtils.isTopLevelClass(importType)) {
158 return false; // same package name -> no import
159 }
160
161 String enclosedElementId = ElementUtils.getUniqueIdentifier(enclosedElement.asType());
162 Set<String> autoImportedTypes = autoImportCache.get(enclosedElementId);
163 if (autoImportedTypes == null) {
164 List<Element> elements = ElementUtils.getElementHierarchy(enclosedElement);
165 autoImportedTypes = new HashSet<>();
166 for (Element element : elements) {
167 if (element.getKind().isClass()) {
168 collectSuperTypeImports((TypeElement) element, autoImportedTypes);
169 collectInnerTypeImports((TypeElement) element, autoImportedTypes);
170 }
171 }
172 autoImportCache.put(enclosedElementId, autoImportedTypes);
173 }
174
175 String qualifiedName = getQualifiedName(importType);
176 if (autoImportedTypes.contains(qualifiedName)) {
177 return false;
178 }
179
180 return true;
181 }
182
183 private static Set<CodeImport> generateImports(Map<String, String> symbols) {
184 TreeSet<CodeImport> importObjects = new TreeSet<>();
185 for (String symbol : symbols.keySet()) {
186 String packageName = symbols.get(symbol);
187 if (packageName != null) {
188 importObjects.add(new CodeImport(packageName, symbol, false));
189 }
190 }
191 return importObjects;
192 }
193
194 private static void collectInnerTypeImports(TypeElement e, Set<String> autoImportedTypes) {
195 autoImportedTypes.add(getQualifiedName(e));
196 for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) {
197 collectInnerTypeImports(innerClass, autoImportedTypes);
198 }
199 }
200
201 private static void collectSuperTypeImports(TypeElement e, Set<String> autoImportedTypes) {
202 List<TypeElement> superTypes = getSuperTypes(e);
203 for (TypeElement superType : superTypes) {
204 List<TypeElement> declaredTypes = getDeclaredTypes(superType);
205 for (TypeElement declaredType : declaredTypes) {
206 if (!superTypes.contains(declaredType)) {
207 autoImportedTypes.add(getQualifiedName(declaredType));
208 }
209 }
210 }
211 }
212
213 private abstract static class TypeReferenceVisitor extends CodeElementScanner<Void, Void> {
214
215 @Override
216 public void visitTree(CodeTree e, Void p, Element enclosing) {
217 if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) {
218 visitStaticFieldReference(enclosing, e.getType(), e.getString());
219 } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) {
220 visitStaticMethodReference(enclosing, e.getType(), e.getString());
221 } else if (e.getType() != null) {
222 visitTypeReference(enclosing, e.getType());
223 }
224 super.visitTree(e, p, enclosing);
225 }
226
227 @Override
228 public Void visitExecutable(CodeExecutableElement e, Void p) {
229 visitAnnotations(e, e.getAnnotationMirrors());
230 if (e.getReturnType() != null) {
231 visitTypeReference(e, e.getReturnType());
232 }
233 for (TypeMirror type : e.getThrownTypes()) {
234 visitTypeReference(e, type);
235 }
236 return super.visitExecutable(e, p);
237 }
238
239 @Override
240 public Void visitType(CodeTypeElement e, Void p) {
241 visitAnnotations(e, e.getAnnotationMirrors());
242
243 visitTypeReference(e, e.getSuperclass());
244 for (TypeMirror type : e.getImplements()) {
245 visitTypeReference(e, type);
246 }
247
248 return super.visitType(e, p);
249 }
250
251 private void visitAnnotations(Element enclosingElement, List<? extends AnnotationMirror> mirrors) {
252 for (AnnotationMirror mirror : mirrors) {
253 visitAnnotation(enclosingElement, mirror);
254 }
255 }
256
257 public void visitAnnotation(Element enclosingElement, AnnotationMirror e) {
258 visitTypeReference(enclosingElement, e.getAnnotationType());
259 if (!e.getElementValues().isEmpty()) {
260 Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
261 Set<? extends ExecutableElement> methodsSet = values.keySet();
262 List<ExecutableElement> methodsList = new ArrayList<>();
263 for (ExecutableElement method : methodsSet) {
264 if (values.get(method) == null) {
265 continue;
266 }
267 methodsList.add(method);
268 }
269
270 for (int i = 0; i < methodsList.size(); i++) {
271 AnnotationValue value = values.get(methodsList.get(i));
272 visitAnnotationValue(enclosingElement, value);
273 }
274 }
275 }
276
277 public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) {
278 e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null);
279 }
280
281 private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
282
283 private final Element enclosingElement;
284
285 public AnnotationValueReferenceVisitor(Element enclosedElement) {
286 this.enclosingElement = enclosedElement;
287 }
288
289 @Override
290 public Void visitBoolean(boolean b, Void p) {
291 return null;
292 }
293
294 @Override
295 public Void visitByte(byte b, Void p) {
296 return null;
297 }
298
299 @Override
300 public Void visitChar(char c, Void p) {
301 return null;
302 }
303
304 @Override
305 public Void visitDouble(double d, Void p) {
306 return null;
307 }
308
309 @Override
310 public Void visitFloat(float f, Void p) {
311 return null;
312 }
313
314 @Override
315 public Void visitInt(int i, Void p) {
316 return null;
317 }
318
319 @Override
320 public Void visitLong(long i, Void p) {
321 return null;
322 }
323
324 @Override
325 public Void visitShort(short s, Void p) {
326 return null;
327 }
328
329 @Override
330 public Void visitString(String s, Void p) {
331 return null;
332 }
333
334 @Override
335 public Void visitType(TypeMirror t, Void p) {
336 visitTypeReference(enclosingElement, t);
337 return null;
338 }
339
340 @Override
341 public Void visitEnumConstant(VariableElement c, Void p) {
342 visitTypeReference(enclosingElement, c.asType());
343 return null;
344 }
345
346 @Override
347 public Void visitAnnotation(AnnotationMirror a, Void p) {
348 TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a);
349 return null;
350 }
351
352 @Override
353 public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
354 for (int i = 0; i < vals.size(); i++) {
355 TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i));
356 }
357 return null;
358 }
359 }
360
361 @Override
362 public Void visitVariable(VariableElement f, Void p) {
363 visitAnnotations(f, f.getAnnotationMirrors());
364 visitTypeReference(f, f.asType());
365 return super.visitVariable(f, p);
366 }
367
368 @Override
369 public void visitImport(CodeImport e, Void p) {
370 }
371
372 public abstract void visitTypeReference(Element enclosedType, TypeMirror type);
373
374 public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName);
375
376 public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName);
377
378 }
379
380 private class ImportTypeReferenceVisitor extends TypeReferenceVisitor {
381
382 @Override
383 public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) {
384 visitTypeReference(enclosedType, type);
385 }
386
387 @Override
388 public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) {
389 visitTypeReference(enclosedType, type);
390 }
391
392 @Override
393 public void visitTypeReference(Element enclosedType, TypeMirror type) {
394 if (type != null) {
395 switch (type.getKind()) {
396 case BOOLEAN:
397 case BYTE:
398 case CHAR:
399 case DOUBLE:
400 case FLOAT:
401 case SHORT:
402 case INT:
403 case LONG:
404 case VOID:
405 return;
406 case DECLARED:
407 if (needsImport(enclosedType, type)) {
408 DeclaredType declard = (DeclaredType) type;
409 registerSymbol(classImportUsage, ElementUtils.getEnclosedQualifiedName(declard), ElementUtils.getDeclaredName(declard, false));
410 }
411 for (TypeMirror argument : ((DeclaredType) type).getTypeArguments()) {
412 visitTypeReference(enclosedType, argument);
413 }
414 return;
415 case ARRAY:
416 visitTypeReference(enclosedType, ((ArrayType) type).getComponentType());
417 return;
418 case WILDCARD:
419 WildcardType wildcard = (WildcardType) type;
420 if (wildcard.getExtendsBound() != null) {
421 visitTypeReference(enclosedType, wildcard.getExtendsBound());
422 } else if (wildcard.getSuperBound() != null) {
423 visitTypeReference(enclosedType, wildcard.getSuperBound());
424 }
425 return;
426 case TYPEVAR:
427 return;
428 default:
429 throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
430 }
431
432 }
433 }
434
435 private void registerSymbol(Map<String, String> symbolUsage, String elementQualifiedName, String elementName) {
436 if (symbolUsage.containsKey(elementName)) {
437 String otherQualifiedName = symbolUsage.get(elementName);
438 if (otherQualifiedName == null) {
439 // already registered ambiguous
440 return;
441 }
442 if (!otherQualifiedName.equals(elementQualifiedName)) {
443 symbolUsage.put(elementName, null);
444 }
445 } else {
446 symbolUsage.put(elementName, elementQualifiedName);
447 }
448 }
449
450 }
451
452 }