1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System;
6 using System.Collections.Generic;
7 using System.Collections.Immutable;
8 using System.IO;
9 
10 namespace ILCompiler.DependencyAnalysisFramework
11 {
12     /// <summary>
13     /// Api for dependency analyzer. The expected use pattern is that a set of nodes will be added to the
14     /// graph as roots. These nodes will internally implement the various dependency details
15     /// so that if MarkedNodeList is called, it can produce the complete graph. For the case
16     /// where nodes have deferred computation the ComputeDependencyRoutine even will be triggered
17     /// to fill in data.
18     ///
19     /// The Log visitor logic can be called at any time, and should log the current set of marked
20     /// nodes and edges in the analysis. (Notably, if its called before MarkedNodeList is evaluated
21     /// it will contain only roots, if its called during, the edges/nodes may be incomplete, and
22     /// if called after MarkedNodeList is computed it will be a complete graph.
23     ///
24     /// </summary>
25     /// <typeparam name="DependencyContextType"></typeparam>
26     public abstract class DependencyAnalyzerBase<DependencyContextType>
27     {
28         /// <summary>
29         /// Add a root node
30         /// </summary>
AddRoot(DependencyNodeCore<DependencyContextType> rootNode, string reason)31         public abstract void AddRoot(DependencyNodeCore<DependencyContextType> rootNode, string reason);
32 
33         /// <summary>
34         /// Add a root node
35         /// </summary>
AddRoot(object rootNode, string reason)36         public void AddRoot(object rootNode, string reason)
37         {
38             AddRoot((DependencyNodeCore<DependencyContextType>)rootNode, reason);
39         }
40 
41         /// <summary>
42         /// Return the marked node list. Do not modify this list, as it will cause unexpected behavior.
43         /// Call <see cref="ComputeMarkedNodes"/> to compute the list first.
44         /// </summary>
45         public abstract ImmutableArray<DependencyNodeCore<DependencyContextType>> MarkedNodeList
46         {
47             get;
48         }
49 
50         /// <summary>
51         /// Computes the list of marked nodes. This is a no-op if the marked nodes are already computed.
52         /// The list is available as <see cref="MarkedNodeList"/>.
53         /// </summary>
ComputeMarkedNodes()54         public abstract void ComputeMarkedNodes();
55 
56         /// <summary>
57         /// This event is triggered when a node is added to the graph.
58         /// </summary>
59         public abstract event Action<DependencyNodeCore<DependencyContextType>> NewMarkedNode;
60 
61         /// <summary>
62         /// This event is triggered when the algorithm requires that dependencies of some set of
63         /// nodes be computed.
64         /// </summary>
65 
66         public abstract event Action<List<DependencyNodeCore<DependencyContextType>>> ComputeDependencyRoutine;
67 
68         /// <summary>
69         /// Used to walk all nodes that should be emitted to a log. Not intended for other purposes.
70         /// </summary>
71         /// <param name="logNodeVisitor"></param>
VisitLogNodes(IDependencyAnalyzerLogNodeVisitor<DependencyContextType> logNodeVisitor)72         public abstract void VisitLogNodes(IDependencyAnalyzerLogNodeVisitor<DependencyContextType> logNodeVisitor);
73 
74         /// <summary>
75         /// Used to walk the logical edges in the graph as part of log building.
76         /// </summary>
77         /// <param name="logEdgeVisitor"></param>
VisitLogEdges(IDependencyAnalyzerLogEdgeVisitor<DependencyContextType> logEdgeVisitor)78         public abstract void VisitLogEdges(IDependencyAnalyzerLogEdgeVisitor<DependencyContextType> logEdgeVisitor);
79     }
80 }
81