langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Dependencies.java
changeset 33366 a113e08cc061
parent 30731 38eaf2ca243e
child 39599 3c7da4996d8c
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Dependencies.java	Wed Oct 21 18:40:01 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Dependencies.java	Thu Oct 22 09:05:54 2015 +0200
@@ -30,7 +30,7 @@
 import com.sun.tools.javac.code.Symbol.Completer;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
 import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.util.GraphUtils.DependencyKind;
 import com.sun.tools.javac.util.GraphUtils.DotVisitor;
 import com.sun.tools.javac.util.GraphUtils.NodeVisitor;
 
@@ -42,13 +42,13 @@
 import java.util.Collection;
 import java.util.EnumMap;
 import java.util.EnumSet;
-import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-import java.util.Set;
 import java.util.Stack;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import javax.tools.JavaFileObject;
 
@@ -78,69 +78,23 @@
     }
 
     /**
-     * This enum models different kinds of attribution actions triggered during
-     * symbol completion.
-     */
-    public enum AttributionKind {
-        /**
-         * Attribution of superclass (i.e. @{code extends} clause).
-         */
-        EXTENDS {
-            @Override
-            String format(JCTree tree) {
-                return "extends " + super.format(tree);
-            }
-        },
-        /**
-         * Attribution of superinterface (i.e. an type in the @{code interface} clause).
-         */
-        IMPLEMENTS {
-            @Override
-            String format(JCTree tree) {
-                return "implements " + super.format(tree);
-            }
-        },
-        /**
-         * Attribution of an import statement
-         */
-        IMPORT,
-        /**
-         * Attribution of type-variable bound
-         */
-        TVAR {
-            @Override
-            String format(JCTree tree) {
-                return "<" + super.format(tree) + ">";
-            }
-        };
-
-        String format(JCTree tree) {
-            return tree.toString();
-        }
-    }
-
-    /**
      * Push a new completion node on the stack.
      */
     abstract public void push(ClassSymbol s, CompletionCause phase);
 
     /**
-     * Push a new attribution node on the stack.
-     */
-    abstract public void push(AttributionKind ak, JCTree t);
-
-    /**
      * Remove current dependency node from the stack.
      */
     abstract public void pop();
 
-    public enum CompletionCause {
+    public enum CompletionCause implements GraphUtils.DependencyKind {
         CLASS_READER,
         HEADER_PHASE,
         HIERARCHY_PHASE,
         IMPORTS_PHASE,
         MEMBER_ENTER,
-        MEMBERS_PHASE;
+        MEMBERS_PHASE,
+        OTHER;
     }
 
     /**
@@ -163,13 +117,8 @@
         /**
          * Register a Context.Factory to create a Dependencies.
          */
-        public static void preRegister(final Context context) {
-            context.put(dependenciesKey, new Context.Factory<Dependencies>() {
-                public Dependencies make(Context c) {
-                    Dependencies deps = new GraphDependencies(context);
-                    return deps;
-                }
-            });
+        public static void preRegister(Context context) {
+            context.put(dependenciesKey, (Context.Factory<Dependencies>) GraphDependencies::new);
         }
 
         /**
@@ -195,12 +144,11 @@
         enum DependenciesMode {
             SOURCE("source"),
             CLASS("class"),
-            REDUNDANT("redundant"),
-            SIDE_EFFECTS("side-effects");
+            REDUNDANT("redundant");
 
             final String opt;
 
-            private DependenciesMode(String opt) {
+            DependenciesMode(String opt) {
                 this.opt = opt;
             }
 
@@ -228,46 +176,19 @@
         }
 
         /**
-         * Class representing a node in the dependency graph. Nodes are of two main
-         * kinds: (i) symbol nodes, corresponding to symbol completion requests
-         * (either from source or classfile); (ii) attribution nodes, corresponding to
-         * attribution actions triggered during (source) completion.
+         * Class representing a node in the dependency graph.
          */
-        public static abstract class Node extends GraphUtils.AbstractNode<String, Node>
-                implements GraphUtils.DottableNode<String, Node> {
-
-            /**
-             * Model the dependencies between nodes.
-             */
-            public enum DependencyKind implements GraphUtils.DependencyKind {
-                /**
-                 * standard dependency - i.e. completion of the source node depends
-                 * on completion of the sink node.
-                 */
-                REQUIRES("solid"),
-                /**
-                 * soft dependencies - i.e. completion of the source node depends
-                 * on side-effects of the source node. These dependencies are meant
-                 * to capture the order in which javac processes all dependants of a given node.
-                 */
-                SIDE_EFFECTS("dashed");
-
-                final String dotStyle;
-
-                DependencyKind(String dotStyle) {
-                    this.dotStyle = dotStyle;
-                }
-            }
-
+        public static abstract class Node extends GraphUtils.AbstractNode<ClassSymbol, Node>
+                implements GraphUtils.DottableNode<ClassSymbol, Node> {
             /**
              * dependant nodes grouped by kind
              */
-            EnumMap<DependencyKind, List<Node>> depsByKind;
+            EnumMap<CompletionCause, List<Node>> depsByKind;
 
-            Node(String value) {
+            Node(ClassSymbol value) {
                 super(value);
-                this.depsByKind = new EnumMap<>(DependencyKind.class);
-                for (DependencyKind depKind : DependencyKind.values()) {
+                this.depsByKind = new EnumMap<>(CompletionCause.class);
+                for (CompletionCause depKind : CompletionCause.values()) {
                     depsByKind.put(depKind, new ArrayList<Node>());
                 }
             }
@@ -281,8 +202,7 @@
 
             @Override
             public boolean equals(Object obj) {
-                return obj instanceof Node &&
-                        data.equals(((Node) obj).data);
+                return obj instanceof Node && data.equals(((Node) obj).data);
             }
 
             @Override
@@ -292,19 +212,12 @@
 
             @Override
             public GraphUtils.DependencyKind[] getSupportedDependencyKinds() {
-                return DependencyKind.values();
+                return CompletionCause.values();
             }
 
             @Override
-            public java.util.Collection<? extends Node> getDependenciesByKind(GraphUtils.DependencyKind dk) {
-                List<Node> deps = depsByKind.get(dk);
-                if (dk == DependencyKind.REQUIRES) {
-                    return deps;
-                } else {
-                    Set<Node> temp = new HashSet<>(deps);
-                    temp.removeAll(depsByKind.get(DependencyKind.REQUIRES));
-                    return temp;
-                }
+            public java.util.Collection<? extends Node> getDependenciesByKind(DependencyKind dk) {
+                return depsByKind.get(dk);
             }
 
             @Override
@@ -317,9 +230,14 @@
             @Override
             public Properties dependencyAttributes(Node to, GraphUtils.DependencyKind dk) {
                 Properties p = new Properties();
-                p.put("style", ((DependencyKind) dk).dotStyle);
+                p.put("label", dk);
                 return p;
             }
+
+            @Override
+            public String toString() {
+                return data.getQualifiedName().toString();
+            }
         }
 
         /**
@@ -349,11 +267,9 @@
             }
 
             final Kind ck;
-            final ClassSymbol sym;
 
             CompletionNode(ClassSymbol sym) {
-                super(sym.getQualifiedName().toString());
-                this.sym = sym;
+                super(sym);
                 //infer completion kind by looking at the symbol fields
                 boolean fromClass = (sym.classfile == null && sym.sourcefile == null) ||
                         (sym.classfile != null && sym.classfile.getKind() == JavaFileObject.Kind.CLASS);
@@ -371,27 +287,7 @@
             }
 
             public ClassSymbol getClassSymbol() {
-                return sym;
-            }
-        }
-
-        /**
-         * This is a dependency node used to model attribution actions triggered during
-         * source symbol completion. The possible kinds of attribution actions are
-         * captured in {@link AttributionNode}.
-         */
-        static class AttributionNode extends Node {
-
-            AttributionNode(AttributionKind ak, JCTree tree) {
-                super(ak.format(tree));
-            }
-
-            @Override
-            public Properties nodeAttributes() {
-                Properties p = super.nodeAttributes();
-                p.put("shape", "box");
-                p.put("style", "solid");
-                return p;
+                return data;
             }
         }
 
@@ -403,25 +299,20 @@
         /**
          * map containing all dependency nodes seen so far
          */
-        Map<String, Node> dependencyNodeMap = new LinkedHashMap<>();
+        Map<ClassSymbol, Node> dependencyNodeMap = new LinkedHashMap<>();
 
         @Override
         public void push(ClassSymbol s, CompletionCause phase) {
             Node n = new CompletionNode(s);
-            if (n == push(n)) {
+            if (n == push(n, phase)) {
                 s.completer = this;
             }
         }
 
-        @Override
-        public void push(AttributionKind ak, JCTree t) {
-            push(new AttributionNode(ak, t));
-        }
-
         /**
          * Push a new dependency on the stack.
          */
-        protected Node push(Node newNode) {
+        protected Node push(Node newNode, CompletionCause cc) {
             Node cachedNode = dependencyNodeMap.get(newNode.data);
             if (cachedNode == null) {
                 dependencyNodeMap.put(newNode.data, newNode);
@@ -430,7 +321,7 @@
             }
             if (!nodeStack.isEmpty()) {
                 Node currentNode = nodeStack.peek();
-                currentNode.addDependency(Node.DependencyKind.REQUIRES, newNode);
+                currentNode.addDependency(cc, newNode);
             }
             nodeStack.push(newNode);
             return newNode;
@@ -455,10 +346,6 @@
                 //filter source completions
                 new FilterVisitor(CompletionNode.Kind.CLASS).visit(dependencyNodeMap.values(), null);
             }
-            if (dependenciesModes.contains(DependenciesMode.SIDE_EFFECTS)) {
-                //add side-effects edges
-                new SideEffectVisitor().visit(dependencyNodeMap.values(), null);
-            }
             if (dependenciesFile != null) {
                 //write to file
                 try (FileWriter fw = new FileWriter(dependenciesFile)) {
@@ -469,7 +356,7 @@
 
         @Override
         public void complete(Symbol sym) throws CompletionFailure {
-            push((ClassSymbol) sym, null);
+            push((ClassSymbol)sym, CompletionCause.OTHER);
             pop();
             sym.completer = this;
         }
@@ -484,31 +371,9 @@
         }
 
         /**
-         * This visitor is used to generate the special side-effect dependencies
-         * given a graph containing only standard dependencies.
-         */
-        private static class SideEffectVisitor extends NodeVisitor<String, Node, Void> {
-            @Override
-            public void visitNode(Node node, Void arg) {
-                //do nothing
-            }
-
-            @Override
-            public void visitDependency(GraphUtils.DependencyKind dk, Node from, Node to, Void arg) {
-                //if we are adding multiple dependencies to same node
-                //make order explicit via special 'side-effect' dependencies
-                List<Node> deps = from.depsByKind.get(dk);
-                int pos = deps.indexOf(to);
-                if (dk == Node.DependencyKind.REQUIRES && pos > 0) {
-                    to.addDependency(Node.DependencyKind.SIDE_EFFECTS, deps.get(pos - 1));
-                }
-            }
-        }
-
-        /**
          * This visitor is used to prune the graph from spurious edges using some heuristics.
          */
-        private static class PruneVisitor extends NodeVisitor<String, Node, Void> {
+        private static class PruneVisitor extends NodeVisitor<ClassSymbol, Node, Void> {
             @Override
             public void visitNode(Node node, Void arg) {
                 //do nothing
@@ -517,8 +382,7 @@
             @Override
             public void visitDependency(GraphUtils.DependencyKind dk, Node from, Node to, Void arg) {
                 //heuristic - skips dependencies that are likely to be fake
-                if (from.equals(to) ||
-                        from.depsByKind.get(Node.DependencyKind.REQUIRES).contains(to)) {
+                if (from.equals(to)) {
                     to.depsByKind.get(dk).remove(from);
                 }
             }
@@ -527,7 +391,7 @@
         /**
          * This visitor is used to retain only completion nodes with given kind.
          */
-        private class FilterVisitor extends NodeVisitor<String, Node, Void> {
+        private class FilterVisitor extends NodeVisitor<ClassSymbol, Node, Void> {
 
             CompletionNode.Kind ck;
 
@@ -571,11 +435,6 @@
         }
 
         @Override
-        public void push(AttributionKind ak, JCTree t) {
-            //do nothing
-        }
-
-        @Override
         public void pop() {
             //do nothing
         }