private SolutionState( BranchId branchId, int workspaceVersion, SolutionServices solutionServices, SolutionId id, string filePath, IEnumerable<ProjectId> projectIds, ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap, ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap, ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap, ProjectDependencyGraph dependencyGraph, VersionStamp version, Lazy<VersionStamp> lazyLatestProjectVersion) { _branchId = branchId; _workspaceVersion = workspaceVersion; _id = id; _filePath = filePath; _solutionServices = solutionServices; _projectIds = projectIds.ToImmutableReadOnlyListOrEmpty(); _projectIdToProjectStateMap = idToProjectStateMap; _projectIdToTrackerMap = projectIdToTrackerMap; _linkedFilesMap = linkedFilesMap; _dependencyGraph = dependencyGraph; _version = version; _lazyLatestProjectVersion = lazyLatestProjectVersion; CheckInvariants(); }
/// <summary> /// Get approximate solution size at the point of call. /// /// This API is not supposed to return 100% accurate size. /// /// if a feature require 100% accurate size, use Solution to calculate it. this API is supposed to /// lazy and very cheap on answering that question. /// </summary> public long GetSolutionSize(Workspace workspace, SolutionId solutionId) { var service = workspace.Services.GetService<IPersistentStorageLocationService>(); return service.IsSupported(workspace) ? _tracker.GetSolutionSize(solutionId) : -1; }
private Solution( BranchId branchId, int workspaceVersion, SolutionServices solutionServices, SolutionId id, string filePath, ImmutableList<ProjectId> projectIds, ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap, ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap, ProjectDependencyGraph dependencyGraph, VersionStamp version, Lazy<VersionStamp> lazyLatestProjectVersion) { this.branchId = branchId; this.workspaceVersion = workspaceVersion; this.id = id; this.filePath = filePath; this.solutionServices = solutionServices; this.projectIds = projectIds; this.projectIdToProjectStateMap = idToProjectStateMap; this.projectIdToTrackerMap = projectIdToTrackerMap; this.dependencyGraph = dependencyGraph; this.projectIdToProjectMap = ImmutableHashMap<ProjectId, Project>.Empty; this.version = version; this.lazyLatestProjectVersion = lazyLatestProjectVersion; CheckInvariants(); }
public override Task NewSolutionSnapshotAsync(Solution solution, CancellationToken cancellationToken) { // check whether we are good to report total symbol numbers if (_symbolCountByProjectMap == null || _symbolCountByProjectMap.Count < solution.ProjectIds.Count || string.IsNullOrEmpty(solution.FilePath)) { return SpecializedTasks.EmptyTask; } if (_solutionId != null && _solutionId != solution.Id) { ReportCount(); return SpecializedTasks.EmptyTask; } _solutionId = solution.Id; foreach (var projectId in solution.ProjectIds) { if (!_symbolCountByProjectMap.ContainsKey(projectId)) { return SpecializedTasks.EmptyTask; } } ReportCount(); return SpecializedTasks.EmptyTask; }
public static void UpdateStorageLocation(SolutionId id, string storageLocation) { lock (_gate) { // Store the esent database in a different location for the out of proc server. _idToStorageLocation[id] = Path.Combine(storageLocation, "Server"); } }
/// <summary> /// Create a new instance of a SolutionInfo. /// </summary> public static SolutionInfo Create( SolutionId id, VersionStamp version, string filePath = null, IEnumerable<ProjectInfo> projects = null) { return new SolutionInfo(new SolutionAttributes(id, version, filePath), projects); }
public static async Task<long> GetSolutionSizeAsync (Workspace workspace, SolutionId id, CancellationToken cancellationToken) { long result = 0; foreach (var project in workspace.CurrentSolution.Projects) { result += await GetProjectSizeAsync (project, cancellationToken); } return result; }
public void OnBeforeWorkingFolderChange() { this.AssertIsForeground(); _currentSolutionId = _workspace.CurrentSolution.Id; var solutionId = _currentSolutionId; UnregisterPrimarySolutionAsync(solutionId, synchronousShutdown: true).Wait(); }
private SolutionInfo( SolutionId id, VersionStamp version, string filePath, IEnumerable<ProjectInfo> projects) { this.Id = id; this.Version = version; this.FilePath = filePath; this.Projects = projects.ToImmutableReadOnlyListOrEmpty(); }
public Task NewSolutionSnapshotAsync(Solution solution, CancellationToken cancellationToken) { if (_solutionId != solution.Id) { _map.Clear(); _solutionId = solution.Id; } return SpecializedTasks.EmptyTask; }
public TestHostSolution(params TestHostProject[] projects) { this.Id = SolutionId.CreateNewId(); this.Version = VersionStamp.Create(); this.Projects = projects; foreach (var project in projects) { project.SetSolution(this); } }
public WorkspaceHost( VisualStudioWorkspaceImpl workspace, RemoteHostClient client) { _workspace = workspace; _client = client; _currentSolutionId = workspace.CurrentSolution.Id; // Ensure that we populate the remote service with the initial state of // the workspace's solution. RegisterPrimarySolutionAsync().Wait(); }
public PersistentStorageService(IOptionService optionService) { _optionService = optionService; _lookupAccessLock = new object(); _lookup = new Dictionary<string, AbstractPersistentStorage>(); _lastSolutionPath = null; _primarySolutionId = null; _primarySolutionStorage = null; }
private async Task RegisterPrimarySolutionAsync() { _currentSolutionId = _workspace.CurrentSolution.Id; var solutionId = _currentSolutionId; using (var session = await _client.CreateServiceSessionAsync(WellKnownRemoteHostServices.RemoteHostService, _workspace.CurrentSolution, CancellationToken.None).ConfigureAwait(false)) { await session.InvokeAsync( WellKnownRemoteHostServices.RemoteHostService_PersistentStorageService_RegisterPrimarySolutionId, solutionId.Id.ToByteArray(), solutionId.DebugName).ConfigureAwait(false); await session.InvokeAsync( WellKnownRemoteHostServices.RemoteHostService_PersistentStorageService_UpdateSolutionIdStorageLocation, solutionId.Id.ToByteArray(), solutionId.DebugName, _workspace.ProjectTracker.GetWorkingFolderPath(_workspace.CurrentSolution)).ConfigureAwait(false); } }
public HostProject(Workspace workspace, SolutionId solutionId, string languageName, ParseOptions parseOptions, IEnumerable<MetadataReference> metadataReferences) { Debug.Assert(workspace != null); Debug.Assert(languageName != null); Debug.Assert(parseOptions != null); Debug.Assert(metadataReferences != null); _workspace = workspace; this.Id = ProjectId.CreateNewId(debugName: "Miscellaneous Files"); this.Language = languageName; _parseOptions = parseOptions; // the assembly name must be unique for each collection of loose files. since the name doesn't matter // a random GUID can be used. _assemblyName = Guid.NewGuid().ToString("N"); _version = VersionStamp.Create(); _metadataReferences = metadataReferences; }
public static void UpdateStorageLocation(SolutionId id, string storageLocation) { lock (_gate) { // We can get null when the solution has no corresponding file location // in the host process. This is not abnormal and can come around for // many reasons. In that case, we simply do not store a storage location // for this solution, indicating to all remote consumers that persistent // storage is not available for this solution. if (storageLocation == null) { _idToStorageLocation.Remove(id); } else { // Store the esent database in a different location for the out of proc server. _idToStorageLocation[id] = Path.Combine(storageLocation, "Server"); } } }
internal void StartPushingToWorkspaceAndNotifyOfOpenDocuments( IEnumerable <AbstractProject> projects) { AssertIsForeground(); // If the workspace host isn't actually ready yet, we shouldn't do anything. // Also, if the solution is closing we shouldn't do anything either, because all of our state is // in the process of going away. This can happen if we receive notification that a document has // opened in the middle of the solution close operation. if (!this.HostReadyForEvents || _tracker._solutionIsClosing) { return; } // We need to push these projects and any project dependencies we already know about. Therefore, compute the // transitive closure of the projects that haven't already been pushed, keeping them in appropriate order. var visited = new HashSet <AbstractProject>(); var inOrderToPush = new List <AbstractProject>(); foreach (var project in projects) { AddToPushListIfNeeded(project, inOrderToPush, visited); } var projectInfos = inOrderToPush.Select(p => p.CreateProjectInfoForCurrentState()).ToImmutableArray(); // We need to enable projects to start pushing changes to workspace hosts even before we add the solution/project to the host. // This is required because between the point we capture the project info for current state and the point where we start pushing to workspace hosts, // project system may send new events on the AbstractProject on a background thread, and these won't get pushed over to the workspace hosts as we didn't set the _pushingChangesToWorkspaceHost flag on the AbstractProject. // By invoking StartPushingToWorkspaceHosts upfront, any project state changes on the background thread will enqueue notifications to workspace hosts on foreground scheduled tasks. foreach (var project in inOrderToPush) { project.StartPushingToWorkspaceHosts(); } if (!_solutionAdded) { string solutionFilePath = null; VersionStamp?version = default(VersionStamp?); // Figure out the solution version if (ErrorHandler.Succeeded(_tracker._vsSolution.GetSolutionInfo(out var solutionDirectory, out var solutionFileName, out var userOptsFile)) && solutionFileName != null) { solutionFilePath = Path.Combine(solutionDirectory, solutionFileName); if (File.Exists(solutionFilePath)) { version = VersionStamp.Create(File.GetLastWriteTimeUtc(solutionFilePath)); } } if (version == null) { version = VersionStamp.Create(); } var id = SolutionId.CreateNewId(string.IsNullOrWhiteSpace(solutionFileName) ? null : solutionFileName); _tracker.RegisterSolutionProperties(id); var solutionInfo = SolutionInfo.Create(id, version.Value, solutionFilePath, projects: projectInfos); _tracker.NotifyWorkspaceHosts(host => host.OnSolutionAdded(solutionInfo)); _solutionAdded = true; } else { // The solution is already added, so we'll just do project added notifications from here foreach (var projectInfo in projectInfos) { this.Host.OnProjectAdded(projectInfo); } } foreach (var project in inOrderToPush) { _pushedProjects.Add(project); foreach (var document in project.GetCurrentDocuments()) { if (document.IsOpen) { this.Host.OnDocumentOpened( document.Id, document.GetOpenTextBuffer(), isCurrentContext: LinkedFileUtilities.IsCurrentContextHierarchy(document, _tracker._runningDocumentTable)); } } } }
public void SerializeSolutionId(SolutionId solutionId, ObjectWriter writer, CancellationToken cancellationToken) { writer.WriteValue(solutionId.Id.ToByteArray()); writer.WriteString(solutionId.DebugName); }
public SolutionAttributes(SolutionId id, VersionStamp version, string filePath) { Id = id ?? throw new ArgumentNullException(nameof(id)); Version = version; FilePath = filePath; }
public void OnSolutionRemoved() { this.AssertIsForeground(); // Have to use the cached solution ID we've got as the workspace will // no longer have a solution we can look at. var solutionId = _currentSolutionId; _currentSolutionId = null; UnregisterPrimarySolutionAsync(solutionId, synchronousShutdown: false).Wait(); }
public Task NewSolutionSnapshotAsync(Solution solution, CancellationToken cancellationToken) { if (solution.Id != _currentSolutionId) { _projectGuidCache.Clear(); _errorDetailCache.Clear(); _currentSolutionId = solution.Id; } return SpecializedTasks.EmptyTask; }
public void RegisterSolutionProperties(SolutionId solutionId) { AssertIsForeground(); try { var solutionWorkingFolder = (IVsSolutionWorkingFolders)_vsSolution; solutionWorkingFolder.GetFolder( (uint)__SolutionWorkingFolder.SlnWF_StatePersistence, Guid.Empty, fVersionSpecific: true, fEnsureCreated: true, pfIsTemporary: out var temporary, pszBstrFullPath: out var workingFolderPath); if (!temporary && !string.IsNullOrWhiteSpace(workingFolderPath)) { s_workingFolderPathMap.Add(solutionId, workingFolderPath); } } catch { // don't crash just because solution having problem getting working folder information } }
public long GetSolutionSize(SolutionId solutionId) { return(_solutionId == solutionId ? _size : -1); }
static IComplierExtension() { _workSpace = new AdhocWorkspace(); _workSpace.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId("formatter"), VersionStamp.Default)); _options = new CSharpParseOptions(LanguageVersion.Latest); }
public void TestSolutionId() { VerifyJsonSerialization(SolutionId.CreateNewId("solution")); }
public void PersistentStorageService_UpdateSolutionIdStorageLocation(SolutionId solutionId, string storageLocation) { RemotePersistentStorageLocationService.UpdateStorageLocation(solutionId, storageLocation); }
public MockPersistentStorageLocationService(SolutionId solutionId, string storageLocation) { _solutionId = solutionId; _storageLocation = storageLocation; }
public void PersistentStorageService_RegisterPrimarySolutionId(SolutionId solutionId) { var persistentStorageService = GetPersistentStorageService(); persistentStorageService?.RegisterPrimarySolution(solutionId); }
public void Create_FilePath(string path) { var info = SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Default, filePath: path); Assert.Equal(path, info.FilePath); }
/// <summary> /// Open a solution file and all referenced projects. /// </summary> public async Task <Solution> OpenSolutionAsync(string solutionFilePath, CancellationToken cancellationToken = default(CancellationToken)) { if (solutionFilePath == null) { throw new ArgumentNullException(nameof(solutionFilePath)); } this.ClearSolution(); var absoluteSolutionPath = this.GetAbsoluteSolutionPath(solutionFilePath, Environment.CurrentDirectory); using (_dataGuard.DisposableWait(cancellationToken)) { this.SetSolutionProperties(absoluteSolutionPath); } VersionStamp version = default(VersionStamp); #if !MSBUILD12 Microsoft.Build.Construction.SolutionFile solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(absoluteSolutionPath); var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw; var invalidProjects = new List <ProjectInSolution>(); // seed loaders from known project types using (_dataGuard.DisposableWait(cancellationToken)) { foreach (var project in solutionFile.ProjectsInOrder) { if (project.ProjectType == SolutionProjectType.SolutionFolder) { continue; } var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode); if (projectAbsolutePath != null) { var extension = Path.GetExtension(projectAbsolutePath); if (extension.Length > 0 && extension[0] == '.') { extension = extension.Substring(1); } var loader = ProjectFileLoader.GetLoaderForProjectFileExtension(this, extension); if (loader != null) { _projectPathToLoaderMap[projectAbsolutePath] = loader; } } else { invalidProjects.Add(project); } } } // a list to accumulate all the loaded projects var loadedProjects = new List <ProjectInfo>(); // load all the projects foreach (var project in solutionFile.ProjectsInOrder) { cancellationToken.ThrowIfCancellationRequested(); if (project.ProjectType != SolutionProjectType.SolutionFolder && !invalidProjects.Contains(project)) { var projectAbsolutePath = TryGetAbsolutePath(project.AbsolutePath, reportMode); if (projectAbsolutePath != null) { IProjectFileLoader loader; if (TryGetLoaderFromProjectPath(projectAbsolutePath, reportMode, out loader)) { // projects get added to 'loadedProjects' as side-effect // never perfer metadata when loading solution, all projects get loaded if they can. var tmp = await GetOrLoadProjectAsync(projectAbsolutePath, loader, preferMetadata : false, loadedProjects : loadedProjects, cancellationToken : cancellationToken).ConfigureAwait(false); } } } } #else SolutionFile solutionFile = null; using (var reader = new StreamReader(absoluteSolutionPath)) { version = VersionStamp.Create(File.GetLastWriteTimeUtc(absoluteSolutionPath)); var text = await reader.ReadToEndAsync().ConfigureAwait(false); solutionFile = SolutionFile.Parse(new StringReader(text)); } var solutionFolder = Path.GetDirectoryName(absoluteSolutionPath); // seed loaders from known project types using (_dataGuard.DisposableWait()) { foreach (var projectBlock in solutionFile.ProjectBlocks) { string absoluteProjectPath; if (TryGetAbsoluteProjectPath(projectBlock.ProjectPath, solutionFolder, ReportMode.Ignore, out absoluteProjectPath)) { var loader = ProjectFileLoader.GetLoaderForProjectTypeGuid(this, projectBlock.ProjectTypeGuid); if (loader != null) { _projectPathToLoaderMap[absoluteProjectPath] = loader; } } } } // a list to accumulate all the loaded projects var loadedProjects = new List <ProjectInfo>(); var reportMode = this.SkipUnrecognizedProjects ? ReportMode.Log : ReportMode.Throw; // load all the projects foreach (var projectBlock in solutionFile.ProjectBlocks) { cancellationToken.ThrowIfCancellationRequested(); string absoluteProjectPath; if (TryGetAbsoluteProjectPath(projectBlock.ProjectPath, solutionFolder, reportMode, out absoluteProjectPath)) { IProjectFileLoader loader; if (TryGetLoaderFromProjectPath(absoluteProjectPath, reportMode, out loader)) { // projects get added to 'loadedProjects' as side-effect // never perfer metadata when loading solution, all projects get loaded if they can. var tmp = await GetOrLoadProjectAsync(absoluteProjectPath, loader, preferMetadata : false, loadedProjects : loadedProjects, cancellationToken : cancellationToken).ConfigureAwait(false); } } } #endif // construct workspace from loaded project infos this.OnSolutionAdded(SolutionInfo.Create(SolutionId.CreateNewId(debugName: absoluteSolutionPath), version, absoluteSolutionPath, loadedProjects)); this.UpdateReferencesAfterAdd(); return(this.CurrentSolution); }
public long GetSolutionSize(Workspace workspace, SolutionId solutionId) { return workspace is VisualStudioWorkspaceImpl ? _tracker.GetSolutionSize(solutionId) : -1; }
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 })); } else { w.OnProjectAdded(projectInfo); } _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguage(language); }); // 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); }
/// <summary> /// Create a <see cref="Solution"/> for <paramref name="code"/> /// Each unique namespace in <paramref name="code"/> is added as a project. /// </summary> /// <param name="code">The code to create the solution from.</param> /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param> /// <param name="metadataReferences">The metadata references.</param> /// <param name="languageVersion">The <see cref="LanguageVersion"/>.</param> /// <returns>A <see cref="Solution"/>.</returns> public static Solution CreateSolution(IEnumerable <string> code, CSharpCompilationOptions compilationOptions, IEnumerable <MetadataReference>?metadataReferences = null, LanguageVersion languageVersion = LanguageVersion.Latest) { var solutionInfo = SolutionInfo.Create( SolutionId.CreateNewId("Test.sln"), VersionStamp.Default, projects: GetProjectInfos()); var solution = EmptySolution; foreach (var projectInfo in solutionInfo.Projects) { solution = solution.AddProject(projectInfo.WithProjectReferences(FindReferences(projectInfo))); } return(solution); IEnumerable <ProjectInfo> GetProjectInfos() { var byNamespace = new SortedDictionary <string, List <string> >(); foreach (var document in code) { var ns = CodeReader.Namespace(document); if (byNamespace.TryGetValue(ns, out var doc)) { doc.Add(document); } else { byNamespace[ns] = new List <string> { document }; } } var byProject = new SortedDictionary <string, List <KeyValuePair <string, List <string> > > >(); foreach (var kvp in byNamespace) { var last = byProject.Keys.LastOrDefault(); var ns = kvp.Key; if (last != null && ns.Contains(last)) { byProject[last].Add(kvp); } else { byProject.Add(ns, new List <KeyValuePair <string, List <string> > > { kvp }); } } foreach (var kvp in byProject) { var assemblyName = kvp.Key; var projectId = ProjectId.CreateNewId(assemblyName); yield return(ProjectInfo.Create( projectId, VersionStamp.Default, assemblyName, assemblyName, LanguageNames.CSharp, compilationOptions: compilationOptions, metadataReferences: metadataReferences, documents: kvp.Value.SelectMany(x => x.Value) .Select( x => { var documentName = CodeReader.FileName(x); return DocumentInfo.Create( DocumentId.CreateNewId(projectId, documentName), documentName, sourceCodeKind: SourceCodeKind.Regular, loader: new StringLoader(x)); })) .WithParseOptions(CSharpParseOptions.Default.WithLanguageVersion(languageVersion))); } } IEnumerable <ProjectReference> FindReferences(ProjectInfo projectInfo) { var references = new List <ProjectReference>(); foreach (var other in solutionInfo.Projects.Where(x => x.Id != projectInfo.Id)) { if (projectInfo.Documents.Any(x => x.TextLoader is StringLoader stringLoader && (stringLoader.Code.Contains($"using {other.Name};") || stringLoader.Code.Contains($"{other.Name}.")))) { references.Add(new ProjectReference(other.Id)); } } return(references); } }
private static SolutionId CreateSolutionId(byte[] solutionIdGuidBytes, string solutionIdDebugName) { return(SolutionId.CreateFromSerialized(new Guid(solutionIdGuidBytes), solutionIdDebugName)); }
public void UnregisterPrimarySolutionId(SolutionId solutionId, bool synchronousShutdown, CancellationToken cancellationToken) { var persistentStorageService = GetPersistentStorageService(); persistentStorageService?.UnregisterPrimarySolution(solutionId, synchronousShutdown); }
static void Main(string[] args) { // Create the solution with an empty document ProjectId projectId; DocumentId documentId; var solution = Solution.Create(SolutionId.CreateNewId()) .AddProject("MyProject", "MyProject", LanguageNames.CSharp, out projectId) .AddDocument(projectId, @"C:\file.cs", string.Empty, out documentId); var document = solution.GetDocument(documentId); var root = (CompilationUnitSyntax)document.GetSyntaxRoot(); // Add the namespace var namespaceAnnotation = new SyntaxAnnotation(); root = root.WithMembers( Syntax.NamespaceDeclaration( Syntax.ParseName("MyNamespace")) .NormalizeWhitespace() .WithAdditionalAnnotations(namespaceAnnotation)); document = document.UpdateSyntaxRoot(root); Console.WriteLine("-------------------"); Console.WriteLine("With Namespace"); Console.WriteLine(document.GetText().GetText()); // Find our namespace, add a class to it, and update the document var namespaceNode = (NamespaceDeclarationSyntax)root .GetAnnotatedNodesAndTokens(namespaceAnnotation) .Single() .AsNode(); var classAnnotation = new SyntaxAnnotation(); var newNamespaceNode = namespaceNode .WithMembers( Syntax.List <MemberDeclarationSyntax>( Syntax.ClassDeclaration("MyClass") .WithAdditionalAnnotations(classAnnotation))); root = root.ReplaceNode(namespaceNode, newNamespaceNode).NormalizeWhitespace(); document = document.UpdateSyntaxRoot(root); Console.WriteLine("-------------------"); Console.WriteLine("With Class"); Console.WriteLine(document.GetText().GetText()); // Find the class, add a method to it and update the document var classNode = (ClassDeclarationSyntax)root .GetAnnotatedNodesAndTokens(classAnnotation) .Single() .AsNode(); var newClassNode = classNode .WithMembers( Syntax.List <MemberDeclarationSyntax>( Syntax.MethodDeclaration( Syntax.ParseTypeName("void"), "MyMethod") .WithBody( Syntax.Block()))); root = root.ReplaceNode(classNode, newClassNode).NormalizeWhitespace(); document = document.UpdateSyntaxRoot(root); Console.WriteLine("-------------------"); Console.WriteLine("With Method"); Console.WriteLine(document.GetText().GetText()); }
private void ReportCount() { var sourceSymbolCount = _symbolCountByProjectMap.Sum(kv => kv.Value); Logger.Log(FunctionId.Run_Environment, KeyValueLogMessage.Create(m => m["SourceSymbolCount"] = sourceSymbolCount)); // we only report it once _symbolCountByProjectMap = null; _solutionId = null; }
private async Task UnregisterPrimarySolutionAsync( SolutionId solutionId, bool synchronousShutdown) { using (var session = await _client.CreateServiceSessionAsync(WellKnownRemoteHostServices.RemoteHostService, _workspace.CurrentSolution, CancellationToken.None).ConfigureAwait(false)) { // ask remote host to sync initial asset await session.InvokeAsync( WellKnownRemoteHostServices.RemoteHostService_PersistentStorageService_UnregisterPrimarySolutionId, solutionId.Id.ToByteArray(), solutionId.DebugName, synchronousShutdown).ConfigureAwait(false); } }
public void RegisterPrimarySolution(SolutionId solutionId) { // don't create esent storage file right away. it will be // created when first C#/VB project is added lock (_lookupAccessLock) { Contract.ThrowIfTrue(_primarySolutionStorage != null); // just reset solutionId as long as there is no storage has created. _primarySolutionId = solutionId; } }
public void UpdateSolutionProperties(SolutionId solutionId) { s_workingFolderPathMap.Remove(solutionId); RegisterSolutionProperties(solutionId); }
public MockPersistentStorageConfiguration(SolutionId solutionId, string storageLocation, bool throwOnFailure) { _solutionId = solutionId; _storageLocation = storageLocation; _throwOnFailure = throwOnFailure; }
public SolutionKey(SolutionId id, string?filePath, bool isPrimaryBranch) { Id = id; FilePath = filePath; IsPrimaryBranch = isPrimaryBranch; }
public string TryGetStorageLocation(SolutionId solutionId) { return(solutionId == _solutionId ? _storageLocation : null); }
public ReanalyzeScope(SolutionId solutionId) { _solutionId = solutionId; _projectOrDocumentIds = null; }
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>(); // 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; await _visualStudioWorkspaceImpl.EnsureDocumentOptionProvidersInitializedAsync(cancellationToken).ConfigureAwait(true); // 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(); _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) { 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);
private async Task SetupCodeControlAsync() { var w = new AdhocWorkspace(Host); w.AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create())); var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "Code Project", "code", LanguageNames.CSharp); var w2 = w.CurrentSolution.AddProject(projectInfo); w.TryApplyChanges(w2); DocumentInfo documentInfo; var filename = Filename; if (filename != null) { documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(projectInfo.Id), "Default", null, SourceCodeKind.Regular, new FileTextLoader(filename, Encoding.UTF8), filename); } else { documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(projectInfo.Id), "Default", null, SourceCodeKind.Regular); } w2 = w.CurrentSolution.AddDocument(documentInfo); w.TryApplyChanges(w2); CodeControl.XOffset = 100; CodeControl.JTF2 = JTF2; CodeControl.PreviewKeyDown += CodeControlOnPreviewKeyDown; var doc = w.CurrentSolution.GetDocument(documentInfo.Id); if (doc != null) { ClassDiagram.Document = doc; CodeControl.Document = doc; var tree = await doc.GetSyntaxTreeAsync(); // ReSharper disable once AssignNullToNotNullAttribute CodeControl.SyntaxTree = tree; var model = await doc.GetSemanticModelAsync(); // ReSharper disable once AssignNullToNotNullAttribute CodeControl.SemanticModel = model; CodeControl.Compilation = model.Compilation; } DateTime startTime = default; CodeControl.AddHandler(RoslynCodeBase.RenderStartEvent, new RoutedEventHandler((sender, args) => { startTime = DateTime.Now; Debug.WriteLine("render start"); })); CodeControl.AddHandler(RoslynCodeBase.RenderCompleteEvent, new RoutedEventHandler((sender, args) => { var span = DateTime.Now - startTime; var msg = $"render complete time is {span}"; Debug.WriteLine(msg); ProtoLogger.Instance.LogAction(msg); })); await CodeControl.UpdateFormattedTextAsync(); CodeControlRendered = true; Rendering.Visibility = Visibility.Collapsed; }
public long GetSolutionSize(SolutionId solutionId) { return _solutionId == solutionId ? _size : -1; }
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, _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) .WithDefaultNamespace(creationInfo.DefaultNamespace); // 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 })); } 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); }
/// <summary> /// Loads the <see cref="SolutionInfo"/> for the specified solution file, including all projects referenced by the solution file and /// all the projects referenced by the project files. /// </summary> /// <param name="solutionFilePath">The path to the solution file to be loaded. This may be an absolute path or a path relative to the /// current working directory.</param> /// <param name="progress">An optional <see cref="IProgress{T}"/> that will receive updates as the solution is loaded.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> to allow cancellation of this operation.</param> public async Task <SolutionInfo> LoadSolutionInfoAsync( string solutionFilePath, IProgress <ProjectLoadProgress> progress = null, CancellationToken cancellationToken = default) { if (solutionFilePath == null) { throw new ArgumentNullException(nameof(solutionFilePath)); } if (!_pathResolver.TryGetAbsoluteSolutionPath(solutionFilePath, baseDirectory: Directory.GetCurrentDirectory(), DiagnosticReportingMode.Throw, out var absoluteSolutionPath)) { // TryGetAbsoluteSolutionPath should throw before we get here. return(null); } using (_dataGuard.DisposableWait(cancellationToken)) { this.SetSolutionProperties(absoluteSolutionPath); } var solutionFile = MSB.Construction.SolutionFile.Parse(absoluteSolutionPath); var reportingMode = GetReportingModeForUnrecognizedProjects(); var reportingOptions = new DiagnosticReportingOptions( onPathFailure: reportingMode, onLoaderFailure: reportingMode); var projectPaths = ImmutableArray.CreateBuilder <string>(); // load all the projects foreach (var project in solutionFile.ProjectsInOrder) { cancellationToken.ThrowIfCancellationRequested(); if (project.ProjectType != MSB.Construction.SolutionProjectType.SolutionFolder) { projectPaths.Add(project.RelativePath); } } var buildManager = new ProjectBuildManager(_properties); var worker = new Worker( _workspaceServices, _diagnosticReporter, _pathResolver, _projectFileLoaderRegistry, buildManager, projectPaths.ToImmutable(), baseDirectory: Path.GetDirectoryName(absoluteSolutionPath), _properties, projectMap: null, progress, requestedProjectOptions: reportingOptions, discoveredProjectOptions: reportingOptions, preferMetadataForReferencesOfDiscoveredProjects: false); var projects = await worker.LoadAsync(cancellationToken).ConfigureAwait(false); // construct workspace from loaded project infos return(SolutionInfo.Create( SolutionId.CreateNewId(debugName: absoluteSolutionPath), version: default,
/// <summary> /// Starts pushing events from the given projects to the workspace hosts and notifies about open documents. /// </summary> /// <remarks>This method must be called on the foreground thread.</remarks> internal void StartPushingToWorkspaceAndNotifyOfOpenDocuments(IEnumerable <AbstractProject> projects) { AssertIsForeground(); // If the solution is closing we shouldn't do anything, because all of our state is // in the process of going away. This can happen if we receive notification that a document has // opened in the middle of the solution close operation. if (_solutionIsClosing) { return; } // We need to push these projects and any project dependencies we already know about. Therefore, compute the // transitive closure of the projects that haven't already been pushed, keeping them in appropriate order. var visited = new HashSet <AbstractProject>(); var inOrderToPush = new List <AbstractProject>(); void addToInOrderToPush(AbstractProject project) { Contract.ThrowIfFalse(ContainsProject(project)); // Bail out if any of the following is true: // 1. We have already started pushing changes for this project OR // 2. We have already visited this project in a prior recursive call if (_pushedProjects.Contains(project) || !visited.Add(project)) { return; } foreach (var projectReference in project.GetCurrentProjectReferences()) { addToInOrderToPush(GetProject(projectReference.ProjectId)); } inOrderToPush.Add(project); } foreach (var project in projects) { addToInOrderToPush(project); } var projectInfos = inOrderToPush.Select(p => p.CreateProjectInfoForCurrentState()).ToImmutableArray(); // We need to enable projects to start pushing changes to the workspace even before we add the solution/project to the host. // This is required because between the point we capture the project info for current state and the point where we start pushing to the workspace, // project system may send new events on the AbstractProject on a background thread, and these won't get pushed over to the workspace hosts as we didn't set the _pushingChangesToWorkspaceHost flag on the AbstractProject. // By invoking StartPushingToWorkspaceHosts upfront, any project state changes on the background thread will enqueue notifications to workspace hosts on foreground scheduled tasks. foreach (var project in inOrderToPush) { project.PushingChangesToWorkspace = true; Logger.Log(FunctionId.AbstractProject_PushedToWorkspace, KeyValueLogMessage.Create(LogType.Trace, m => { m[AbstractProject.ProjectGuidPropertyName] = project.Guid; })); } using (WorkspaceServices.GetService <IGlobalOperationNotificationService>()?.Start("Add Project to Workspace")) { if (!_solutionAdded) { string solutionFilePath = null; VersionStamp?version = default; // Figure out the solution version if (ErrorHandler.Succeeded(_vsSolution.GetSolutionInfo(out var solutionDirectory, out var solutionFileName, out var userOptsFile)) && solutionFileName != null) { solutionFilePath = Path.Combine(solutionDirectory, solutionFileName); if (File.Exists(solutionFilePath)) { version = VersionStamp.Create(File.GetLastWriteTimeUtc(solutionFilePath)); } } if (version == null) { version = VersionStamp.Create(); } var id = SolutionId.CreateNewId(string.IsNullOrWhiteSpace(solutionFileName) ? null : solutionFileName); var solutionInfo = SolutionInfo.Create(id, version.Value, solutionFilePath, projects: projectInfos); NotifyWorkspace(workspace => workspace.OnSolutionAdded(solutionInfo)); _solutionAdded = true; var persistenceService = WorkspaceServices.GetRequiredService <IPersistentStorageLocationService>() as VisualStudioPersistentStorageLocationService; persistenceService?.UpdateForVisualStudioWorkspace(_workspace); } else { // The solution is already added, so we'll just do project added notifications from here foreach (var projectInfo in projectInfos) { NotifyWorkspace(workspace => workspace.OnProjectAdded(projectInfo)); } } foreach (var project in inOrderToPush) { _pushedProjects.Add(project); foreach (var document in project.GetCurrentDocuments()) { if (document.IsOpen) { NotifyWorkspace(workspace => { workspace.OnDocumentOpened( document.Id, document.GetOpenTextBuffer().AsTextContainer(), isCurrentContext: LinkedFileUtilities.IsCurrentContextHierarchy(document, _runningDocumentTable)); (workspace as VisualStudioWorkspaceImpl)?.ConnectToSharedHierarchyEvents(document); }); } } } } }
public void UpdateSolutionProperties(SolutionId solutionId) { AssertIsForeground(); s_workingFolderPathMap.Remove(solutionId); RegisterSolutionProperties(solutionId); }
/// <summary> /// Get approximate solution size at the point of call. /// /// This API is not supposed to return 100% accurate size. /// /// if a feature require 100% accurate size, use Solution to calculate it. this API is supposed to /// lazy and very cheap on answering that question. /// </summary> public long GetSolutionSize(Workspace workspace, SolutionId solutionId) => IsSupported(workspace) ? _tracker.GetSolutionSize(solutionId) : -1;
public void UpdateSolutionIdStorageLocation(SolutionId solutionId, string storageLocation, CancellationToken cancellationToken) { RemotePersistentStorageLocationService.UpdateStorageLocation(solutionId, storageLocation); }
/// <summary> /// Get approximate solution size at the point of call. /// /// This API is not supposed to return 100% accurate size. /// /// if a feature require 100% accurate size, use Solution to calculate it. this API is supposed to /// lazy and very cheap on answering that question. /// </summary> public long GetSolutionSize(Workspace workspace, SolutionId solutionId) { return(workspace is VisualStudioWorkspaceImpl?_tracker.GetSolutionSize(solutionId) : -1); }
private void SolutionEvents_OnBeforeOpenSolution(object sender, BeforeOpenSolutionEventArgs e) { var stringManager = _stringManager; if (NitraCommonPackage.Configs.Count == 0) { } foreach (var config in NitraCommonPackage.Configs) { var server = new Server(stringManager, config, this); _servers.Add(server); } var solutionPath = e.SolutionFilename; var id = new SolutionId(stringManager.GetId(solutionPath)); _currentSolutionPath = solutionPath; _currentSolutionId = id; foreach (var server in _servers) server.SolutionStartLoading(id, solutionPath); Debug.WriteLine($"tr: BeforeOpenSolution(SolutionFilename='{solutionPath}' id={id})"); }
public void RegisterPrimarySolutionId(SolutionId solutionId, CancellationToken cancellationToken) { var persistentStorageService = GetPersistentStorageService(); persistentStorageService?.RegisterPrimarySolution(solutionId); }
public void UnregisterPrimarySolution(SolutionId solutionId, bool synchronousShutdown) { AbstractPersistentStorage storage = null; lock (_lookupAccessLock) { if (_primarySolutionId == null) { // primary solution is never registered or already unregistered Contract.ThrowIfTrue(_primarySolutionStorage != null); return; } Contract.ThrowIfFalse(_primarySolutionId == solutionId); _primarySolutionId = null; if (_primarySolutionStorage == null) { // primary solution is registered but no C#/VB project was added return; } storage = _primarySolutionStorage; _primarySolutionStorage = null; } if (storage != null) { if (synchronousShutdown) { // dispose storage outside of the lock storage.Dispose(); } else { // make it to shutdown asynchronously Task.Run(() => storage.Dispose()); } } }
public SolutionChecksumObjectInfo(SolutionId id, VersionStamp version, string filePath) { Id = id; Version = version; FilePath = filePath; }