private void CreateChildren(object state) { IGraphContext context = (IGraphContext)state; using (GraphTransactionScope scope = new GraphTransactionScope()) { foreach (var node in context.InputNodes.Where(n => n.HasCategory(CssGraphSchema.CssAtDirectivesParent))) { CreateChild <AtDirective>(context, node, CssGraphSchema.CssAtDirectives); context.ReportProgress(1, 3, null); } foreach (var node in context.InputNodes.Where(n => n.HasCategory(CssGraphSchema.CssIdSelectorParent))) { CreateChild <IdSelector>(context, node, CssGraphSchema.CssIdSelector); context.ReportProgress(2, 3, null); } foreach (var node in context.InputNodes.Where(n => n.HasCategory(CssGraphSchema.CssClassSelectorParent))) { CreateChild <ClassSelector>(context, node, CssGraphSchema.CssClassSelector); context.ReportProgress(3, 3, null); } scope.Complete(); } context.OnCompleted(); }
private static async Task PopulateContextGraphAsync(Solution solution, List <IGraphQuery> graphQueries, IGraphContext context) { try { var cancellationToken = context.CancelToken; var graphBuilderTasks = graphQueries.Select(q => q.GetGraphAsync(solution, context, cancellationToken)).ToArray(); var graphBuilders = await Task.WhenAll(graphBuilderTasks).ConfigureAwait(false); // Perform the actual graph transaction using var transaction = new GraphTransactionScope(); // Remove any links that may have been added by a previous population. We don't // remove nodes to maintain node identity, matching the behavior of the old // providers. context.Graph.Links.Clear(); foreach (var graphBuilder in graphBuilders) { graphBuilder.ApplyToGraph(context.Graph); context.OutputNodes.AddAll(graphBuilder.CreatedNodes); } transaction.Complete(); } catch (Exception ex) when(FatalError.ReportWithoutCrashUnlessCanceledAndPropagate(ex)) { throw ExceptionUtilities.Unreachable; } }
private GraphNode GetOrCreateConfigNode(IGraphContext context, IItemNode packagesConfig) { var nodeId = packagesConfig.GetId(); var fileNode = context.Graph.Nodes.Get(nodeId); if (fileNode == null) { using (var scope = new GraphTransactionScope()) { fileNode = context.Graph.Nodes.GetOrCreate( nodeId, Path.GetFileName(packagesConfig.PhysicalPath), CodeNodeCategories.ProjectItem); if (!context.OutputNodes.Contains(fileNode)) { context.OutputNodes.Add(fileNode); } scope.Complete(); } } return(fileNode); }
private GraphNode GetOrCreatePackageNode(IGraphContext context, GraphNode parent, IVsPackageMetadata package) { var parentId = parent.GetValue <GraphNodeId>("Id"); var nodeId = GraphNodeId.GetNested( parentId, GraphNodeId.GetPartial(CodeGraphNodeIdName.Member, package.Id), GraphNodeId.GetPartial(CodeGraphNodeIdName.Parameter, package.VersionString)); var node = context.Graph.Nodes.Get(nodeId); if (node == null) { using (var scope = new GraphTransactionScope()) { node = context.Graph.Nodes.GetOrCreate(nodeId, package.Id, ReferencesGraphSchema.PackageCategory); node.SetValue <string>(DgmlNodeProperties.Icon, GraphIcons.Package); node.SetValue <IVsPackageMetadata>(ReferencesGraphSchema.PackageProperty, package); // Establish the relationship with the parent node. context.Graph.Links.GetOrCreate(parent, node, null, GraphCommonSchema.Contains); context.OutputNodes.Add(node); scope.Complete(); } } return(node); }
private async Task TrackChangesOnGraphContextAsync(IGraphContext graphContext, IDependenciesGraphProjectContext updatedProjectContext) { foreach (var inputGraphNode in graphContext.InputNodes) { var projectPath = GetPartialValueFromGraphNodeId(inputGraphNode.Id, CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(projectPath) || !projectPath.Equals(updatedProjectContext.ProjectFilePath, StringComparison.OrdinalIgnoreCase)) { continue; } var existingNodeInfo = inputGraphNode.GetValue <IDependencyNode>( DependenciesGraphSchema.DependencyNodeProperty); if (existingNodeInfo == null) { continue; } var subTreeProvider = await GetSubTreeProviderAsync(graphContext, inputGraphNode, projectPath, existingNodeInfo.Id).ConfigureAwait(false); if (subTreeProvider == null) { continue; } // Get updated reference from the new snapshot var updatedNodeInfo = subTreeProvider.GetDependencyNode(existingNodeInfo.Id); if (updatedNodeInfo == null) { continue; } using (var scope = new GraphTransactionScope()) { // Diff existing node children and updated node children to get whats removed var nodesToRemove = existingNodeInfo.Children.Except(updatedNodeInfo.Children); foreach (var nodeToRemove in nodesToRemove) { RemoveGraphNode(graphContext, projectPath, nodeToRemove); } // Diff updated node children and existing node children to get whats added var nodesToAdd = updatedNodeInfo.Children.Except(existingNodeInfo.Children); foreach (var nodeToAdd in nodesToAdd) { AddGraphNode(graphContext, projectPath, subTreeProvider, inputGraphNode, nodeToAdd); } // Update the node info saved on the 'inputNode' inputGraphNode.SetValue(DependenciesGraphSchema.DependencyNodeProperty, updatedNodeInfo); scope.Complete(); } } }
public override bool HandleChanges(IGraphContext graphContext, SnapshotChangedEventArgs e) { IDependenciesSnapshot snapshot = e.Snapshot; if (snapshot == null || e.Token.IsCancellationRequested) { return(false); } foreach (GraphNode inputGraphNode in graphContext.InputNodes.ToList()) { string existingDependencyId = inputGraphNode.GetValue <string>(DependenciesGraphSchema.DependencyIdProperty); if (string.IsNullOrEmpty(existingDependencyId)) { continue; } string projectPath = inputGraphNode.Id.GetValue(CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(projectPath)) { continue; } IDependency updatedDependency = GetDependency(projectPath, existingDependencyId, out IDependenciesSnapshot updatedSnapshot); if (updatedDependency == null) { continue; } IDependenciesGraphViewProvider viewProvider = ViewProviders .FirstOrDefaultValue((x, d) => x.SupportsDependency(d), updatedDependency); if (viewProvider == null) { continue; } if (!viewProvider.ShouldTrackChanges(projectPath, snapshot.ProjectPath, updatedDependency)) { continue; } using (var scope = new GraphTransactionScope()) { viewProvider.TrackChanges( graphContext, projectPath, updatedDependency, inputGraphNode, updatedSnapshot.Targets[updatedDependency.TargetFramework]); scope.Complete(); } } return(false); }
static void Main(string[] args) { if (args.Length == 0) { Console.WriteLine("Usage: ScrubGraph file.dgml"); Console.WriteLine("This tool removes Category='Active' on Nodes and removes all non-containment links"); Console.WriteLine("Thereby creating a nice 'template' graph that can be checked in"); return; } int removedCategories = 0; int removedLinks = 0; string fileName = args[0]; Graph g = Graph.Load(fileName, GraphCommonSchema.Schema, GraphLayoutSchema.Schema); using (var scope = new GraphTransactionScope()) { foreach (var node in g.Nodes) { foreach (var cat in node.Categories) { if (cat.Id == "Active") { removedCategories++; node.RemoveCategory(cat); break; } } } foreach (var link in g.Links.ToArray()) { if (!link.IsContainment) { removedLinks++; g.Links.Remove(link); } } scope.Complete(); } g.Save(fileName); if (removedLinks > 0) { Console.WriteLine("Removed {0} non containment links", removedLinks); } if (removedCategories > 0) { Console.WriteLine("Removed {0} active states", removedCategories); } if (removedCategories == 0 && removedLinks == 0) { Console.WriteLine("Graph is clean"); } }
private static void MarkThatNodesHaveChildren(IGraphContext context) { using (var scope = new GraphTransactionScope()) { foreach (var node in context.InputNodes.Where(IsMdFile)) { node.SetValue(DgmlNodeProperties.ContainsChildren, true); } scope.Complete(); } }
/// <summary> /// Checks if given node has children and adds corresponding IDependencyDescription to the node. /// </summary> private async Task CheckChildrenAsync(IGraphContext graphContext) { foreach (var inputGraphNode in graphContext.InputNodes) { if (graphContext.CancelToken.IsCancellationRequested) { return; } // All graph nodes generated here will have this unique node id, root node will have it equal to null var nodeIdString = GetPartialValueFromGraphNodeId(inputGraphNode.Id, CodeGraphNodeIdName.File); var nodeId = DependencyNodeId.FromString(nodeIdString); if (nodeId == null) { continue; } var projectPath = GetPartialValueFromGraphNodeId(inputGraphNode.Id, CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(projectPath)) { continue; } var subTreeProvider = await GetSubTreeProviderAsync(graphContext, inputGraphNode, projectPath, nodeId).ConfigureAwait(false); if (subTreeProvider == null) { continue; } IDependencyNode nodeInfo = subTreeProvider.GetDependencyNode(nodeId); if (nodeInfo == null) { continue; } using (var scope = new GraphTransactionScope()) { inputGraphNode.SetValue(DependenciesGraphSchema.ProviderProperty, subTreeProvider); inputGraphNode.SetValue(DependenciesGraphSchema.DependencyNodeProperty, nodeInfo); if (nodeInfo.HasChildren) { inputGraphNode.SetValue(DgmlNodeProperties.ContainsChildren, true); } scope.Complete(); } } }
public override bool HandleChanges(IGraphContext graphContext, SnapshotChangedEventArgs changes) { var snapshot = changes.Snapshot; if (snapshot == null) { return(false); } foreach (var inputGraphNode in graphContext.InputNodes.ToList()) { var existingDependency = inputGraphNode.GetValue <IDependency>( DependenciesGraphSchema.DependencyProperty); if (existingDependency == null) { continue; } var projectPath = inputGraphNode.Id.GetValue(CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(projectPath)) { continue; } var viewProvider = ViewProviders.FirstOrDefault(x => x.Value.SupportsDependency(existingDependency)); if (viewProvider == null) { continue; } if (!viewProvider.Value.ShouldTrackChanges(projectPath, snapshot.ProjectPath, existingDependency)) { continue; } var updatedDependency = GetDependency(projectPath, existingDependency.Id); if (updatedDependency == null) { continue; } using (var scope = new GraphTransactionScope()) { viewProvider.Value.TrackChanges( graphContext, projectPath, existingDependency, updatedDependency, inputGraphNode); scope.Complete(); } } return(false); }
public override bool HandleRequest(IGraphContext graphContext) { bool trackChanges = false; foreach (GraphNode inputGraphNode in graphContext.InputNodes) { if (graphContext.CancelToken.IsCancellationRequested) { return(trackChanges); } string projectPath = inputGraphNode.Id.GetValue(CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(projectPath)) { continue; } IDependency dependency = GetDependency(inputGraphNode, out IDependenciesSnapshot snapshot); if (dependency == null || snapshot == null) { continue; } IDependenciesGraphViewProvider viewProvider = ViewProviders .FirstOrDefaultValue((x, d) => x.SupportsDependency(d), dependency); if (viewProvider == null) { continue; } if (graphContext.TrackChanges) { trackChanges = true; } using (var scope = new GraphTransactionScope()) { viewProvider.BuildGraph( graphContext, projectPath, dependency, inputGraphNode, snapshot.Targets[dependency.TargetFramework]); scope.Complete(); } } return(trackChanges); }
public override bool HandleRequest(IGraphContext graphContext) { var trackChanges = false; foreach (var inputGraphNode in graphContext.InputNodes) { if (graphContext.CancelToken.IsCancellationRequested) { return(trackChanges); } var projectPath = inputGraphNode.Id.GetValue(CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(projectPath)) { continue; } var dependency = GetDependency(graphContext, inputGraphNode); if (dependency == null) { continue; } var viewProvider = ViewProviders.FirstOrDefault(x => x.Value.SupportsDependency(dependency)); if (viewProvider == null) { continue; } if (dependency.Flags.Contains(DependencyTreeFlags.SupportsHierarchy)) { trackChanges = true; } using (var scope = new GraphTransactionScope()) { inputGraphNode.SetValue(DependenciesGraphSchema.DependencyProperty, dependency); if (viewProvider.Value.HasChildren(projectPath, dependency)) { inputGraphNode.SetValue(DgmlNodeProperties.ContainsChildren, true); } scope.Complete(); } } return(trackChanges); }
private void Prepare(IGraphContext context) { GraphNode selectedNode = context.InputNodes.FirstOrDefault(node => node.IsPaketDependenciesNode() || node.IsPaketReferencesNode()); if (selectedNode == null) { return; } using (GraphTransactionScope transactionScope = new GraphTransactionScope()) { selectedNode.SetValue(DgmlNodeProperties.ContainsChildren, true); selectedNode.AddCategory(PaketGraphSchema.PaketCategory); transactionScope.Complete(); } }
public sealed override bool TryHandleRequest(IGraphContext graphContext) { if (!CanHandle(graphContext)) { return(false); } bool trackChanges = false; foreach (GraphNode inputGraphNode in graphContext.InputNodes) { if (graphContext.CancelToken.IsCancellationRequested) { return(trackChanges); } string projectPath = inputGraphNode.Id.GetValue(CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(projectPath)) { continue; } IDependency dependency = FindDependency(inputGraphNode, out IDependenciesSnapshot snapshot); if (dependency == null || snapshot == null) { continue; } IDependenciesGraphViewProvider viewProvider = FindViewProvider(dependency); if (viewProvider == null) { continue; } using (var scope = new GraphTransactionScope()) { ProcessInputNode(graphContext, inputGraphNode, dependency, snapshot, viewProvider, projectPath, ref trackChanges); scope.Complete(); } } return(trackChanges); }
public override bool HandleRequest(IGraphContext graphContext) { foreach (GraphNode inputGraphNode in graphContext.InputNodes) { if (graphContext.CancelToken.IsCancellationRequested) { return(false); } string projectPath = inputGraphNode.Id.GetValue(CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(projectPath)) { continue; } IDependency dependency = GetDependency(inputGraphNode, out IDependenciesSnapshot snapshot); if (dependency == null || snapshot == null) { continue; } IDependenciesGraphViewProvider viewProvider = ViewProviders .FirstOrDefaultValue((x, d) => x.SupportsDependency(d), dependency); if (viewProvider == null) { continue; } using (var scope = new GraphTransactionScope()) { inputGraphNode.SetValue(DependenciesGraphSchema.DependencyIdProperty, dependency.Id); inputGraphNode.SetValue(DependenciesGraphSchema.ResolvedProperty, dependency.Resolved); if (viewProvider.HasChildren(projectPath, dependency)) { inputGraphNode.SetValue(DgmlNodeProperties.ContainsChildren, true); } scope.Complete(); } } return(false); }
private void CreateOutline(IGraphContext context) { using (var scope = new GraphTransactionScope()) { context.Graph.Links.Remove(context.Graph.Links.Where(l => l.Label == "mixin" || l.Label == "hat")); foreach (GraphNode node in GetAllowedFiles(context.InputNodes)) { Uri url = node.Id.GetNestedValueByName <Uri>(CodeGraphNodeIdName.File); _cache[url] = context; node.AddCategory(LessGraphSchema.LessFile); CreateValues(context, node); } scope.Complete(); } }
private static void ProcessGraphTasks(GraphBuilder[] graphBuilders, IGraphContext context) { // Perform the actual graph transaction using var transaction = new GraphTransactionScope(); // Remove any links that may have been added by a previous population. We don't // remove nodes to maintain node identity, matching the behavior of the old // providers. context.Graph.Links.Clear(); foreach (var graphBuilder in graphBuilders) { graphBuilder.ApplyToGraph(context.Graph); context.OutputNodes.AddAll(graphBuilder.CreatedNodes); } transaction.Complete(); }
public void ApplyToGraph(Graph graph) { using (_gate.DisposableWait()) { using (var graphTransaction = new GraphTransactionScope()) { graph.Merge(this.Graph); foreach (var deferredProperty in _deferredPropertySets) { var nodeToSet = graph.Nodes.Get(deferredProperty.Item1.Id); nodeToSet.SetValue(deferredProperty.Item2, deferredProperty.Item3); } graphTransaction.Complete(); } } }
/// <summary> /// Checks if given node has children and adds corresponding IDependencyDescription to the node. /// </summary> private async Task CheckChildrenAsync(IGraphContext graphContext) { foreach (var inputGraphNode in graphContext.InputNodes) { if (graphContext.CancelToken.IsCancellationRequested) { return; } var projectPath = GetPartialValueFromGraphNodeId(inputGraphNode.Id, CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(projectPath)) { continue; } var(node, subTreeProvider) = await GetDependencyNodeInfoAsync(graphContext, inputGraphNode, projectPath) .ConfigureAwait(false); if (node == null || subTreeProvider == null) { continue; } // refresh node node = subTreeProvider.GetDependencyNode(node.Id); if (node == null) { continue; } using (var scope = new GraphTransactionScope()) { inputGraphNode.SetValue(DependenciesGraphSchema.ProviderProperty, subTreeProvider); inputGraphNode.SetValue(DependenciesGraphSchema.DependencyNodeProperty, node); if (node.HasChildren) { inputGraphNode.SetValue(DgmlNodeProperties.ContainsChildren, true); } scope.Complete(); } } }
public override bool HandleRequest(IGraphContext graphContext) { var trackChanges = false; foreach (var inputGraphNode in graphContext.InputNodes) { if (graphContext.CancelToken.IsCancellationRequested) { return(trackChanges); } var projectPath = inputGraphNode.Id.GetValue(CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(projectPath)) { continue; } var dependency = GetDependency(graphContext, inputGraphNode); if (dependency == null) { continue; } var viewProvider = ViewProviders.FirstOrDefault(x => x.Value.SupportsDependency(dependency)); if (viewProvider == null) { continue; } if (graphContext.TrackChanges) { trackChanges = true; } using (var scope = new GraphTransactionScope()) { viewProvider.Value.BuildGraph(graphContext, projectPath, dependency, inputGraphNode); scope.Complete(); } } return(trackChanges); }
private void BeginGetGraphData(IGraphContext context, bool queueUserWorkItem) { if (context.Direction == GraphContextDirection.Self && context.RequestedProperties.Contains(DgmlNodeProperties.ContainsChildren)) { var configNode = context.InputNodes.FirstOrDefault(node => node.IsConfigNode()); if (configNode != null) { using (var scope = new GraphTransactionScope()) { configNode.SetValue(DgmlNodeProperties.ContainsChildren, true); scope.Complete(); } } } else if (context.Direction == GraphContextDirection.Contains) { var configNode = context.InputNodes.FirstOrDefault(node => node.IsConfigNode()); if (configNode != null) { if (queueUserWorkItem) { ThreadPool.QueueUserWorkItem(TryAddPackageNodes, context); } else { TryAddPackageNodes(context); } // Prevent OnCompleted since we're either doing it // async or synchronously and completing in AddPackageNodes. return; } } else if (context.Direction == GraphContextDirection.Custom) { StartSearch(context); return; } context.OnCompleted(); }
private void PopulateChildrenOfNodes(IGraphContext context) { using (var scope = new GraphTransactionScope()) { foreach (var file in context.InputNodes.Where(IsMdFile)) { Graph graph = file.Owner; var fn = file.Id.GetNestedValueByName <Uri>(CodeGraphNodeIdName.File).LocalPath; foreach (var heading in GetMdHeadings(file)) { GraphNodeId valueId = file.Id + GraphNodeId.GetPartial(MarkdownSchema.MdValueName, heading.Item1); GraphNode node = graph.Nodes.GetOrCreate(valueId, heading.Item1, MarkdownSchema.Heading); node.SetValue(CodeNodeProperties.SourceLocation, heading.Item2); GraphLink link = graph.Links.GetOrCreate(file, node, null, MarkdownSchema.File2HeadingLink); context.OutputNodes.Add(node); } } scope.Complete(); } }
private void AddPackageNodes(IGraphContext context, Func <GraphNode> parentNode, IEnumerable <IVsPackageMetadata> installedPackages, bool removeUninstalledNodes = true) { var allPackages = installedPackages.ToList(); var installedIds = new HashSet <Tuple <string, string> >(allPackages.Select(x => Tuple.Create(x.Id, x.VersionString))); if (removeUninstalledNodes) { // Remove nodes that aren't installed anymore. var toRemove = from node in context.OutputNodes where node.IsPackageNode() let installed = node.GetValue <IVsPackageMetadata>(ReferencesGraphSchema.PackageProperty) where installed != null && !installedIds.Contains(Tuple.Create(installed.Id, installed.VersionString)) select node; if (toRemove.Any()) { using (var scope = new GraphTransactionScope()) { toRemove.ToList().ForEach(node => node.Remove()); scope.Complete(); } } } var progress = 0; var count = allPackages.Count; foreach (var nugetPackage in allPackages) { var node = GetOrCreatePackageNode(context, parentNode(), nugetPackage); context.ReportProgress(++progress, count, null); if (context.CancelToken.IsCancellationRequested) { break; } context.CancelToken.ThrowIfCancellationRequested(); System.Threading.Thread.Sleep(100); } }
private void AddPackageNodes(IGraphContext context, Func <GraphNode> parentNode, IEnumerable <PaketMetadata> installedPackages) { var allPackages = installedPackages.ToList(); for (int index = 0; index < allPackages.Count; index++) { PaketMetadata paketMetadata = allPackages[index]; using (var scope = new GraphTransactionScope()) { CreateNode(context, parentNode(), paketMetadata); scope.Complete(); } context.ReportProgress(index, allPackages.Count, null); if (context.CancelToken.IsCancellationRequested) { break; } } }
private void CreateChildren(object state) { IGraphContext context = (IGraphContext)state; using (GraphTransactionScope scope = new GraphTransactionScope()) { foreach (var node in context.InputNodes.Where(n => n.HasCategory(LessGraphSchema.LessMixinParent))) { CreateChild <LessMixinDeclaration>(context, node, LessGraphSchema.LessMixin); context.ReportProgress(1, 2, null); } foreach (var node in context.InputNodes.Where(n => n.HasCategory(LessGraphSchema.LessVariableParent))) { CreateChild <LessVariableDeclaration>(context, node, LessGraphSchema.LessVariable); context.ReportProgress(2, 2, null); } scope.Complete(); } context.OnCompleted(); }
private void CreateOutline(object state) { IGraphContext context = (IGraphContext)state; using (var scope = new GraphTransactionScope()) { //context.Graph.Links.Clear(); //context.OutputNodes.Clear(); context.Graph.Links.Remove(context.Graph.Links.Where(l => l.Label == "dir" || l.Label == "id" || l.Label == "class")); foreach (GraphNode node in GetAllowedFiles(context.InputNodes)) { Uri url = node.Id.GetNestedValueByName <Uri>(CodeGraphNodeIdName.File); _cache[url] = context; node.AddCategory(CssGraphSchema.CssFile); CreateValues(context, node); } scope.Complete(); } }
/// <summary> /// Generates search graph containing nodes matching search criteria in Solution Explorer /// and attaches it to correct top level node. /// </summary> private void Search(IGraphContext graphContext) { var searchParametersTypeName = typeof(ISolutionSearchParameters).GUID.ToString(); var searchParameters = graphContext.GetValue <ISolutionSearchParameters>(searchParametersTypeName); if (searchParameters == null) { return; } var searchTerm = searchParameters.SearchQuery.SearchString?.ToLowerInvariant(); if (searchTerm == null) { return; } var cachedDependencyToMatchingResultsMap = new Dictionary <string, HashSet <IDependency> >(StringComparer.OrdinalIgnoreCase); var searchResultsPerContext = new Dictionary <string, HashSet <IDependency> >(StringComparer.OrdinalIgnoreCase); var snapshotProviders = AggregateSnapshotProvider.GetSnapshotProviders(); foreach (var snapshotProvider in snapshotProviders) { var snapshot = snapshotProvider.CurrentSnapshot; if (snapshot == null) { continue; } searchResultsPerContext[snapshotProvider.ProjectFilePath] = SearchFlat(snapshotProvider.ProjectFilePath, searchTerm.ToLowerInvariant(), graphContext, snapshot); } foreach (var snapshotProvider in snapshotProviders) { var snapshot = snapshotProvider.CurrentSnapshot; if (snapshot == null) { continue; } var allTopLevelDependencies = snapshot.GetFlatTopLevelDependencies(); var matchedDependencies = searchResultsPerContext[snapshotProvider.ProjectFilePath]; using (var scope = new GraphTransactionScope()) { foreach (var topLevelDependency in allTopLevelDependencies) { var targetedSnapshot = snapshot.Targets[topLevelDependency.TargetFramework]; if (!cachedDependencyToMatchingResultsMap .TryGetValue(topLevelDependency.Id, out HashSet <IDependency> topLevelDependencyMatches)) { var viewProvider = ViewProviders.FirstOrDefault(x => x.Value.SupportsDependency(topLevelDependency)); if (viewProvider == null) { continue; } var processed = viewProvider.Value.MatchSearchResults( snapshotProvider.ProjectFilePath, topLevelDependency, searchResultsPerContext, out topLevelDependencyMatches); if (!processed) { if (matchedDependencies.Count == 0) { continue; } topLevelDependencyMatches = GetMatchingResultsForDependency( topLevelDependency, targetedSnapshot, matchedDependencies, cachedDependencyToMatchingResultsMap); } cachedDependencyToMatchingResultsMap[topLevelDependency.Id] = topLevelDependencyMatches; } if (topLevelDependencyMatches.Count == 0) { continue; } var topLevelNode = Builder.AddTopLevelGraphNode(graphContext, snapshotProvider.ProjectFilePath, topLevelDependency.ToViewModel(targetedSnapshot)); foreach (var matchedDependency in topLevelDependencyMatches) { var matchedDependencyNode = Builder.AddGraphNode(graphContext, snapshotProvider.ProjectFilePath, topLevelNode, matchedDependency.ToViewModel(targetedSnapshot)); graphContext.Graph.Links.GetOrCreate(topLevelNode, matchedDependencyNode, null /*label*/, GraphCommonSchema.Contains); } if (topLevelNode != null) { // 'node' is a GraphNode for top level dependency (which is part of solution explorer tree) // Setting ProjectItem category (and correct GraphNodeId) ensures that search graph appears // under right solution explorer hierarchy item topLevelNode.AddCategory(CodeNodeCategories.ProjectItem); } } scope.Complete(); } } graphContext.OnCompleted(); }
private void CreateChildren(object state) { IGraphContext context = (IGraphContext)state; using (GraphTransactionScope scope = new GraphTransactionScope()) { foreach (var node in context.InputNodes.Where(n => n.HasCategory(CssGraphSchema.CssAtDirectivesParent))) { CreateChild<AtDirective>(context, node, CssGraphSchema.CssAtDirectives); context.ReportProgress(1, 3, null); } foreach (var node in context.InputNodes.Where(n => n.HasCategory(CssGraphSchema.CssIdSelectorParent))) { CreateChild<IdSelector>(context, node, CssGraphSchema.CssIdSelector); context.ReportProgress(2, 3, null); } foreach (var node in context.InputNodes.Where(n => n.HasCategory(CssGraphSchema.CssClassSelectorParent))) { CreateChild<ClassSelector>(context, node, CssGraphSchema.CssClassSelector); context.ReportProgress(3, 3, null); } scope.Complete(); } context.OnCompleted(); }
private async Task TrackChangesOnGraphContextAsync(IGraphContext graphContext, IDependenciesGraphProjectContext updatedProjectContext) { foreach (var inputGraphNode in graphContext.InputNodes.ToList()) { var existingNodeInfo = inputGraphNode.GetValue <IDependencyNode>( DependenciesGraphSchema.DependencyNodeProperty); if (existingNodeInfo == null) { continue; } var projectPath = GetPartialValueFromGraphNodeId(inputGraphNode.Id, CodeGraphNodeIdName.Assembly); bool shouldProcess = !string.IsNullOrEmpty(projectPath) && projectPath.Equals(updatedProjectContext.ProjectFilePath, StringComparison.OrdinalIgnoreCase); var contextProject = updatedProjectContext.ProjectFilePath; if (!shouldProcess) { shouldProcess = !string.IsNullOrEmpty(existingNodeInfo.Id.ContextProject) && existingNodeInfo.Id.ContextProject.Equals(updatedProjectContext.ProjectFilePath, StringComparison.OrdinalIgnoreCase); } if (!shouldProcess) { continue; } var subTreeProvider = await GetSubTreeProviderAsync(graphContext, inputGraphNode, projectPath, existingNodeInfo.Id).ConfigureAwait(false); if (subTreeProvider == null) { continue; } // store existing children, since existingNodeInfo instance might be updated // (this is a side effect for top level nodes) var existingChildren = new HashSet <IDependencyNode>(existingNodeInfo.Children); // Get updated reference from the new snapshot var updatedNodeInfo = subTreeProvider.GetDependencyNode(existingNodeInfo.Id); if (updatedNodeInfo == null) { continue; } using (var scope = new GraphTransactionScope()) { var comparer = new DependencyNodeResolvedStateComparer(); // Diff existing node children and updated node children to get whats removed var nodesToRemove = existingChildren.Except(updatedNodeInfo.Children, comparer).ToList(); // Diff updated node children and existing node children to get whats added var nodesToAdd = updatedNodeInfo.Children.Except(existingChildren, comparer).ToList(); foreach (var nodeToRemove in nodesToRemove) { RemoveGraphNode(graphContext, contextProject, nodeToRemove); existingNodeInfo.RemoveChild(nodeToRemove); } foreach (var nodeToAdd in nodesToAdd) { AddGraphNode(graphContext, contextProject, null, inputGraphNode, nodeToAdd); existingNodeInfo.AddChild(nodeToAdd); } // Update the node info saved on the 'inputNode' inputGraphNode.SetValue(DependenciesGraphSchema.DependencyNodeProperty, updatedNodeInfo); scope.Complete(); } } }
/// <summary> /// Generates search graph containing nodes matching search criteria in Solution Explorer /// and attaches it to correct top level node. /// </summary> private async Task SearchAsync(IGraphContext graphContext) { var searchParametersTypeName = typeof(ISolutionSearchParameters).GUID.ToString(); var searchParameters = graphContext.GetValue <ISolutionSearchParameters>(searchParametersTypeName); if (searchParameters == null) { return; } var searchTerm = searchParameters.SearchQuery.SearchString?.ToLowerInvariant(); if (searchTerm == null) { return; } var projectContexts = ProjectContextProvider.GetProjectContexts(); foreach (var projectContext in projectContexts) { var subTreeProviders = projectContext.GetProviders(); foreach (var subTreeProvider in subTreeProviders) { await RegisterSubTreeProviderAsync(subTreeProvider, graphContext).ConfigureAwait(false); foreach (var topLevelNode in subTreeProvider.RootNode.Children) { var refreshedTopLevelNode = subTreeProvider.GetDependencyNode(topLevelNode.Id); if (refreshedTopLevelNode == null) { continue; } var matchingNodes = await subTreeProvider.SearchAsync(refreshedTopLevelNode, searchTerm).ConfigureAwait(true); if (matchingNodes == null || matchingNodes.Count() <= 0) { continue; } // Note: scope should start and complete on the same thread, so we have to do it for each provider. using (var scope = new GraphTransactionScope()) { // add provider's root node to display matching nodes var topLevelGraphNode = AddTopLevelGraphNode(graphContext, projectContext.ProjectFilePath, subTreeProvider, nodeInfo: refreshedTopLevelNode); // now recursively add graph nodes for provider nodes that match search criteria under // provider's root node AddNodesToGraphRecursive(graphContext, projectContext.ProjectFilePath, subTreeProvider, topLevelGraphNode, matchingNodes); // 'node' is a GraphNode for top level dependency (which is part of solution explorer tree) // Setting ProjectItem category (and correct GraphNodeId) ensures that search graph appears // under right solution explorer hierarchy item topLevelGraphNode.AddCategory(CodeNodeCategories.ProjectItem); scope.Complete(); } } } } graphContext.OnCompleted(); }
private void CreateOutline(object state) { IGraphContext context = (IGraphContext)state; using (var scope = new GraphTransactionScope()) { //context.Graph.Links.Clear(); //context.OutputNodes.Clear(); context.Graph.Links.Remove(context.Graph.Links.Where(l => l.Label == "dir" || l.Label == "id" || l.Label == "class")); foreach (GraphNode node in GetAllowedFiles(context.InputNodes)) { Uri url = node.Id.GetNestedValueByName<Uri>(CodeGraphNodeIdName.File); _cache[url] = context; node.AddCategory(CssGraphSchema.CssFile); CreateValues(context, node); } scope.Complete(); } }
/// <summary> /// ProjectContextChanged gets fired every time dependencies change for projects across solution. /// <see cref="_expandedGraphContexts"/> contains all nodes that we need to check for potential updates /// in their child dependencies. /// </summary> private void OnSnapshotChanged(object sender, SnapshotChangedEventArgs e) { DependenciesSnapshot snapshot = e.Snapshot; if (snapshot == null || e.Token.IsCancellationRequested) { return; } // _expandedGraphContexts remembers graph expanded or checked so far. // Each context represents one level in the graph, i.e. a node and its first level dependencies // Tracking changes over all expanded contexts ensures that all levels are processed // and updated when there are any changes in nodes data. lock (_lock) { foreach (IGraphContext graphContext in _expandedGraphContexts) { if (e.Token.IsCancellationRequested) { return; } bool anyChanges = false; try { if (HandleChanges(graphContext)) { anyChanges = true; } } finally { // Calling OnCompleted ensures that the changes are reflected in UI if (anyChanges) { graphContext.OnCompleted(); } } } } return; bool HandleChanges(IGraphContext graphContext) { bool anyChanges = false; foreach (GraphNode inputGraphNode in graphContext.InputNodes.ToList()) { string?existingDependencyId = inputGraphNode.GetValue <string>(DependenciesGraphSchema.DependencyIdProperty); if (string.IsNullOrEmpty(existingDependencyId)) { continue; } string?nodeProjectPath = inputGraphNode.Id.GetValue(CodeGraphNodeIdName.Assembly); if (string.IsNullOrEmpty(nodeProjectPath)) { continue; } DependenciesSnapshot?updatedSnapshot = _aggregateSnapshotProvider.GetSnapshot(nodeProjectPath !); IDependency?updatedDependency = updatedSnapshot?.FindDependency(existingDependencyId); if (updatedDependency == null) // or updatedSnapshot == null { continue; } IDependenciesGraphViewProvider?viewProvider = _viewProviders .FirstOrDefaultValue((x, d) => x.SupportsDependency(d), updatedDependency); if (viewProvider == null) { continue; } if (!viewProvider.ShouldApplyChanges(nodeProjectPath !, snapshot.ProjectPath, updatedDependency)) { continue; } using var scope = new GraphTransactionScope(); if (viewProvider.ApplyChanges( graphContext, nodeProjectPath !, updatedDependency, inputGraphNode, updatedSnapshot !.DependenciesByTargetFramework[updatedDependency.TargetFramework])) { anyChanges = true; } scope.Complete(); } return(anyChanges); } }
private void CreateOutline(IGraphContext context) { using (var scope = new GraphTransactionScope()) { context.Graph.Links.Remove(context.Graph.Links.Where(l => l.Label == "mixin" || l.Label == "hat")); foreach (GraphNode node in GetAllowedFiles(context.InputNodes)) { Uri url = node.Id.GetNestedValueByName<Uri>(CodeGraphNodeIdName.File); _cache[url] = context; node.AddCategory(LessGraphSchema.LessFile); CreateValues(context, node); } scope.Complete(); } }
private void CreateChildren(object state) { IGraphContext context = (IGraphContext)state; using (GraphTransactionScope scope = new GraphTransactionScope()) { foreach (var node in context.InputNodes.Where(n => n.HasCategory(LessGraphSchema.LessMixinParent))) { CreateChild<LessMixinDeclaration>(context, node, LessGraphSchema.LessMixin); context.ReportProgress(1, 2, null); } foreach (var node in context.InputNodes.Where(n => n.HasCategory(LessGraphSchema.LessVariableParent))) { CreateChild<LessVariableDeclaration>(context, node, LessGraphSchema.LessVariable); context.ReportProgress(2, 2, null); } scope.Complete(); } context.OnCompleted(); }
/// <summary> /// Generates search graph containing nodes matching search criteria in Solution Explorer /// and attaches it to correct top level node. /// </summary> private void Search(IGraphContext graphContext) { string searchParametersTypeName = typeof(ISolutionSearchParameters).GUID.ToString(); ISolutionSearchParameters searchParameters = graphContext.GetValue <ISolutionSearchParameters>(searchParametersTypeName); string?searchTerm = searchParameters?.SearchQuery.SearchString; if (searchTerm == null) { return; } var cachedDependencyToMatchingResultsMap = new Dictionary <string, HashSet <IDependency> >(StringComparer.OrdinalIgnoreCase); var searchResultsPerContext = new Dictionary <string, HashSet <IDependency> >(StringComparer.OrdinalIgnoreCase); System.Collections.Generic.IReadOnlyCollection <IDependenciesSnapshot> snapshots = AggregateSnapshotProvider.GetSnapshots(); foreach (IDependenciesSnapshot snapshot in snapshots) { searchResultsPerContext[snapshot.ProjectPath] = SearchFlat( searchTerm, snapshot); } foreach (IDependenciesSnapshot snapshot in snapshots) { IEnumerable <IDependency> allTopLevelDependencies = snapshot.GetFlatTopLevelDependencies(); HashSet <IDependency> matchedDependencies = searchResultsPerContext[snapshot.ProjectPath]; using var scope = new GraphTransactionScope(); foreach (IDependency topLevelDependency in allTopLevelDependencies) { ITargetedDependenciesSnapshot targetedSnapshot = snapshot.DependenciesByTargetFramework[topLevelDependency.TargetFramework]; if (!cachedDependencyToMatchingResultsMap .TryGetValue(topLevelDependency.Id, out HashSet <IDependency>?topLevelDependencyMatches)) { IDependenciesGraphViewProvider?viewProvider = FindViewProvider(topLevelDependency); if (viewProvider == null) { continue; } if (!viewProvider.MatchSearchResults( topLevelDependency, searchResultsPerContext, out topLevelDependencyMatches)) { if (matchedDependencies.Count == 0) { continue; } topLevelDependencyMatches = GetMatchingResultsForDependency( topLevelDependency, targetedSnapshot, matchedDependencies, cachedDependencyToMatchingResultsMap); } cachedDependencyToMatchingResultsMap[topLevelDependency.Id] = topLevelDependencyMatches; } if (topLevelDependencyMatches.Count == 0) { continue; } GraphNode topLevelNode = _builder.AddTopLevelGraphNode(graphContext, snapshot.ProjectPath, topLevelDependency.ToViewModel(targetedSnapshot)); foreach (IDependency matchedDependency in topLevelDependencyMatches) { GraphNode matchedDependencyNode = _builder.AddGraphNode(graphContext, snapshot.ProjectPath, topLevelNode, matchedDependency.ToViewModel(targetedSnapshot)); graphContext.Graph.Links.GetOrCreate(topLevelNode, matchedDependencyNode, label: null, GraphCommonSchema.Contains); } if (topLevelNode != null) { // 'node' is a GraphNode for top level dependency (which is part of solution explorer tree) // Setting ProjectItem category (and correct GraphNodeId) ensures that search graph appears // under right solution explorer hierarchy item topLevelNode.AddCategory(CodeNodeCategories.ProjectItem); } } scope.Complete(); } graphContext.OnCompleted(); }
private static void ProcessGraphTasks(GraphBuilder[] graphBuilders, IGraphContext context) { // Perform the actual graph transaction using (var transaction = new GraphTransactionScope()) { // Remove any links that may have been added by a previous population. We don't // remove nodes to maintain node identity, matching the behavior of the old // providers. context.Graph.Links.Clear(); foreach (var graphBuilder in graphBuilders) { graphBuilder.ApplyToGraph(context.Graph); context.OutputNodes.AddAll(graphBuilder.CreatedNodes); } transaction.Complete(); } }