Пример #1
0
        private static async Task DoWorkInWriterLock(IVsProject project, Action <MsBuildProject> action)
        {
            UnconfiguredProject unconfiguredProject = GetUnconfiguredProject(project);

            if (unconfiguredProject != null)
            {
                var service = unconfiguredProject.ProjectService.Services.ProjectLockService;
                if (service != null)
                {
                    using (ProjectWriteLockReleaser x = await service.WriteLockAsync())
                    {
                        await x.CheckoutAsync(unconfiguredProject.FullPath);

                        ConfiguredProject configuredProject = await unconfiguredProject.GetSuggestedConfiguredProjectAsync();

                        MsBuildProject buildProject = await x.GetProjectAsync(configuredProject);

                        if (buildProject != null)
                        {
                            action(buildProject);
                        }

                        await x.ReleaseAsync();
                    }

                    await unconfiguredProject.ProjectService.Services.ThreadingPolicy.SwitchToUIThread();
                }
            }
        }
Пример #2
0
        public static async Task DoWorkInWriterLockAsync(Project project, IVsHierarchy hierarchy, Action <MsBuildProject> action)
        {
            await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            var vsProject = (IVsProject)hierarchy;
            UnconfiguredProject unconfiguredProject = GetUnconfiguredProject(vsProject);

            if (unconfiguredProject != null)
            {
                var service = unconfiguredProject.ProjectService.Services.ProjectLockService;
                if (service != null)
                {
                    using (ProjectWriteLockReleaser x = await service.WriteLockAsync())
                    {
                        await x.CheckoutAsync(unconfiguredProject.FullPath);

                        ConfiguredProject configuredProject = await unconfiguredProject.GetSuggestedConfiguredProjectAsync();

                        MsBuildProject buildProject = await x.GetProjectAsync(configuredProject);

                        if (buildProject != null)
                        {
                            action(buildProject);
                        }

                        await x.ReleaseAsync();
                    }

                    await unconfiguredProject.ProjectService.Services.ThreadingPolicy.SwitchToUIThread();

                    project.Save();
                }
            }
        }
Пример #3
0
        private async Task ReevaluateLoadedConfiguredProjects(CancellationToken cancellationToken, ProjectWriteLockReleaser access)
        {
            foreach (var configuredProject in _unconfiguredProject.LoadedConfiguredProjects)
            {
                try {
                    var jsproj = await access.GetProjectAsync(configuredProject, cancellationToken);

                    jsproj.ReevaluateIfNecessary();
                } catch (Exception ex) {
                    System.Diagnostics.Debug.Fail("We were unable to mark a configuration as dirty" + ex.Message, ex.StackTrace);
                }
            }
        }
Пример #4
0
        public async Task OpenProjectForWriteAsync(ConfiguredProject project, Action <Project> 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.UnconfiguredProject.FullPath)
                .ConfigureAwait(true);

                Project evaluatedProject = await access.GetProjectAsync(project, cancellationToken)
                                           .ConfigureAwait(true);

                // Deliberately not async to reduce the type of
                // code you can run while holding the lock.
                action(evaluatedProject);
            }
        }
Пример #5
0
        private static async Task DoWorkInWriterLockInternal(Project project, IVsHierarchy hierarchy, Action <MsBuildProject> action)
        {
            UnconfiguredProject unconfiguredProject = GetUnconfiguredProject((IVsProject)hierarchy);

            if (unconfiguredProject != null)
            {
                var service = unconfiguredProject.ProjectService.Services.ProjectLockService;
                if (service != null)
                {
                    // WriteLockAsync will move us to a background thread.
                    using (ProjectWriteLockReleaser x = await service.WriteLockAsync())
                    {
                        await x.CheckoutAsync(unconfiguredProject.FullPath);

                        ConfiguredProject configuredProject = await unconfiguredProject.GetSuggestedConfiguredProjectAsync();

                        MsBuildProject buildProject = await x.GetProjectAsync(configuredProject);

                        if (buildProject != null)
                        {
                            action(buildProject);
                        }

                        await x.ReleaseAsync();
                    }

                    // perform the save synchronously
                    await Task.Run(() =>
                    {
                        // move to the UI thread for the rest of this method
                        unconfiguredProject.ProjectService.Services.ThreadingPolicy.SwitchToUIThread();

                        var fileSystem = new PhysicalFileSystem(@"c:\");
                        fileSystem.MakeFileWritable(project.FullName);
                        project.Save();
                    }
                                   );
                }
            }
        }
Пример #6
0
 private async Task HandleFileChangedAsync(CancellationToken cancellationToken = default(CancellationToken))
 {
     try
     {
         // Only notify the project if the contents of the watched file have changed.
         // In the case if we fail to read the contents, we will opt to notify the project.
         byte[] newHash = GetFileHashOrNull(_fileBeingWatched);
         if (newHash == null || _previousContentsHash == null || !newHash.SequenceEqual(_previousContentsHash))
         {
             TraceUtilities.TraceVerbose("{0} changed on disk. Marking project dirty", _fileBeingWatched);
             _previousContentsHash = newHash;
             cancellationToken.ThrowIfCancellationRequested();
             await _projectServices.Project.Services.ProjectAsynchronousTasks.LoadedProjectAsync(async() =>
             {
                 using (ProjectWriteLockReleaser access = await _projectServices.ProjectLockService.WriteLockAsync(cancellationToken))
                 {
                     // notify all the loaded configured projects
                     IEnumerable <ConfiguredProject> currentProjects = _projectServices.Project.LoadedConfiguredProjects;
                     foreach (ConfiguredProject configuredProject in currentProjects)
                     {
                         // Inside a write lock, we should get back to the same thread.
                         Project project = await access.GetProjectAsync(configuredProject, cancellationToken).ConfigureAwait(true);
                         project.MarkDirty();
                         configuredProject.NotifyProjectChange();
                     }
                 }
             });
         }
         else
         {
             TraceUtilities.TraceWarning("{0} changed on disk, but has no actual content change.", _fileBeingWatched);
         }
     }
     catch (OperationCanceledException)
     {
         // Project is already unloaded
     }
 }
        /// <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);
                        }
                    }
                }
            }
        }
Пример #8
0
 private async Task ReevaluateLoadedConfiguredProjects(CancellationToken cancellationToken, ProjectWriteLockReleaser access) {
     foreach (var configuredProject in _unconfiguredProject.LoadedConfiguredProjects) {
         try {
             var jsproj = await access.GetProjectAsync(configuredProject, cancellationToken);
             jsproj.ReevaluateIfNecessary();
         } catch (Exception ex) {
             System.Diagnostics.Debug.Fail("We were unable to mark a configuration as dirty" + ex.Message, ex.StackTrace);
         }
     }
 }
Пример #9
0
        async Task <bool> BuildProjectAsync(ProjectWriteLockReleaser writeAccess)
        {
            var msBuildProject = await writeAccess.GetProjectAsync(ConfiguredProject);

            var solutionPath = QtProjectTracker.SolutionPath;
            var configProps  = new Dictionary <string, string>(
                ConfiguredProject.ProjectConfiguration.Dimensions.ToImmutableDictionary())
            {
                { "SolutionPath", solutionPath },
                { "SolutionFileName", Path.GetFileName(solutionPath) },
                { "SolutionName", Path.GetFileNameWithoutExtension(solutionPath) },
                { "SolutionExt", Path.GetExtension(solutionPath) },
                { "SolutionDir", Path.GetDirectoryName(solutionPath).TrimEnd('\\') + '\\' }
            };

            foreach (var property in Properties)
            {
                configProps[property.Key] = property.Value;
            }

            var projectInstance = new ProjectInstance(msBuildProject.Xml,
                                                      configProps, null, new ProjectCollection());

            var loggerVerbosity = LoggerVerbosity;

            if (QtVsToolsPackage.Instance.Options.BuildDebugInformation)
            {
                loggerVerbosity = QtVsToolsPackage.Instance.Options.BuildLoggerVerbosity;
            }
            var buildParams = new BuildParameters()
            {
                Loggers = (loggerVerbosity != LoggerVerbosity.Quiet)
                        ? new[] { new QtProjectLogger()
                                  {
                                      Verbosity = loggerVerbosity
                                  } }
                        : null
            };

            var buildRequest = new BuildRequestData(projectInstance,
                                                    Targets.ToArray(),
                                                    hostServices: null,
                                                    flags: BuildRequestDataFlags.ProvideProjectStateAfterBuild);

            if (QtVsToolsPackage.Instance.Options.BuildDebugInformation)
            {
                Messages.Print(string.Format(
                                   "{0:HH:mm:ss.FFF} QtProjectBuild({1}): Build [{2}] {3}",
                                   DateTime.Now, Thread.CurrentThread.ManagedThreadId,
                                   ConfiguredProject.ProjectConfiguration.Name,
                                   UnconfiguredProject.FullPath));
                Messages.Print("=== Targets");
                foreach (var target in buildRequest.TargetNames)
                {
                    Messages.Print(string.Format("    {0}", target));
                }
                Messages.Print("=== Properties");
                foreach (var property in Properties)
                {
                    Messages.Print(string.Format("    {0}={1}",
                                                 property.Key, property.Value));
                }
            }

            BuildResult result = null;

            while (result == null)
            {
                try {
                    result = BuildManager.DefaultBuildManager.Build(
                        buildParams, buildRequest);
                } catch (InvalidOperationException) {
                    if (QtVsToolsPackage.Instance.Options.BuildDebugInformation)
                    {
                        Messages.Print(string.Format(
                                           "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] "
                                           + "Warning: Another build is in progress; waiting...",
                                           DateTime.Now,
                                           Thread.CurrentThread.ManagedThreadId,
                                           ConfiguredProject.ProjectConfiguration.Name));
                    }
                    await Task.Delay(3000);
                }
            }

            if (QtVsToolsPackage.Instance.Options.BuildDebugInformation)
            {
                string        resMsg;
                StringBuilder resInfo = new StringBuilder();
                if (result?.OverallResult == BuildResultCode.Success)
                {
                    resMsg = "Build ok";
                }
                else
                {
                    resMsg = "Build FAIL";
                    if (result == null)
                    {
                        resInfo.AppendLine("####### Build returned 'null'");
                    }
                    else
                    {
                        resInfo.AppendLine("####### Build returned 'Failure' code");
                        if (result.ResultsByTarget != null)
                        {
                            foreach (var tr in result.ResultsByTarget)
                            {
                                var res = tr.Value;
                                if (res.ResultCode != TargetResultCode.Failure)
                                {
                                    continue;
                                }
                                resInfo.AppendFormat("### Target '{0}' FAIL\r\n", tr.Key);
                                if (res.Items != null && res.Items.Length > 0)
                                {
                                    resInfo.AppendFormat(
                                        "Items: {0}\r\n", string.Join(", ", res.Items
                                                                      .Select(it => it.ItemSpec)));
                                }
                                var e = tr.Value?.Exception;
                                if (e != null)
                                {
                                    resInfo.AppendFormat(
                                        "Exception: {0}\r\nStacktrace:\r\n{1}\r\n",
                                        e.Message, e.StackTrace);
                                }
                            }
                        }
                    }
                }
                Messages.Print(string.Format(
                                   "{0:HH:mm:ss.FFF} QtProjectBuild({1}): [{2}] {3}\r\n{4}",
                                   DateTime.Now, Thread.CurrentThread.ManagedThreadId,
                                   ConfiguredProject.ProjectConfiguration.Name,
                                   resMsg, resInfo.ToString()));
            }

            bool ok = false;

            if (result == null ||
                result.ResultsByTarget == null ||
                result.OverallResult != BuildResultCode.Success)
            {
                Messages.Print(string.Format("{0}: background build FAILED!",
                                             Path.GetFileName(UnconfiguredProject.FullPath)));
            }
            else
            {
                var checkResults = result.ResultsByTarget
                                   .Where(x => Targets.Contains(x.Key))
                                   .Select(x => x.Value);
                ok = checkResults.Any() &&
                     checkResults.All(x => x.ResultCode == TargetResultCode.Success);
                if (ok)
                {
                    msBuildProject.MarkDirty();
                }
            }
            await writeAccess.ReleaseAsync();

            return(ok);
        }