From bef50c7ffb7a180ae2318170a14906114bb1d513 Mon Sep 17 00:00:00 2001 From: Joey Robichaud Date: Fri, 10 Sep 2021 21:23:35 -0700 Subject: [PATCH] Handle .editorconfig changes without running a new design time build --- src/OmniSharp.MSBuild/ProjectManager.cs | 61 ++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/src/OmniSharp.MSBuild/ProjectManager.cs b/src/OmniSharp.MSBuild/ProjectManager.cs index 2bf70ca9b1..6dd5497518 100644 --- a/src/OmniSharp.MSBuild/ProjectManager.cs +++ b/src/OmniSharp.MSBuild/ProjectManager.cs @@ -392,7 +392,7 @@ private void WatchProjectFiles(ProjectFileInfo projectFileInfo) // Watch beneath the Project folder for changes to .editorconfig files. _fileSystemWatcher.Watch(".editorconfig", (file, changeType) => { - QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false, projectFileInfo.ProjectIdInfo, file); + UpdateAnalyzerConfigFile(projectFileInfo, file, changeType); }); // Watch in folders above the Project folder for changes to .editorconfig files. @@ -406,7 +406,7 @@ private void WatchProjectFiles(ProjectFileInfo projectFileInfo) _fileSystemWatcher.Watch(Path.Combine(parentPath, ".editorconfig"), (file, changeType) => { - QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false, projectFileInfo.ProjectIdInfo, file); + UpdateAnalyzerConfigFile(projectFileInfo, file, changeType); }); } } @@ -465,7 +465,7 @@ private void UpdateProject(string projectFilePath, string changeTriggerFilePath) } // if the update was triggered by a change to an editorconfig file, only reload that analyzer config file - // this will propagata a reanalysis of the project + // this will propagate a reanalysis of the project if (changeTriggerFilePath != null && changeTriggerFilePath.ToLowerInvariant().EndsWith(".editorconfig")) { UpdateAnalyzerConfigFile(project, changeTriggerFilePath); @@ -556,6 +556,30 @@ private void UpdateAdditionalFiles(Project project, IList additionalFile } } + private void UpdateAnalyzerConfigFile(ProjectFileInfo projectFileInfo, string analyzerConfigFile, FileChangeType changeType) + { + var project = _workspace.CurrentSolution.GetProject(projectFileInfo.Id); + + // Since an .editorconfig file of MSBuild properties is generated by the SDK during builds, + // update the analyzer config file without requesting a new design time build. + switch (changeType) + { + case FileChangeType.Create: + _workspace.AddAnalyzerConfigDocument(projectFileInfo.Id, analyzerConfigFile); + _logger.LogDebug($"Added {analyzerConfigFile} to project {project.Name}."); + break; + case FileChangeType.Change: + UpdateAnalyzerConfigFile(project, analyzerConfigFile); + break; + case FileChangeType.Delete: + RemoveAnalyzerConfigFile(project, analyzerConfigFile); + break; + default: + QueueProjectUpdate(projectFileInfo.FilePath, allowAutoRestore: false, projectFileInfo.ProjectIdInfo, analyzerConfigFile); + break; + } + } + private void UpdateAnalyzerConfigFile(Project project, string analyzerConfigFile) { if (!_workspace.EditorConfigEnabled) @@ -581,6 +605,31 @@ private void UpdateAnalyzerConfigFile(Project project, string analyzerConfigFile _logger.LogDebug($"Reloaded {currentAnalyzerConfigDocument.Id} from {analyzerConfigFile} in project {project.Name}."); } + private void RemoveAnalyzerConfigFile(Project project, string analyzerConfigFile) + { + if (!_workspace.EditorConfigEnabled) + { + _logger.LogDebug($".editorconfig files were configured by the project {project.Name} but will not be respected because the feature is switched off in OmniSharp. Enable .editorconfig support in OmniSharp to take advantage of them."); + return; + } + + var currentAnalyzerConfigDocument = project.AnalyzerConfigDocuments.FirstOrDefault(x => x.FilePath.Equals(analyzerConfigFile)); + if (currentAnalyzerConfigDocument == null) + { + _logger.LogDebug($"The change was reported in {analyzerConfigFile} but it doesn't belong to any project."); + return; + } + + if (!File.Exists(analyzerConfigFile)) + { + _logger.LogWarning($"The change was reported in {analyzerConfigFile} but it doesn't exist on disk."); + return; + } + + _workspace.RemoveAnalyzerConfigDocument(currentAnalyzerConfigDocument.Id); + _logger.LogDebug($"Removed {currentAnalyzerConfigDocument.Id} from {analyzerConfigFile} in project {project.Name}."); + } + private void UpdateAnalyzerConfigFiles(Project project, IList analyzerConfigFiles) { if (!_workspace.EditorConfigEnabled) @@ -736,8 +785,8 @@ private void UpdateProjectReferences(Project project, ImmutableArray pro if (projectFileInfo.ProjectReferenceAliases.TryGetValue(projectReferencePath, out var projectReferenceAliases)) { if (!string.IsNullOrEmpty(projectReferenceAliases)) - { - aliases = ImmutableArray.CreateRange(projectReferenceAliases.Split(new char[]{','},StringSplitOptions.RemoveEmptyEntries).Select(a => a.Trim())); + { + aliases = ImmutableArray.CreateRange(projectReferenceAliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(a => a.Trim())); _logger.LogDebug($"Setting aliases: {projectReferencePath}, {projectReferenceAliases} "); } } @@ -806,7 +855,7 @@ private void UpdateReferences(Project project, ImmutableArray projectRef { if (!string.IsNullOrEmpty(aliases)) { - reference = reference.WithAliases(aliases.Split(new char[]{','},StringSplitOptions.RemoveEmptyEntries).Select(a => a.Trim())); + reference = reference.WithAliases(aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(a => a.Trim())); _logger.LogDebug($"Setting aliases: {referencePath}, {aliases} "); } }