示例#1
0
        /// <summary>
        /// Returns an unconfigured project level contexts for given project file path.
        /// </summary>
        /// <param name="projectFilePath">Full path to project path.</param>
        /// <returns>
        /// Instance of <see cref="IDependenciesGraphProjectContext"/> or null if context was not found for given project file.
        /// </returns>
        public IDependenciesGraphProjectContext GetProjectContext(string projectFilePath)
        {
            if (string.IsNullOrEmpty(projectFilePath))
            {
                throw new ArgumentException(nameof(projectFilePath));
            }

            IDependenciesGraphProjectContext context = null;

            if (ProjectContexts.TryGetValue(projectFilePath, out context))
            {
                return(context);
            }

            context = ProjectExportProvider.GetExport <IDependenciesGraphProjectContext>(projectFilePath);
            if (context == null)
            {
                return(null);
            }

            ProjectContexts[projectFilePath] = context;
            context.ProjectContextChanged   += OnProjectContextChanged;
            context.ProjectContextUnloaded  += OnProjectContextUnloaded;

            return(context);
        }
示例#2
0
        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();
                }
            }
        }
示例#3
0
 /// <summary>
 /// Property ExpandedGraphContexts remembers graph expanded 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.
 /// </summary>
 internal async Task TrackChangesAsync(IDependenciesGraphProjectContext updatedProjectContext)
 {
     foreach (var graphContext in ExpandedGraphContexts.ToList())
     {
         try
         {
             await TrackChangesOnGraphContextAsync(graphContext, updatedProjectContext).ConfigureAwait(false);
         }
         finally
         {
             // Calling OnCompleted ensures that the changes are reflected in UI
             graphContext.OnCompleted();
         }
     }
 }
示例#4
0
 public ProjectContextEventArgs(IDependenciesGraphProjectContext context)
 {
     Context = context;
 }
示例#5
0
        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();
                }
            }
        }
 public ProjectContextEventArgs(IDependenciesGraphProjectContext context,
                                IDependenciesChangeDiff diff = null)
 {
     Context = context;
     Diff    = diff ?? new DependenciesChange().GetDiff();
 }