Пример #1
0
        public async Task <VisualStudioProject> CreateAndAddToWorkspaceAsync(
            string projectSystemName, string language, VisualStudioProjectCreationInfo creationInfo, CancellationToken cancellationToken)
        {
            // HACK: Fetch this service to ensure it's still created on the UI thread; once this is
            // moved off we'll need to fix up it's constructor to be free-threaded.

            await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

            _visualStudioWorkspaceImpl.Services.GetRequiredService <VisualStudioMetadataReferenceManager>();

            _visualStudioWorkspaceImpl.SubscribeExternalErrorDiagnosticUpdateSourceToSolutionBuildEvents();

            // Since we're on the UI thread here anyways, use that as an opportunity to grab the
            // IVsSolution object and solution file path.
            //
            // ConfigureAwait(true) as we have to come back to the UI thread to do the cast to IVsSolution2.
            var solution = (IVsSolution2?)await _serviceProvider.GetServiceAsync(typeof(SVsSolution)).ConfigureAwait(true);

            var solutionFilePath = solution != null && ErrorHandler.Succeeded(solution.GetSolutionInfo(out _, out var filePath, out _))
                ? filePath
                : null;

            // Following can be off the UI thread.
            await TaskScheduler.Default;

            // From this point on, we start mutating the solution.  So make us non cancellable.
            cancellationToken = CancellationToken.None;

            var id           = ProjectId.CreateNewId(projectSystemName);
            var assemblyName = creationInfo.AssemblyName ?? projectSystemName;

            // We will use the project system name as the default display name of the project
            var project = new VisualStudioProject(
                _visualStudioWorkspaceImpl,
                _dynamicFileInfoProviders,
                _hostDiagnosticUpdateSource,
                id,
                displayName: projectSystemName,
                language,
                assemblyName: assemblyName,
                compilationOptions: creationInfo.CompilationOptions,
                filePath: creationInfo.FilePath,
                parseOptions: creationInfo.ParseOptions);

            var versionStamp = creationInfo.FilePath != null?VersionStamp.Create(File.GetLastWriteTimeUtc(creationInfo.FilePath))
                                   : VersionStamp.Create();

            await _visualStudioWorkspaceImpl.ApplyChangeToWorkspaceAsync(w =>
            {
                _visualStudioWorkspaceImpl.AddProjectToInternalMaps_NoLock(project, creationInfo.Hierarchy, creationInfo.ProjectGuid, projectSystemName);

                var projectInfo = ProjectInfo.Create(
                    id,
                    versionStamp,
                    name: projectSystemName,
                    assemblyName: assemblyName,
                    language: language,
                    filePath: creationInfo.FilePath,
                    compilationOptions: creationInfo.CompilationOptions,
                    parseOptions: creationInfo.ParseOptions)
                                  .WithTelemetryId(creationInfo.ProjectGuid);

                // If we don't have any projects and this is our first project being added, then we'll create a new SolutionId
                // and count this as the solution being added so that event is raised.
                if (w.CurrentSolution.ProjectIds.Count == 0)
                {
                    var solutionSessionId = GetSolutionSessionId();

                    w.OnSolutionAdded(
                        SolutionInfo.Create(
                            SolutionId.CreateNewId(solutionFilePath),
                            VersionStamp.Create(),
                            solutionFilePath,
                            projects: new[] { projectInfo },
                            analyzerReferences: w.CurrentSolution.AnalyzerReferences)
                        .WithTelemetryId(solutionSessionId));
                }
                else
                {
                    w.OnProjectAdded(projectInfo);
                }
            }).ConfigureAwait(false);

            // Ensure that other VS contexts get accurate information that the UIContext for this language is now active.
            // This is not cancellable as we have already mutated the solution.
            await _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguageAsync(language, CancellationToken.None).ConfigureAwait(false);

            return(project);