40 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph; |
40 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph; |
41 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node; |
41 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node; |
42 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException; |
42 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException; |
43 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode; |
43 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode; |
44 |
44 |
|
45 import java.io.File; |
|
46 import java.io.FileWriter; |
|
47 import java.io.IOException; |
45 import java.util.ArrayList; |
48 import java.util.ArrayList; |
46 import java.util.Collection; |
49 import java.util.Collection; |
47 import java.util.Collections; |
50 import java.util.Collections; |
48 import java.util.EnumMap; |
51 import java.util.EnumMap; |
49 import java.util.EnumSet; |
52 import java.util.EnumSet; |
74 Log log; |
77 Log log; |
75 |
78 |
76 /** should the graph solver be used? */ |
79 /** should the graph solver be used? */ |
77 boolean allowGraphInference; |
80 boolean allowGraphInference; |
78 |
81 |
|
82 /** |
|
83 * folder in which the inference dependency graphs should be written. |
|
84 */ |
|
85 final private String dependenciesFolder; |
|
86 |
|
87 /** |
|
88 * List of graphs awaiting to be dumped to a file. |
|
89 */ |
|
90 private List<String> pendingGraphs; |
|
91 |
79 public static Infer instance(Context context) { |
92 public static Infer instance(Context context) { |
80 Infer instance = context.get(inferKey); |
93 Infer instance = context.get(inferKey); |
81 if (instance == null) |
94 if (instance == null) |
82 instance = new Infer(context); |
95 instance = new Infer(context); |
83 return instance; |
96 return instance; |
94 log = Log.instance(context); |
107 log = Log.instance(context); |
95 inferenceException = new InferenceException(diags); |
108 inferenceException = new InferenceException(diags); |
96 Options options = Options.instance(context); |
109 Options options = Options.instance(context); |
97 allowGraphInference = Source.instance(context).allowGraphInference() |
110 allowGraphInference = Source.instance(context).allowGraphInference() |
98 && options.isUnset("useLegacyInference"); |
111 && options.isUnset("useLegacyInference"); |
|
112 dependenciesFolder = options.get("dumpInferenceGraphsTo"); |
|
113 pendingGraphs = List.nil(); |
99 } |
114 } |
100 |
115 |
101 /** A value for prototypes that admit any type, including polymorphic ones. */ |
116 /** A value for prototypes that admit any type, including polymorphic ones. */ |
102 public static final Type anyPoly = new JCNoType(); |
117 public static final Type anyPoly = new JCNoType(); |
103 |
118 |
216 /* if the is no result info then we can clear the capture types |
231 /* if the is no result info then we can clear the capture types |
217 * cache without affecting any result info check |
232 * cache without affecting any result info check |
218 */ |
233 */ |
219 inferenceContext.captureTypeCache.clear(); |
234 inferenceContext.captureTypeCache.clear(); |
220 } |
235 } |
|
236 dumpGraphsIfNeeded(env.tree, msym, resolveContext); |
|
237 } |
|
238 } |
|
239 |
|
240 private void dumpGraphsIfNeeded(DiagnosticPosition pos, Symbol msym, Resolve.MethodResolutionContext rsContext) { |
|
241 int round = 0; |
|
242 try { |
|
243 for (String graph : pendingGraphs.reverse()) { |
|
244 Assert.checkNonNull(dependenciesFolder); |
|
245 Name name = msym.name == msym.name.table.names.init ? |
|
246 msym.owner.name : msym.name; |
|
247 String filename = String.format("%s@%s[mode=%s,step=%s]_%d.dot", |
|
248 name, |
|
249 pos.getStartPosition(), |
|
250 rsContext.attrMode(), |
|
251 rsContext.step, |
|
252 round); |
|
253 File dotFile = new File(dependenciesFolder, filename); |
|
254 try (FileWriter fw = new FileWriter(dotFile)) { |
|
255 fw.append(graph); |
|
256 } |
|
257 round++; |
|
258 } |
|
259 } catch (IOException ex) { |
|
260 Assert.error("Error occurred when dumping inference graph: " + ex.getMessage()); |
|
261 } finally { |
|
262 pendingGraphs = List.nil(); |
221 } |
263 } |
222 } |
264 } |
223 |
265 |
224 /** |
266 /** |
225 * Generate constraints from the generic method's return type. If the method |
267 * Generate constraints from the generic method's return type. If the method |
1638 */ |
1680 */ |
1639 void solve(GraphStrategy sstrategy) { |
1681 void solve(GraphStrategy sstrategy) { |
1640 checkWithinBounds(inferenceContext, warn); //initial propagation of bounds |
1682 checkWithinBounds(inferenceContext, warn); //initial propagation of bounds |
1641 InferenceGraph inferenceGraph = new InferenceGraph(stuckDeps); |
1683 InferenceGraph inferenceGraph = new InferenceGraph(stuckDeps); |
1642 while (!sstrategy.done()) { |
1684 while (!sstrategy.done()) { |
|
1685 if (dependenciesFolder != null) { |
|
1686 //add this graph to the pending queue |
|
1687 pendingGraphs = pendingGraphs.prepend(inferenceGraph.toDot()); |
|
1688 } |
1643 InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph); |
1689 InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph); |
1644 List<Type> varsToSolve = List.from(nodeToSolve.data); |
1690 List<Type> varsToSolve = List.from(nodeToSolve.data); |
1645 List<Type> saved_undet = inferenceContext.save(); |
1691 List<Type> saved_undet = inferenceContext.save(); |
1646 try { |
1692 try { |
1647 //repeat until all variables are solved |
1693 //repeat until all variables are solved |
1833 } |
1879 } |
1834 |
1880 |
1835 @Override |
1881 @Override |
1836 public Properties nodeAttributes() { |
1882 public Properties nodeAttributes() { |
1837 Properties p = new Properties(); |
1883 Properties p = new Properties(); |
1838 p.put("label", toString()); |
1884 p.put("label", "\"" + toString() + "\""); |
1839 return p; |
1885 return p; |
1840 } |
1886 } |
1841 |
1887 |
1842 @Override |
1888 @Override |
1843 public Properties dependencyAttributes(Node sink, GraphUtils.DependencyKind dk) { |
1889 public Properties dependencyAttributes(Node sink, GraphUtils.DependencyKind dk) { |