public void AddProject(AbstractProject project) { var creationInfo = new VisualStudioProjectCreationInfo { AssemblyName = project.AssemblyName, FilePath = project.ProjectFilePath, Hierarchy = project.Hierarchy, ProjectGuid = project.Guid, }; project.VisualStudioProject = _projectFactory.CreateAndAddToWorkspace(project.ProjectSystemName, project.Language, creationInfo); project.UpdateVisualStudioProjectProperties(); _typeScriptProjects[project.Id] = project; }
public void AddProject(AbstractProject project) { if (_projectFactory != null) { var creationInfo = new VisualStudioProjectCreationInfo { AssemblyName = project.AssemblyName, FilePath = project.ProjectFilePath, ProjectGuid = project.Guid, }; project.VisualStudioProject = _projectFactory.CreateAndAddToWorkspace(project.ProjectSystemName, project.Language, creationInfo); project.UpdateVisualStudioProjectProperties(); } else { // We don't have an ID, so make something up project.ExplicitId = ProjectId.CreateNewId(project.ProjectSystemName); Workspace.OnProjectAdded(ProjectInfo.Create(project.ExplicitId, VersionStamp.Create(), project.ProjectSystemName, project.ProjectSystemName, project.Language)); } _projects[project.Id] = project; }
public VisualStudioProject CreateAndAddToWorkspace(string projectUniqueName, string language, VisualStudioProjectCreationInfo creationInfo) { // 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. _visualStudioWorkspaceImpl.Services.GetRequiredService <VisualStudioMetadataReferenceManager>(); var id = ProjectId.CreateNewId(projectUniqueName); var directoryNameOpt = creationInfo.FilePath != null?Path.GetDirectoryName(creationInfo.FilePath) : null; var project = new VisualStudioProject(_visualStudioWorkspaceImpl, _dynamicFileInfoProviders, _hostDiagnosticUpdateSource, id, projectUniqueName, language, directoryNameOpt); var versionStamp = creationInfo.FilePath != null?VersionStamp.Create(File.GetLastWriteTimeUtc(creationInfo.FilePath)) : VersionStamp.Create(); var assemblyName = creationInfo.AssemblyName ?? projectUniqueName; _visualStudioWorkspaceImpl.AddProjectToInternalMaps(project, creationInfo.Hierarchy, creationInfo.ProjectGuid, projectUniqueName); _visualStudioWorkspaceImpl.ApplyChangeToWorkspace(w => { var projectInfo = ProjectInfo.Create( id, versionStamp, name: projectUniqueName, assemblyName: assemblyName, language: language, filePath: creationInfo.FilePath, compilationOptions: creationInfo.CompilationOptions, parseOptions: creationInfo.ParseOptions); // HACK: update this since we're still on the UI thread. Note we can only update this if we don't have projects -- the workspace // only lets us really do this with OnSolutionAdded for now. string solutionPathToSetWithOnSolutionAdded = null; var solution = (IVsSolution)Shell.ServiceProvider.GlobalProvider.GetService(typeof(SVsSolution)); if (solution != null && ErrorHandler.Succeeded(solution.GetSolutionInfo(out _, out var solutionFilePath, out _))) { if (w.CurrentSolution.FilePath != solutionFilePath && w.CurrentSolution.ProjectIds.Count == 0) { solutionPathToSetWithOnSolutionAdded = solutionFilePath; } } if (solutionPathToSetWithOnSolutionAdded != null) { w.OnSolutionAdded( SolutionInfo.Create( SolutionId.CreateNewId(solutionPathToSetWithOnSolutionAdded), VersionStamp.Create(), solutionPathToSetWithOnSolutionAdded, projects: new[] { projectInfo })); // set working folder for the persistent service var persistenceService = w.Services.GetRequiredService <IPersistentStorageLocationService>() as VisualStudioPersistentStorageLocationService; persistenceService?.UpdateForVisualStudioWorkspace(w); } else { w.OnProjectAdded(projectInfo); } }); // We do all these sets after the w.OnProjectAdded, as the setting of these properties is going to try to modify the workspace // again. Those modifications will all implicitly do nothing, since the workspace already has the values from above. // We could pass these all through the constructor (but that gets verbose), or have some other control to ignore these, // but that seems like overkill. project.AssemblyName = assemblyName; project.CompilationOptions = creationInfo.CompilationOptions; project.FilePath = creationInfo.FilePath; project.ParseOptions = creationInfo.ParseOptions; return(project); }
public VisualStudioProject CreateAndAddToWorkspace(string projectSystemName, string language, VisualStudioProjectCreationInfo creationInfo) { // 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. _visualStudioWorkspaceImpl.Services.GetRequiredService <VisualStudioMetadataReferenceManager>(); // HACK: since we're on the UI thread, ensure we initialize our options provider which depends on a UI-affinitized experimentation service _visualStudioWorkspaceImpl.EnsureDocumentOptionProvidersInitialized(); var id = ProjectId.CreateNewId(projectSystemName); var directoryNameOpt = creationInfo.FilePath != null?Path.GetDirectoryName(creationInfo.FilePath) : null; // 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, directoryNameOpt); var versionStamp = creationInfo.FilePath != null?VersionStamp.Create(File.GetLastWriteTimeUtc(creationInfo.FilePath)) : VersionStamp.Create(); var assemblyName = creationInfo.AssemblyName ?? projectSystemName; _visualStudioWorkspaceImpl.AddProjectToInternalMaps(project, creationInfo.Hierarchy, creationInfo.ProjectGuid, projectSystemName); _visualStudioWorkspaceImpl.ApplyChangeToWorkspace(w => { var projectInfo = ProjectInfo.Create( id, versionStamp, name: projectSystemName, assemblyName: assemblyName, language: language, filePath: creationInfo.FilePath, compilationOptions: creationInfo.CompilationOptions, parseOptions: creationInfo.ParseOptions); // If we don't have any projects and this is our first project being added, then we'll create a new SolutionId if (w.CurrentSolution.ProjectIds.Count == 0) { // Fetch the current solution path. Since we're on the UI thread right now, we can do that. string solutionFilePath = null; var solution = (IVsSolution)Shell.ServiceProvider.GlobalProvider.GetService(typeof(SVsSolution)); if (solution != null) { if (ErrorHandler.Failed(solution.GetSolutionInfo(out _, out solutionFilePath, out _))) { // Paranoia: if the call failed, we definitely don't want to use any stuff that was set solutionFilePath = null; } } w.OnSolutionAdded( SolutionInfo.Create( SolutionId.CreateNewId(solutionFilePath), VersionStamp.Create(), solutionFilePath, projects: new[] { projectInfo })); // set working folder for the persistent service var persistenceService = w.Services.GetRequiredService <IPersistentStorageLocationService>() as VisualStudioPersistentStorageLocationService; persistenceService?.UpdateForVisualStudioWorkspace(w); } else { w.OnProjectAdded(projectInfo); } }); // We do all these sets after the w.OnProjectAdded, as the setting of these properties is going to try to modify the workspace // again. Those modifications will all implicitly do nothing, since the workspace already has the values from above. // We could pass these all through the constructor (but that gets verbose), or have some other control to ignore these, // but that seems like overkill. project.AssemblyName = assemblyName; project.CompilationOptions = creationInfo.CompilationOptions; project.FilePath = creationInfo.FilePath; project.ParseOptions = creationInfo.ParseOptions; return(project); }
public VisualStudioProject CreateAndAddToWorkspace(string projectSystemName, string language, VisualStudioProjectCreationInfo creationInfo) { // 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. _visualStudioWorkspaceImpl.Services.GetRequiredService <VisualStudioMetadataReferenceManager>(); // HACK: since we're on the UI thread, ensure we initialize our options provider which depends on a UI-affinitized experimentation service _visualStudioWorkspaceImpl.EnsureDocumentOptionProvidersInitialized(); 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(); _visualStudioWorkspaceImpl.AddProjectToInternalMaps(project, creationInfo.Hierarchy, creationInfo.ProjectGuid, projectSystemName); _visualStudioWorkspaceImpl.ApplyChangeToWorkspace(w => { 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 if (w.CurrentSolution.ProjectIds.Count == 0) { // Fetch the current solution path. Since we're on the UI thread right now, we can do that. string?solutionFilePath = null; var solution = (IVsSolution)Shell.ServiceProvider.GlobalProvider.GetService(typeof(SVsSolution)); if (solution != null) { if (ErrorHandler.Failed(solution.GetSolutionInfo(out _, out solutionFilePath, out _))) { // Paranoia: if the call failed, we definitely don't want to use any stuff that was set solutionFilePath = null; } } 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); } _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguage(language); }); return(project);
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);