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);
        }
Exemple #2
0
        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}'");
        }
Exemple #3
0
 public ProjectToUpdate(string filePath, bool allowAutoRestore, ProjectIdInfo projectIdInfo)
 {
     ProjectIdInfo    = projectIdInfo ?? throw new ArgumentNullException(nameof(projectIdInfo));
     FilePath         = filePath ?? throw new ArgumentNullException(nameof(filePath));
     AllowAutoRestore = allowAutoRestore;
 }
Exemple #4
0
 private (ProjectFileInfo, ProjectLoadedEventArgs) LoadProject(string projectFilePath, ProjectIdInfo idInfo)
 => LoadOrReloadProject(projectFilePath, () => ProjectFileInfo.Load(projectFilePath, idInfo, _projectLoader, _sessionId, _dotNetInfo));
Exemple #5
0
 public void QueueProjectUpdate(string projectFilePath, bool allowAutoRestore, ProjectIdInfo projectId)
 {
     _logger.LogInformation($"Queue project update for '{projectFilePath}'");
     _queue.Post(new ProjectToUpdate(projectFilePath, allowAutoRestore, projectId));
 }
Exemple #6
0
        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);
        }