|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ILCompiler.DependencyAnalysisFramework
{
public struct FirstMarkLogStrategy<DependencyContextType> : IDependencyAnalysisMarkStrategy<DependencyContextType>
{
private sealed class MarkData
{
public MarkData(string reason, DependencyNodeCore<DependencyContextType> reason1, DependencyNodeCore<DependencyContextType> reason2)
{
Reason = reason;
Reason1 = reason1;
Reason2 = reason2;
}
public string Reason
{
get;
}
public DependencyNodeCore<DependencyContextType> Reason1
{
get;
}
public DependencyNodeCore<DependencyContextType> Reason2
{
get;
}
}
private HashSet<string> _reasonStringOnlyNodes;
bool IDependencyAnalysisMarkStrategy<DependencyContextType>.MarkNode(
DependencyNodeCore<DependencyContextType> node,
DependencyNodeCore<DependencyContextType> reasonNode,
DependencyNodeCore<DependencyContextType> reasonNode2,
string reason)
{
if (node.Marked)
return false;
if ((reasonNode == null) && (reasonNode2 == null))
{
Debug.Assert(reason != null);
_reasonStringOnlyNodes ??= new HashSet<string>();
_reasonStringOnlyNodes.Add(reason);
}
node.SetMark(new MarkData(reason, reasonNode, reasonNode2));
return true;
}
void IDependencyAnalysisMarkStrategy<DependencyContextType>.VisitLogNodes(IEnumerable<DependencyNodeCore<DependencyContextType>> nodeList, IDependencyAnalyzerLogNodeVisitor<DependencyContextType> logNodeVisitor)
{
var combinedNodesReported = new HashSet<Tuple<DependencyNodeCore<DependencyContextType>, DependencyNodeCore<DependencyContextType>>>();
if (_reasonStringOnlyNodes != null)
{
foreach (string reasonOnly in _reasonStringOnlyNodes)
{
logNodeVisitor.VisitRootNode(reasonOnly);
}
}
foreach (DependencyNodeCore<DependencyContextType> node in nodeList)
{
if (node.Marked)
{
MarkData markData = (MarkData)node.GetMark();
if (markData.Reason2 != null)
{
var combinedNode = new Tuple<DependencyNodeCore<DependencyContextType>, DependencyNodeCore<DependencyContextType>>(markData.Reason1, markData.Reason2);
if (combinedNodesReported.Add(combinedNode))
{
logNodeVisitor.VisitCombinedNode(combinedNode);
}
}
}
}
}
void IDependencyAnalysisMarkStrategy<DependencyContextType>.VisitLogEdges(IEnumerable<DependencyNodeCore<DependencyContextType>> nodeList, IDependencyAnalyzerLogEdgeVisitor<DependencyContextType> logEdgeVisitor)
{
foreach (DependencyNodeCore<DependencyContextType> node in nodeList)
{
if (node.Marked)
{
MarkData markData = (MarkData)node.GetMark();
if (markData.Reason2 != null)
{
Debug.Assert(markData.Reason1 != null);
logEdgeVisitor.VisitEdge(markData.Reason1, markData.Reason2, node, markData.Reason);
}
else if (markData.Reason1 != null)
{
logEdgeVisitor.VisitEdge(markData.Reason1, node, markData.Reason);
}
else
{
Debug.Assert(markData.Reason != null);
logEdgeVisitor.VisitEdge(markData.Reason, node);
}
}
}
}
void IDependencyAnalysisMarkStrategy<DependencyContextType>.AttachContext(DependencyContextType context)
{
// This logger does not need to use the context
}
}
}
|