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 }