Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java @ 16759:23415229349b
Truffle-DSL: new package structure.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 11 Aug 2014 15:57:14 +0200 |
parents | graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java@f78eafd5ba9e |
children | ccb4e2bd894f |
comparison
equal
deleted
inserted
replaced
16758:c5f8eeb3cbc8 | 16759:23415229349b |
---|---|
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.compiler; | |
24 | |
25 import java.util.*; | |
26 | |
27 import javax.annotation.processing.*; | |
28 import javax.lang.model.element.*; | |
29 import javax.lang.model.type.*; | |
30 | |
31 import com.oracle.truffle.dsl.processor.java.*; | |
32 | |
33 public class JDTCompiler extends AbstractCompiler { | |
34 | |
35 public static boolean isValidElement(Element currentElement) { | |
36 try { | |
37 Class<?> elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl"); | |
38 return elementClass.isAssignableFrom(currentElement.getClass()); | |
39 } catch (ClassNotFoundException e) { | |
40 return false; | |
41 } | |
42 } | |
43 | |
44 public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) { | |
45 return sortBySourceOrder(new ArrayList<>(environment.getElementUtils().getAllMembers(type))); | |
46 } | |
47 | |
48 public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) { | |
49 return sortBySourceOrder(new ArrayList<>(type.getEnclosedElements())); | |
50 } | |
51 | |
52 private static List<? extends Element> sortBySourceOrder(List<Element> elements) { | |
53 final Map<TypeElement, List<Object>> declarationOrders = new HashMap<>(); | |
54 | |
55 Collections.sort(elements, new Comparator<Element>() { | |
56 public int compare(Element o1, Element o2) { | |
57 try { | |
58 TypeMirror enclosing1 = o1.getEnclosingElement().asType(); | |
59 TypeMirror enclosing2 = o2.getEnclosingElement().asType(); | |
60 | |
61 if (ElementUtils.typeEquals(enclosing1, enclosing2)) { | |
62 List<Object> declarationOrder = lookupDeclarationOrder(declarationOrders, (TypeElement) o1.getEnclosingElement()); | |
63 if (declarationOrder == null) { | |
64 return 0; | |
65 } | |
66 Object o1Binding = field(o1, "_binding"); | |
67 Object o2Binding = field(o2, "_binding"); | |
68 | |
69 int i1 = declarationOrder.indexOf(o1Binding); | |
70 int i2 = declarationOrder.indexOf(o2Binding); | |
71 | |
72 return i1 - i2; | |
73 } else { | |
74 if (ElementUtils.isSubtype(enclosing1, enclosing2)) { | |
75 return 1; | |
76 } else if (ElementUtils.isSubtype(enclosing2, enclosing1)) { | |
77 return -1; | |
78 } else { | |
79 return 0; | |
80 } | |
81 } | |
82 } catch (Exception e) { | |
83 throw new RuntimeException(e); | |
84 } | |
85 } | |
86 }); | |
87 return elements; | |
88 } | |
89 | |
90 private static List<Object> lookupDeclarationOrder(Map<TypeElement, List<Object>> declarationOrders, TypeElement type) throws Exception, ClassNotFoundException { | |
91 if (declarationOrders.containsKey(type)) { | |
92 return declarationOrders.get(type); | |
93 } | |
94 | |
95 Object binding = field(type, "_binding"); | |
96 Class<?> sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); | |
97 Class<?> binaryTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding"); | |
98 | |
99 List<Object> declarationOrder = null; | |
100 if (sourceTypeBinding.isAssignableFrom(binding.getClass())) { | |
101 declarationOrder = findSourceTypeOrder(binding); | |
102 } else if (binaryTypeBinding.isAssignableFrom(binding.getClass())) { | |
103 declarationOrder = findBinaryTypeOrder(binding); | |
104 } | |
105 | |
106 declarationOrders.put(type, declarationOrder); | |
107 | |
108 return declarationOrder; | |
109 } | |
110 | |
111 private static List<Object> findBinaryTypeOrder(Object binding) throws Exception { | |
112 Object binaryType = lookupBinaryType(binding); | |
113 final Object[] sortedMethods = (Object[]) method(binaryType, "getMethods"); | |
114 | |
115 List<Object> sortedElements = new ArrayList<>(); | |
116 if (sortedMethods != null) { | |
117 sortedElements.addAll(Arrays.asList(sortedMethods)); | |
118 } | |
119 final Object[] sortedFields = (Object[]) method(binaryType, "getFields"); | |
120 if (sortedFields != null) { | |
121 sortedElements.addAll(Arrays.asList(sortedFields)); | |
122 } | |
123 final Object[] sortedTypes = (Object[]) method(binaryType, "getMemberTypes", new Class[0]); | |
124 if (sortedTypes != null) { | |
125 sortedElements.addAll(Arrays.asList(sortedTypes)); | |
126 } | |
127 | |
128 Collections.sort(sortedElements, new Comparator<Object>() { | |
129 public int compare(Object o1, Object o2) { | |
130 try { | |
131 int structOffset1 = (int) field(o1, "structOffset"); | |
132 int structOffset2 = (int) field(o2, "structOffset"); | |
133 return structOffset1 - structOffset2; | |
134 } catch (Exception e) { | |
135 throw new RuntimeException(e); | |
136 } | |
137 } | |
138 }); | |
139 | |
140 Class<?> binaryMethod = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryMethod"); | |
141 Class<?> binaryField = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryField"); | |
142 Class<?> nestedType = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryNestedType"); | |
143 | |
144 List<Object> bindings = new ArrayList<>(); | |
145 for (Object sortedElement : sortedElements) { | |
146 Class<?> elementClass = sortedElement.getClass(); | |
147 if (binaryMethod.isAssignableFrom(elementClass)) { | |
148 char[] selector = (char[]) method(sortedElement, "getSelector"); | |
149 Object[] foundBindings = (Object[]) method(binding, "getMethods", new Class[]{char[].class}, selector); | |
150 if (foundBindings == null || foundBindings.length == 0) { | |
151 continue; | |
152 } else if (foundBindings.length == 1) { | |
153 bindings.add(foundBindings[0]); | |
154 } else { | |
155 char[] idescriptor = (char[]) method(sortedElement, "getMethodDescriptor"); | |
156 for (Object foundBinding : foundBindings) { | |
157 char[] descriptor = (char[]) method(foundBinding, "signature"); | |
158 if (descriptor == null && idescriptor == null || Arrays.equals(descriptor, idescriptor)) { | |
159 bindings.add(foundBinding); | |
160 break; | |
161 } | |
162 } | |
163 } | |
164 } else if (binaryField.isAssignableFrom(elementClass)) { | |
165 char[] selector = (char[]) method(sortedElement, "getName"); | |
166 Object foundField = method(binding, "getField", new Class[]{char[].class, boolean.class}, selector, true); | |
167 if (foundField != null) { | |
168 bindings.add(foundField); | |
169 } | |
170 } else if (nestedType.isAssignableFrom(elementClass)) { | |
171 char[] selector = (char[]) method(sortedElement, "getSourceName"); | |
172 Object foundType = method(binding, "getMemberType", new Class[]{char[].class}, selector); | |
173 if (foundType != null) { | |
174 bindings.add(foundType); | |
175 } | |
176 } else { | |
177 throw new AssertionError("Unexpected encountered type " + elementClass); | |
178 } | |
179 } | |
180 | |
181 return bindings; | |
182 } | |
183 | |
184 private static Object lookupBinaryType(Object binding) throws Exception { | |
185 Object lookupEnvironment = field(binding, "environment"); | |
186 Object compoundClassName = field(binding, "compoundName"); | |
187 Object nameEnvironment = field(lookupEnvironment, "nameEnvironment"); | |
188 Object nameEnvironmentAnswer = method(nameEnvironment, "findType", new Class[]{char[][].class}, compoundClassName); | |
189 Object binaryType = method(nameEnvironmentAnswer, "getBinaryType", new Class[0]); | |
190 return binaryType; | |
191 } | |
192 | |
193 private static List<Object> findSourceTypeOrder(Object binding) throws Exception { | |
194 Object referenceContext = field(field(binding, "scope"), "referenceContext"); | |
195 | |
196 TreeMap<Integer, Object> orderedBindings = new TreeMap<>(); | |
197 | |
198 collectSourceOrder(orderedBindings, referenceContext, "methods"); | |
199 collectSourceOrder(orderedBindings, referenceContext, "fields"); | |
200 collectSourceOrder(orderedBindings, referenceContext, "memberTypes"); | |
201 | |
202 return new ArrayList<>(orderedBindings.values()); | |
203 } | |
204 | |
205 private static void collectSourceOrder(TreeMap<Integer, Object> orderedBindings, Object referenceContext, String fieldName) throws Exception { | |
206 Object[] declarations = (Object[]) field(referenceContext, fieldName); | |
207 if (declarations != null) { | |
208 for (int i = 0; i < declarations.length; i++) { | |
209 Integer declarationSourceStart = (Integer) field(declarations[i], "declarationSourceStart"); | |
210 orderedBindings.put(declarationSourceStart, field(declarations[i], "binding")); | |
211 } | |
212 } | |
213 } | |
214 | |
215 @Override | |
216 public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) { | |
217 try { | |
218 | |
219 char[] source = getSource(method); | |
220 if (source == null) { | |
221 return null; | |
222 } | |
223 | |
224 /* | |
225 * AbstractMethodDeclaration decl = | |
226 * ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); int bodyStart = | |
227 * decl.bodyStart; int bodyEnd = decl.bodyEnd; | |
228 */ | |
229 Object decl = method(field(method, "_binding"), "sourceMethod"); | |
230 int bodyStart = (int) field(decl, "bodyStart"); | |
231 int bodyEnd = (int) field(decl, "bodyEnd"); | |
232 | |
233 int length = bodyEnd - bodyStart; | |
234 char[] target = new char[length]; | |
235 System.arraycopy(source, bodyStart, target, 0, length); | |
236 | |
237 return new String(target); | |
238 } catch (Exception e) { | |
239 return ElementUtils.printException(e); | |
240 } | |
241 } | |
242 | |
243 private static char[] getSource(Element element) throws Exception { | |
244 /* | |
245 * Binding binding = ((ElementImpl)element)._binding; char[] source = null; if (binding | |
246 * instanceof MethodBinding) { source = ((MethodBinding) | |
247 * binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); } else if | |
248 * (binding instanceof SourceTypeBinding) { source = | |
249 * ((SourceTypeBinding)binding).scope.referenceContext | |
250 * .compilationResult.compilationUnit.getContents(); } return source; | |
251 */ | |
252 | |
253 Object binding = field(element, "_binding"); | |
254 Class<?> methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding"); | |
255 Class<?> referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); | |
256 | |
257 char[] source = null; | |
258 if (methodBindingClass.isAssignableFrom(binding.getClass())) { | |
259 Object sourceMethod = method(binding, "sourceMethod"); | |
260 if (sourceMethod == null) { | |
261 return null; | |
262 } | |
263 source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents"); | |
264 } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) { | |
265 source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents"); | |
266 } | |
267 return source; | |
268 } | |
269 | |
270 @Override | |
271 public String getHeaderComment(ProcessingEnvironment env, Element type) { | |
272 try { | |
273 char[] source = getSource(type); | |
274 if (source == null) { | |
275 return null; | |
276 } | |
277 return parseHeader(new String(source)); | |
278 } catch (Exception e) { | |
279 return ElementUtils.printException(e); | |
280 } | |
281 } | |
282 | |
283 } |