Mercurial > hg > truffle
diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java @ 16753:f78eafd5ba9e
Truffle-DSL: the processor compiler abstraction now supports declaration oder for enclosed elements of types for JDT which is not conforming to specification.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 11 Aug 2014 15:53:05 +0200 |
parents | ae6b8ec920e2 |
children |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java Mon Aug 11 15:53:05 2014 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java Mon Aug 11 15:53:05 2014 +0200 @@ -26,6 +26,7 @@ import javax.annotation.processing.*; import javax.lang.model.element.*; +import javax.lang.model.type.*; import com.oracle.truffle.dsl.processor.*; @@ -40,24 +41,28 @@ } } - public List<? extends Element> getEnclosedElementsDeclarationOrder(TypeElement type) { - try { - Object binding = field(type, "_binding"); + public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) { + return sortBySourceOrder(new ArrayList<>(environment.getElementUtils().getAllMembers(type))); + } - Class<?> sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); + public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) { + return sortBySourceOrder(new ArrayList<>(type.getEnclosedElements())); + } + + private static List<? extends Element> sortBySourceOrder(List<Element> elements) { + final Map<TypeElement, List<Object>> declarationOrders = new HashMap<>(); - final List<Object> declarationOrder; - if (sourceTypeBinding.isAssignableFrom(binding.getClass())) { - declarationOrder = findSourceOrder(binding); - } else { - return null; - } + Collections.sort(elements, new Comparator<Element>() { + public int compare(Element o1, Element o2) { + try { + TypeMirror enclosing1 = o1.getEnclosingElement().asType(); + TypeMirror enclosing2 = o2.getEnclosingElement().asType(); - List<Element> enclosedElements = new ArrayList<>(type.getEnclosedElements()); - Collections.sort(enclosedElements, new Comparator<Element>() { - - public int compare(Element o1, Element o2) { - try { + if (Utils.typeEquals(enclosing1, enclosing2)) { + List<Object> declarationOrder = lookupDeclarationOrder(declarationOrders, (TypeElement) o1.getEnclosingElement()); + if (declarationOrder == null) { + return 0; + } Object o1Binding = field(o1, "_binding"); Object o2Binding = field(o2, "_binding"); @@ -65,19 +70,127 @@ int i2 = declarationOrder.indexOf(o2Binding); return i1 - i2; - } catch (Exception e) { - return 0; + } else { + if (Utils.isSubtype(enclosing1, enclosing2)) { + return 1; + } else if (Utils.isSubtype(enclosing2, enclosing1)) { + return -1; + } else { + return 0; + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + return elements; + } + + private static List<Object> lookupDeclarationOrder(Map<TypeElement, List<Object>> declarationOrders, TypeElement type) throws Exception, ClassNotFoundException { + if (declarationOrders.containsKey(type)) { + return declarationOrders.get(type); + } + + Object binding = field(type, "_binding"); + Class<?> sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding"); + Class<?> binaryTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding"); + + List<Object> declarationOrder = null; + if (sourceTypeBinding.isAssignableFrom(binding.getClass())) { + declarationOrder = findSourceTypeOrder(binding); + } else if (binaryTypeBinding.isAssignableFrom(binding.getClass())) { + declarationOrder = findBinaryTypeOrder(binding); + } + + declarationOrders.put(type, declarationOrder); + + return declarationOrder; + } + + private static List<Object> findBinaryTypeOrder(Object binding) throws Exception { + Object binaryType = lookupBinaryType(binding); + final Object[] sortedMethods = (Object[]) method(binaryType, "getMethods"); + + List<Object> sortedElements = new ArrayList<>(); + if (sortedMethods != null) { + sortedElements.addAll(Arrays.asList(sortedMethods)); + } + final Object[] sortedFields = (Object[]) method(binaryType, "getFields"); + if (sortedFields != null) { + sortedElements.addAll(Arrays.asList(sortedFields)); + } + final Object[] sortedTypes = (Object[]) method(binaryType, "getMemberTypes", new Class[0]); + if (sortedTypes != null) { + sortedElements.addAll(Arrays.asList(sortedTypes)); + } + + Collections.sort(sortedElements, new Comparator<Object>() { + public int compare(Object o1, Object o2) { + try { + int structOffset1 = (int) field(o1, "structOffset"); + int structOffset2 = (int) field(o2, "structOffset"); + return structOffset1 - structOffset2; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + Class<?> binaryMethod = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryMethod"); + Class<?> binaryField = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryField"); + Class<?> nestedType = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryNestedType"); + + List<Object> bindings = new ArrayList<>(); + for (Object sortedElement : sortedElements) { + Class<?> elementClass = sortedElement.getClass(); + if (binaryMethod.isAssignableFrom(elementClass)) { + char[] selector = (char[]) method(sortedElement, "getSelector"); + Object[] foundBindings = (Object[]) method(binding, "getMethods", new Class[]{char[].class}, selector); + if (foundBindings == null || foundBindings.length == 0) { + continue; + } else if (foundBindings.length == 1) { + bindings.add(foundBindings[0]); + } else { + char[] idescriptor = (char[]) method(sortedElement, "getMethodDescriptor"); + for (Object foundBinding : foundBindings) { + char[] descriptor = (char[]) method(foundBinding, "signature"); + if (descriptor == null && idescriptor == null || Arrays.equals(descriptor, idescriptor)) { + bindings.add(foundBinding); + break; + } } } + } else if (binaryField.isAssignableFrom(elementClass)) { + char[] selector = (char[]) method(sortedElement, "getName"); + Object foundField = method(binding, "getField", new Class[]{char[].class, boolean.class}, selector, true); + if (foundField != null) { + bindings.add(foundField); + } + } else if (nestedType.isAssignableFrom(elementClass)) { + char[] selector = (char[]) method(sortedElement, "getSourceName"); + Object foundType = method(binding, "getMemberType", new Class[]{char[].class}, selector); + if (foundType != null) { + bindings.add(foundType); + } + } else { + throw new AssertionError("Unexpected encountered type " + elementClass); + } + } - }); - return enclosedElements; - } catch (Exception e) { - return null; - } + return bindings; } - private static List<Object> findSourceOrder(Object binding) throws Exception { + private static Object lookupBinaryType(Object binding) throws Exception { + Object lookupEnvironment = field(binding, "environment"); + Object compoundClassName = field(binding, "compoundName"); + Object nameEnvironment = field(lookupEnvironment, "nameEnvironment"); + Object nameEnvironmentAnswer = method(nameEnvironment, "findType", new Class[]{char[][].class}, compoundClassName); + Object binaryType = method(nameEnvironmentAnswer, "getBinaryType", new Class[0]); + return binaryType; + } + + private static List<Object> findSourceTypeOrder(Object binding) throws Exception { Object referenceContext = field(field(binding, "scope"), "referenceContext"); TreeMap<Integer, Object> orderedBindings = new TreeMap<>();