changeset 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 0e05342037d7
children 55fd5be68a52
files graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JDTCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java
diffstat 4 files changed, 161 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/AbstractCompiler.java	Mon Aug 11 15:53:05 2014 +0200
@@ -42,7 +42,23 @@
         if (o == null) {
             return null;
         }
-        Field field = o.getClass().getField(fieldName);
+        Class<?> clazz = o.getClass();
+        Field field = null;
+        try {
+            field = clazz.getField(fieldName);
+        } catch (NoSuchFieldException e) {
+            while (clazz != null) {
+                try {
+                    field = clazz.getDeclaredField(fieldName);
+                    break;
+                } catch (NoSuchFieldException e1) {
+                    clazz = clazz.getSuperclass();
+                }
+            }
+            if (field == null) {
+                throw e;
+            }
+        }
         field.setAccessible(true);
         return field.get(o);
     }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/Compiler.java	Mon Aug 11 15:53:05 2014 +0200
@@ -33,6 +33,8 @@
 
     String getHeaderComment(ProcessingEnvironment env, Element type);
 
-    List<? extends Element> getEnclosedElementsDeclarationOrder(TypeElement type);
+    List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type);
+
+    List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type);
 
 }
--- 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<>();
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java	Mon Aug 11 15:53:05 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/compiler/JavaCCompiler.java	Mon Aug 11 15:53:05 2014 +0200
@@ -40,10 +40,14 @@
         }
     }
 
-    public List<? extends Element> getEnclosedElementsDeclarationOrder(TypeElement type) {
+    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
         return type.getEnclosedElements();
     }
 
+    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
+        return environment.getElementUtils().getAllMembers(type);
+    }
+
     private static final Class<?>[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class};
     private static final Class<?>[] getCharContentSignature = new Class[]{boolean.class};