private IEnumerable <(string, ProjectIdInfo)> GetProjectPathsAndIdsFromSolution(string solutionFilePath) { _logger.LogInformation($"Detecting projects in '{solutionFilePath}'."); var solutionFile = SolutionFile.ParseFile(solutionFilePath); var processedProjects = new HashSet <string>(StringComparer.OrdinalIgnoreCase); var result = new List <(string, ProjectIdInfo)>(); foreach (var project in solutionFile.Projects) { if (project.IsNotSupported) { continue; } // Solution files are assumed to contain relative paths to project files with Windows-style slashes. var projectFilePath = project.RelativePath.Replace('\\', Path.DirectorySeparatorChar); projectFilePath = Path.Combine(_environment.TargetDirectory, projectFilePath); projectFilePath = Path.GetFullPath(projectFilePath); // Have we seen this project? If so, move on. if (processedProjects.Contains(projectFilePath)) { continue; } if (string.Equals(Path.GetExtension(projectFilePath), ".csproj", StringComparison.OrdinalIgnoreCase)) { var projectIdInfo = new ProjectIdInfo(ProjectId.CreateFromSerialized(new Guid(project.ProjectGuid)), true); result.Add((projectFilePath, projectIdInfo)); } processedProjects.Add(projectFilePath); } return(result); }
private async Task WaitForProjectModelReadyAsync(string documentPath) { // Search and queue for loading C# projects that are likely to reference the requested file. // C# source files are located pretty much always in the same folder with their project file or in a subfolder below. // Search up the root folder to enable on-demand project load in additional scenarios like the following: // - A subfolder in a big codebase was opened in VSCode and then a document was opened that is located outside of the subfoler. // - A workspace was opened in VSCode that includes multiple subfolders from a big codebase. // - Documents from different codebases are opened in the same VSCode workspace. string projectDir = Path.GetDirectoryName(documentPath); do { var csProjFiles = Directory.EnumerateFiles(projectDir, "*.csproj", SearchOption.TopDirectoryOnly).ToList(); if (csProjFiles.Count > 0) { foreach (string csProjFile in csProjFiles) { if (_projectsRequestedOnDemand.TryAdd(csProjFile, 0 /*unused*/)) { var projectIdInfo = new ProjectIdInfo(ProjectId.CreateNewId(csProjFile), false); QueueProjectUpdate(csProjFile, allowAutoRestore: true, projectId: projectIdInfo); } } break; } projectDir = Path.GetDirectoryName(projectDir); } while (projectDir != null); // Wait for all queued projects to load to ensure that workspace is fully up to date before this method completes. // If the project for the document was loaded before and there are no other projects to load at the moment, the call below will be no-op. _logger.LogTrace($"Started waiting for projects queue to be empty when requested '{documentPath}'"); await WaitForQueueEmptyAsync(); _logger.LogTrace($"Stopped waiting for projects queue to be empty when requested '{documentPath}'"); }
public ProjectToUpdate(string filePath, bool allowAutoRestore, ProjectIdInfo projectIdInfo) { ProjectIdInfo = projectIdInfo ?? throw new ArgumentNullException(nameof(projectIdInfo)); FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); AllowAutoRestore = allowAutoRestore; }
private (ProjectFileInfo, ProjectLoadedEventArgs) LoadProject(string projectFilePath, ProjectIdInfo idInfo) => LoadOrReloadProject(projectFilePath, () => ProjectFileInfo.Load(projectFilePath, idInfo, _projectLoader, _sessionId, _dotNetInfo));
public void QueueProjectUpdate(string projectFilePath, bool allowAutoRestore, ProjectIdInfo projectId) { _logger.LogInformation($"Queue project update for '{projectFilePath}'"); _queue.Post(new ProjectToUpdate(projectFilePath, allowAutoRestore, projectId)); }
private IEnumerable <(string, ProjectIdInfo)> GetProjectPathsAndIdsFromSolution(string solutionFilePath) { _logger.LogInformation($"Detecting projects in '{solutionFilePath}'."); var solutionFile = SolutionFile.ParseFile(solutionFilePath); var processedProjects = new HashSet <string>(StringComparer.OrdinalIgnoreCase); var result = new List <(string, ProjectIdInfo)>(); var solutionConfigurations = new Dictionary <ProjectId, Dictionary <string, string> >(); foreach (var globalSection in solutionFile.GlobalSections) { // Try parse project configurations if they are remapped in solution file if (globalSection.Name == "ProjectConfigurationPlatforms") { _logger.LogDebug($"Parsing ProjectConfigurationPlatforms of '{solutionFilePath}'."); foreach (var entry in globalSection.Properties) { var guid = Guid.Parse(entry.Name.Substring(0, 38)); var projId = ProjectId.CreateFromSerialized(guid); var solutionConfig = entry.Name.Substring(39); if (!solutionConfigurations.TryGetValue(projId, out var dict)) { dict = new Dictionary <string, string>(); solutionConfigurations.Add(projId, dict); } dict.Add(solutionConfig, entry.Value); } } } foreach (var project in solutionFile.Projects) { if (project.IsNotSupported) { continue; } // Solution files are assumed to contain relative paths to project files with Windows-style slashes. var projectFilePath = project.RelativePath.Replace('\\', Path.DirectorySeparatorChar); projectFilePath = Path.Combine(_environment.TargetDirectory, projectFilePath); projectFilePath = Path.GetFullPath(projectFilePath); // Have we seen this project? If so, move on. if (processedProjects.Contains(projectFilePath)) { continue; } if (string.Equals(Path.GetExtension(projectFilePath), ".csproj", StringComparison.OrdinalIgnoreCase)) { var projectIdInfo = new ProjectIdInfo(ProjectId.CreateFromSerialized(new Guid(project.ProjectGuid)), true); if (solutionConfigurations.TryGetValue(projectIdInfo.Id, out var configurations)) { projectIdInfo.SolutionConfiguration = configurations; } result.Add((projectFilePath, projectIdInfo)); } processedProjects.Add(projectFilePath); } return(result); }