src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java
changeset 49873 26ebfe8ce852
parent 47798 9fe9292f5931
child 50858 2d3e99a72541
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java	Tue Apr 24 08:13:30 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java	Tue Apr 24 09:04:57 2018 -0700
@@ -24,7 +24,10 @@
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.nio.channels.WritableByteChannel;
+import java.util.Collections;
 import java.util.Map;
 
 /**
@@ -34,9 +37,9 @@
  * @param <M> the type of methods this instance handles
  */
 public final class GraphOutput<G, M> implements Closeable {
-    private final GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?> printer;
+    private final GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?, ?> printer;
 
-    private GraphOutput(GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?> p) {
+    private GraphOutput(GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?, ?> p) {
         this.printer = p;
     }
 
@@ -110,7 +113,8 @@
      */
     public static final class Builder<G, N, M> {
         private final GraphStructure<G, N, ?, ?> structure;
-        private GraphElements<M, ?, ?, ?> elements = null;
+        private ElementsAndLocations<M, ?, ?> elementsAndLocations;
+
         private GraphTypes types = DefaultGraphTypes.DEFAULT;
         private GraphBlocks<G, ?, N> blocks = DefaultGraphBlocks.empty();
         private int major = 4;
@@ -164,9 +168,24 @@
          * @param graphElements the elements implementation
          * @return this builder
          */
+        public <E, P> Builder<G, N, E> elements(GraphElements<E, ?, ?, P> graphElements) {
+            StackLocations<E, P> loc = new StackLocations<>(graphElements);
+            return elementsAndLocations(graphElements, loc);
+        }
+
+        /**
+         * Associates implementation of graph elements and an advanced way to interpret their
+         * locations.
+         *
+         * @param graphElements the elements implementation
+         * @param graphLocations the locations for the elements
+         * @return this builder
+         * @since 0.33 GraalVM 0.33
+         */
         @SuppressWarnings({"unchecked", "rawtypes"})
-        public <E> Builder<G, N, E> elements(GraphElements<E, ?, ?, ?> graphElements) {
-            this.elements = (GraphElements) graphElements;
+        public <E, P> Builder<G, N, E> elementsAndLocations(GraphElements<E, ?, ?, P> graphElements, GraphLocations<E, P, ?> graphLocations) {
+            ElementsAndLocations both = new ElementsAndLocations<>(graphElements, graphLocations);
+            this.elementsAndLocations = both;
             return (Builder<G, N, E>) this;
         }
 
@@ -179,8 +198,7 @@
          * @throws IOException if something goes wrong when writing to the channel
          */
         public GraphOutput<G, M> build(WritableByteChannel channel) throws IOException {
-            ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?> p = new ProtocolImpl<>(major, minor, structure, types, blocks, elements, channel);
-            return new GraphOutput<>(p);
+            return buildImpl(elementsAndLocations, channel);
         }
 
         /**
@@ -200,8 +218,85 @@
          * @return new output sharing {@code channel} and other internals with {@code parent}
          */
         public GraphOutput<G, M> build(GraphOutput<?, ?> parent) {
-            ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?> p = new ProtocolImpl<>(parent.printer, structure, types, blocks, elements);
+            return buildImpl(elementsAndLocations, parent);
+        }
+
+        private <L, P> GraphOutput<G, M> buildImpl(ElementsAndLocations<M, L, P> e, WritableByteChannel channel) throws IOException {
+            // @formatter:off
+            ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?, ?> p = new ProtocolImpl<>(
+                major, minor, structure, types, blocks,
+                e == null ? null : e.elements,
+                e == null ? null : e.locations, channel
+            );
+            // @formatter:on
+            return new GraphOutput<>(p);
+        }
+
+        private <L, P> GraphOutput<G, M> buildImpl(ElementsAndLocations<M, L, P> e, GraphOutput<?, ?> parent) {
+            // @formatter:off
+            ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?, ?> p = new ProtocolImpl<>(
+                parent.printer, structure, types, blocks,
+                e == null ? null : e.elements,
+                e == null ? null : e.locations
+            );
+            // @formatter:on
             return new GraphOutput<>(p);
         }
     }
+
+    private static final class ElementsAndLocations<M, P, L> {
+        final GraphElements<M, ?, ?, P> elements;
+        final GraphLocations<M, P, L> locations;
+
+        ElementsAndLocations(GraphElements<M, ?, ?, P> elements, GraphLocations<M, P, L> locations) {
+            elements.getClass();
+            locations.getClass();
+            this.elements = elements;
+            this.locations = locations;
+        }
+    }
+
+    private static final class StackLocations<M, P> implements GraphLocations<M, P, StackTraceElement> {
+        private final GraphElements<M, ?, ?, P> graphElements;
+
+        StackLocations(GraphElements<M, ?, ?, P> graphElements) {
+            this.graphElements = graphElements;
+        }
+
+        @Override
+        public Iterable<StackTraceElement> methodLocation(M method, int bci, P pos) {
+            StackTraceElement ste = this.graphElements.methodStackTraceElement(method, bci, pos);
+            return Collections.singleton(ste);
+        }
+
+        @Override
+        public URI locationURI(StackTraceElement location) {
+            String path = location.getFileName();
+            try {
+                return path == null ? null : new URI(null, null, path, null);
+            } catch (URISyntaxException ex) {
+                throw new IllegalArgumentException(ex);
+            }
+        }
+
+        @Override
+        public int locationLineNumber(StackTraceElement location) {
+            return location.getLineNumber();
+        }
+
+        @Override
+        public String locationLanguage(StackTraceElement location) {
+            return "Java";
+        }
+
+        @Override
+        public int locationOffsetStart(StackTraceElement location) {
+            return -1;
+        }
+
+        @Override
+        public int locationOffsetEnd(StackTraceElement location) {
+            return -1;
+        }
+    }
 }