Exemple #1
0
        public override async Task <string> OnSetPropertyValueAsync(
            string unevaluatedPropertyValue,
            IProjectProperties defaultProperties,
            IReadOnlyDictionary <string, string> dimensionalConditions = null)
        {
            using (ProjectWriteLockReleaser access = await _projectLockService.WriteLockAsync())
            {
                Microsoft.Build.Construction.ProjectRootElement projectXml = await access.GetProjectXmlAsync(_unconfiguredProject.FullPath);

                await _helper.SetPropertyAsync(unevaluatedPropertyValue, defaultProperties, projectXml);
            }

            return(null);
        }
Exemple #2
0
        public async Task OpenProjectXmlForWriteAsync(UnconfiguredProject project, Action <ProjectRootElement> action, CancellationToken cancellationToken = default(CancellationToken))
        {
            Requires.NotNull(project, nameof(project));
            Requires.NotNull(project, nameof(action));

            using (ProjectWriteLockReleaser access = await _projectLockService.WriteLockAsync(cancellationToken))
            {
                await access.CheckoutAsync(project.FullPath)
                .ConfigureAwait(true);

                ProjectRootElement rootElement = await access.GetProjectXmlAsync(project.FullPath, cancellationToken)
                                                 .ConfigureAwait(true);

                // Deliberately not async to reduce the type of
                // code you can run while holding the lock.
                action(rootElement);
            }
        }
        /// <summary>
        /// Deletes items from the project, and optionally from disk.
        /// Note: Delete and Remove commands are handled via IVsHierarchyDeleteHandler3, not by
        /// IAsyncCommandGroupHandler and first asks us we CanRemove nodes. If yes then RemoveAsync is called.
        /// We can remove only nodes that are standard and based on project items, i.e. nodes that
        /// are created by default IProjectDependenciesSubTreeProvider implementations and have
        /// DependencyNode.GenericDependencyFlags flags and IRule with Context != null, in order to obtain
        /// node's itemSpec. ItemSpec then used to remove a project item having same Include.
        /// </summary>
        /// <param name="nodes">The nodes that should be deleted.</param>
        /// <param name="deleteOptions">A value indicating whether the items should be deleted from disk as well as
        /// from the project file.
        /// </param>
        /// <exception cref="InvalidOperationException">Thrown when <see cref="IProjectTreeProvider.CanRemove"/>
        /// would return <c>false</c> for this operation.</exception>
        public override async Task RemoveAsync(IImmutableSet <IProjectTree> nodes,
                                               DeleteOptions deleteOptions = DeleteOptions.None)
        {
            if (deleteOptions.HasFlag(DeleteOptions.DeleteFromStorage))
            {
                throw new NotSupportedException();
            }

            // Get the list of shared import nodes.
            IEnumerable <IProjectTree> sharedImportNodes = nodes.Where(node =>
                                                                       node.Flags.Contains(DependencyTreeFlags.SharedProjectFlags));

            // Get the list of normal reference Item Nodes (this excludes any shared import nodes).
            IEnumerable <IProjectTree> referenceItemNodes = nodes.Except(sharedImportNodes);

            using (ProjectWriteLockReleaser access = await ProjectLockService.WriteLockAsync())
            {
                Project project = await access.GetProjectAsync(ActiveConfiguredProject).ConfigureAwait(true);

                // Handle the removal of normal reference Item Nodes (this excludes any shared import nodes).
                foreach (IProjectTree node in referenceItemNodes)
                {
                    if (node.BrowseObjectProperties == null || node.BrowseObjectProperties.Context == null)
                    {
                        // if node does not have an IRule with valid ProjectPropertiesContext we can not
                        // get it's itemsSpec. If nodes provided by custom IProjectDependenciesSubTreeProvider
                        // implementation, and have some custom IRule without context, it is not a problem,
                        // since they wouldnot have DependencyNode.GenericDependencyFlags and we would not
                        // end up here, since CanRemove would return false and Remove command would not show
                        // up for those nodes.
                        continue;
                    }

                    IProjectPropertiesContext nodeItemContext = node.BrowseObjectProperties.Context;
                    ProjectItem unresolvedReferenceItem       = project.GetItemsByEvaluatedInclude(nodeItemContext.ItemName)
                                                                .FirstOrDefault(item => string.Equals(item.ItemType,
                                                                                                      nodeItemContext.ItemType,
                                                                                                      StringComparison.OrdinalIgnoreCase));

                    Report.IfNot(unresolvedReferenceItem != null, "Cannot find reference to remove.");
                    if (unresolvedReferenceItem != null)
                    {
                        await access.CheckoutAsync(unresolvedReferenceItem.Xml.ContainingProject.FullPath)
                        .ConfigureAwait(true);

                        project.RemoveItem(unresolvedReferenceItem);
                    }
                }

                IDependenciesSnapshot snapshot = DependenciesSnapshotProvider.CurrentSnapshot;
                Requires.NotNull(snapshot, nameof(snapshot));
                if (snapshot == null)
                {
                    return;
                }

                // Handle the removal of shared import nodes.
                ProjectRootElement projectXml = await access.GetProjectXmlAsync(UnconfiguredProject.FullPath)
                                                .ConfigureAwait(true);

                foreach (IProjectTree sharedImportNode in sharedImportNodes)
                {
                    string sharedFilePath = UnconfiguredProject.GetRelativePath(sharedImportNode.FilePath);
                    if (string.IsNullOrEmpty(sharedFilePath))
                    {
                        continue;
                    }

                    IDependency sharedProjectDependency = snapshot.FindDependency(sharedFilePath, topLevel: true);
                    if (sharedProjectDependency != null)
                    {
                        sharedFilePath = sharedProjectDependency.Path;
                    }

                    // Find the import that is included in the evaluation of the specified ConfiguredProject that
                    // imports the project file whose full path matches the specified one.
                    IEnumerable <ResolvedImport> matchingImports = from import in project.Imports
                                                                   where import.ImportingElement.ContainingProject == projectXml
                                                                   where PathHelper.IsSamePath(import.ImportedProject.FullPath, sharedFilePath)
                                                                   select import;
                    foreach (ResolvedImport importToRemove in matchingImports)
                    {
                        ProjectImportElement importingElementToRemove = importToRemove.ImportingElement;
                        Report.IfNot(importingElementToRemove != null,
                                     "Cannot find shared project reference to remove.");
                        if (importingElementToRemove != null)
                        {
                            await access.CheckoutAsync(importingElementToRemove.ContainingProject.FullPath)
                            .ConfigureAwait(true);

                            importingElementToRemove.Parent.RemoveChild(importingElementToRemove);
                        }
                    }
                }
            }
        }