From 43a0ed4871063c97b2c81427b0fe01ac3a82625c Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Mon, 24 Feb 2020 17:05:44 -0800 Subject: [PATCH 01/11] Add FS watcher for settings file --- .../Services/Analysis/AnalysisService.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index 5fd9f5ef0..f85bfd452 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -7,6 +7,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading; @@ -93,6 +94,8 @@ internal static string GetUniqueIdFromDiagnostic(Diagnostic diagnostic) private Lazy _analysisEngine; + private FileSystemWatcher _pssaSettingsFileWatcher; + private CancellationTokenSource _diagnosticsCancellationTokenSource; /// @@ -253,6 +256,21 @@ public void ClearMarkers(ScriptFile file) /// The sender of the configuration update event. /// The new language server settings. public void OnConfigurationUpdated(object sender, LanguageServerSettings settings) + { + ReinitializeAnalysisEngine(); + } + + private void OnSettingsFileDeleted(object sender, FileSystemEventArgs args) + { + if (args.ChangeType != WatcherChangeTypes.Deleted) + { + return; + } + + ReinitializeAnalysisEngine(); + } + + private void ReinitializeAnalysisEngine() { ClearOpenFileMarkers(); _analysisEngine = new Lazy(InstantiateAnalysisEngine); @@ -260,6 +278,12 @@ public void OnConfigurationUpdated(object sender, LanguageServerSettings setting private PssaCmdletAnalysisEngine InstantiateAnalysisEngine() { + if (_pssaSettingsFileWatcher != null) + { + _pssaSettingsFileWatcher.Dispose(); + _pssaSettingsFileWatcher = null; + } + if (!(_configurationService.CurrentSettings.ScriptAnalysis.Enable ?? false)) { return null; @@ -271,6 +295,11 @@ private PssaCmdletAnalysisEngine InstantiateAnalysisEngine() if (TryFindSettingsFile(out string settingsFilePath)) { _logger.LogInformation($"Configuring PSScriptAnalyzer with rules at '{settingsFilePath}'"); + _pssaSettingsFileWatcher = new FileSystemWatcher(settingsFilePath) + { + EnableRaisingEvents = true, + }; + _pssaSettingsFileWatcher.Deleted += OnSettingsFileDeleted; pssaCmdletEngineBuilder.WithSettingsFile(settingsFilePath); } else From 1a532023e6b10c10a3d8bc13543e050fdab184e7 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 10:15:16 -0800 Subject: [PATCH 02/11] Check for existence of settings file --- .../Services/Analysis/AnalysisService.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index f85bfd452..576eac2b9 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -319,12 +319,14 @@ private bool TryFindSettingsFile(out string settingsFilePath) { settingsFilePath = _workplaceService.ResolveWorkspacePath(configuredPath); - if (settingsFilePath == null) + if (settingsFilePath == null + || !File.Exists(settingsFilePath)) { _logger.LogError($"Unable to find PSSA settings file at '{configuredPath}'. Loading default rules."); + return false; } - return settingsFilePath != null; + return true; } // TODO: Could search for a default here From b7bbb2eaa2a98f9f47501610159477797a60e490 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 10:24:06 -0800 Subject: [PATCH 03/11] Watch for more fs events --- .../Services/Analysis/AnalysisService.cs | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index 576eac2b9..9599c65b1 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -260,13 +260,8 @@ public void OnConfigurationUpdated(object sender, LanguageServerSettings setting ReinitializeAnalysisEngine(); } - private void OnSettingsFileDeleted(object sender, FileSystemEventArgs args) + private void OnSettingsFileUpdated(object sender, FileSystemEventArgs args) { - if (args.ChangeType != WatcherChangeTypes.Deleted) - { - return; - } - ReinitializeAnalysisEngine(); } @@ -299,7 +294,7 @@ private PssaCmdletAnalysisEngine InstantiateAnalysisEngine() { EnableRaisingEvents = true, }; - _pssaSettingsFileWatcher.Deleted += OnSettingsFileDeleted; + _pssaSettingsFileWatcher.Changed += OnSettingsFileUpdated; pssaCmdletEngineBuilder.WithSettingsFile(settingsFilePath); } else @@ -315,24 +310,22 @@ private bool TryFindSettingsFile(out string settingsFilePath) { string configuredPath = _configurationService.CurrentSettings.ScriptAnalysis.SettingsPath; - if (!string.IsNullOrEmpty(configuredPath)) + if (string.IsNullOrEmpty(configuredPath)) { - settingsFilePath = _workplaceService.ResolveWorkspacePath(configuredPath); + settingsFilePath = null; + return false; + } - if (settingsFilePath == null - || !File.Exists(settingsFilePath)) - { - _logger.LogError($"Unable to find PSSA settings file at '{configuredPath}'. Loading default rules."); - return false; - } + settingsFilePath = _workplaceService.ResolveWorkspacePath(configuredPath); - return true; + if (settingsFilePath == null + || !File.Exists(settingsFilePath)) + { + _logger.LogError($"Unable to find PSSA settings file at '{configuredPath}'. Loading default rules."); + return false; } - // TODO: Could search for a default here - - settingsFilePath = null; - return false; + return true; } private void ClearOpenFileMarkers() From a25d6bcedcd60f52013f715755e118ca2db82676 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 12:27:33 -0800 Subject: [PATCH 04/11] Fix filesystem watcher logic --- .../Services/Analysis/AnalysisService.cs | 122 ++++++++++++++---- .../Analysis/PssaCmdletAnalysisEngine.cs | 16 +++ 2 files changed, 115 insertions(+), 23 deletions(-) diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index 9599c65b1..bd5da6552 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -78,6 +79,10 @@ internal static string GetUniqueIdFromDiagnostic(Diagnostic diagnostic) "PSPossibleIncorrectUsageOfRedirectionOperator" }; + private static readonly StringComparison s_osPathStringComparison = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) + ? StringComparison.Ordinal + : StringComparison.OrdinalIgnoreCase; + private readonly ILoggerFactory _loggerFactory; private readonly ILogger _logger; @@ -92,7 +97,7 @@ internal static string GetUniqueIdFromDiagnostic(Diagnostic diagnostic) private readonly ConcurrentDictionary _mostRecentCorrectionsByFile; - private Lazy _analysisEngine; + private Lazy _analysisEngineLazy; private FileSystemWatcher _pssaSettingsFileWatcher; @@ -118,13 +123,13 @@ public AnalysisService( _workplaceService = workspaceService; _analysisDelayMillis = 750; _mostRecentCorrectionsByFile = new ConcurrentDictionary(); - _analysisEngine = new Lazy(InstantiateAnalysisEngine); + _analysisEngineLazy = new Lazy(InstantiateAnalysisEngine); } /// /// The analysis engine to use for running script analysis. /// - private PssaCmdletAnalysisEngine AnalysisEngine => _analysisEngine.Value; + private PssaCmdletAnalysisEngine AnalysisEngine => _analysisEngineLazy?.Value; /// /// Sets up a script analysis run, eventually returning the result. @@ -257,44 +262,60 @@ public void ClearMarkers(ScriptFile file) /// The new language server settings. public void OnConfigurationUpdated(object sender, LanguageServerSettings settings) { - ReinitializeAnalysisEngine(); + InitializeAnalysisEngineToCurrentSettings(); } private void OnSettingsFileUpdated(object sender, FileSystemEventArgs args) { - ReinitializeAnalysisEngine(); + InitializeAnalysisEngineToCurrentSettings(); } - private void ReinitializeAnalysisEngine() + private void InitializeAnalysisEngineToCurrentSettings() { - ClearOpenFileMarkers(); - _analysisEngine = new Lazy(InstantiateAnalysisEngine); - } - - private PssaCmdletAnalysisEngine InstantiateAnalysisEngine() - { - if (_pssaSettingsFileWatcher != null) + // If script analysis has been disabled, just return null + if (_configurationService.CurrentSettings.ScriptAnalysis.Enable != true) { - _pssaSettingsFileWatcher.Dispose(); + _pssaSettingsFileWatcher?.Dispose(); _pssaSettingsFileWatcher = null; + + if (_analysisEngineLazy != null && _analysisEngineLazy.IsValueCreated) + { + _analysisEngineLazy.Value.Dispose(); + } + + _analysisEngineLazy = null; + return; } - if (!(_configurationService.CurrentSettings.ScriptAnalysis.Enable ?? false)) + // We may be triggered after the lazy factory is set, + // but before it's been able to instantiate + if (_analysisEngineLazy == null) { - return null; + _analysisEngineLazy = new Lazy(InstantiateAnalysisEngine); + return; } + else if (!_analysisEngineLazy.IsValueCreated) + { + return; + } + + // Retrieve the current script analysis engine so we can recreate it after we've overridden in + PssaCmdletAnalysisEngine currentAnalysisEngine = AnalysisEngine; + // Clear the open file markers and set the new engine factory + ClearOpenFileMarkers(); + _analysisEngineLazy = new Lazy(() => RecreateAnalysisEngine(currentAnalysisEngine)); + } + + private PssaCmdletAnalysisEngine InstantiateAnalysisEngine() + { var pssaCmdletEngineBuilder = new PssaCmdletAnalysisEngine.Builder(_loggerFactory); // If there's a settings file use that if (TryFindSettingsFile(out string settingsFilePath)) { _logger.LogInformation($"Configuring PSScriptAnalyzer with rules at '{settingsFilePath}'"); - _pssaSettingsFileWatcher = new FileSystemWatcher(settingsFilePath) - { - EnableRaisingEvents = true, - }; - _pssaSettingsFileWatcher.Changed += OnSettingsFileUpdated; + SetSettingsFileWatcher(settingsFilePath); pssaCmdletEngineBuilder.WithSettingsFile(settingsFilePath); } else @@ -306,6 +327,54 @@ private PssaCmdletAnalysisEngine InstantiateAnalysisEngine() return pssaCmdletEngineBuilder.Build(); } + private PssaCmdletAnalysisEngine RecreateAnalysisEngine(PssaCmdletAnalysisEngine oldAnalysisEngine) + { + if (TryFindSettingsFile(out string settingsFilePath)) + { + _logger.LogInformation($"Recreating analysis engine with rules at '{settingsFilePath}'"); + SetSettingsFileWatcher(settingsFilePath); + return oldAnalysisEngine.RecreateWithNewSettings(settingsFilePath); + } + + _logger.LogInformation("PSScriptAnalyzer settings file not found. Falling back to default rules"); + return oldAnalysisEngine.RecreateWithRules(s_defaultRules); + } + + private void SetSettingsFileWatcher(string path) + { + string dirPath = Path.GetDirectoryName(path); + string fileName = Path.GetFileName(path); + + if (_pssaSettingsFileWatcher != null) + { + if (string.Equals(dirPath, _pssaSettingsFileWatcher.Path, s_osPathStringComparison)) + { + if (string.Equals(fileName, _pssaSettingsFileWatcher.Filter, s_osPathStringComparison)) + { + // The current watcher is already watching the right file, so we are done + return; + } + + // We just need to update the filter, which we can do without recreating the watcher + _pssaSettingsFileWatcher.Filter = fileName; + return; + } + + // Otherwise we need to remove the old watcher + // and create a new one + _pssaSettingsFileWatcher.Dispose(); + } + + _pssaSettingsFileWatcher = new FileSystemWatcher(dirPath) + { + Filter = fileName, + EnableRaisingEvents = true, + }; + _pssaSettingsFileWatcher.Created += OnSettingsFileUpdated; + _pssaSettingsFileWatcher.Changed += OnSettingsFileUpdated; + _pssaSettingsFileWatcher.Deleted += OnSettingsFileUpdated; + } + private bool TryFindSettingsFile(out string settingsFilePath) { string configuredPath = _configurationService.CurrentSettings.ScriptAnalysis.SettingsPath; @@ -321,7 +390,8 @@ private bool TryFindSettingsFile(out string settingsFilePath) if (settingsFilePath == null || !File.Exists(settingsFilePath)) { - _logger.LogError($"Unable to find PSSA settings file at '{configuredPath}'. Loading default rules."); + _logger.LogWarning($"Unable to find PSSA settings file at '{configuredPath}'. Loading default rules."); + settingsFilePath = null; return false; } @@ -466,8 +536,14 @@ protected virtual void Dispose(bool disposing) { if (disposing) { - if (_analysisEngine.IsValueCreated) { _analysisEngine.Value.Dispose(); } + if (_analysisEngineLazy != null + && _analysisEngineLazy.IsValueCreated) + { + _analysisEngineLazy.Value.Dispose(); + } + _diagnosticsCancellationTokenSource?.Dispose(); + _pssaSettingsFileWatcher?.Dispose(); } disposedValue = true; diff --git a/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs b/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs index 7eb7e9c02..49298b7d1 100644 --- a/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs +++ b/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs @@ -12,6 +12,7 @@ using System.IO; using System.Linq; using System.Management.Automation; +using System.Management.Automation.Remoting; using System.Management.Automation.Runspaces; using System.Text; using System.Threading; @@ -261,6 +262,21 @@ public Task AnalyzeScriptAsync(string scriptContent, Hashtab return GetSemanticMarkersFromCommandAsync(command); } + public PssaCmdletAnalysisEngine RecreateWithNewSettings(string settingsPath) + { + return new PssaCmdletAnalysisEngine(_logger, _analysisRunspacePool, _pssaModuleInfo, settingsPath); + } + + public PssaCmdletAnalysisEngine RecreateWithNewSettings(Hashtable settingsHashtable) + { + return new PssaCmdletAnalysisEngine(_logger, _analysisRunspacePool, _pssaModuleInfo, settingsHashtable); + } + + public PssaCmdletAnalysisEngine RecreateWithRules(string[] rules) + { + return new PssaCmdletAnalysisEngine(_logger, _analysisRunspacePool, _pssaModuleInfo, rules); + } + #region IDisposable Support private bool disposedValue = false; // To detect redundant calls From bba06643b327747ac11fc4fff4fe47869a74518c Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 12:31:00 -0800 Subject: [PATCH 05/11] Improve file watcher disposal --- .../Services/Analysis/AnalysisService.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index bd5da6552..e81393110 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -362,7 +362,7 @@ private void SetSettingsFileWatcher(string path) // Otherwise we need to remove the old watcher // and create a new one - _pssaSettingsFileWatcher.Dispose(); + DisposeCurrentSettingsFileWatcher(); } _pssaSettingsFileWatcher = new FileSystemWatcher(dirPath) @@ -398,6 +398,21 @@ private bool TryFindSettingsFile(out string settingsFilePath) return true; } + private void DisposeCurrentSettingsFileWatcher() + { + if (_pssaSettingsFileWatcher == null) + { + return; + } + + _pssaSettingsFileWatcher.Created -= OnSettingsFileUpdated; + _pssaSettingsFileWatcher.Changed -= OnSettingsFileUpdated; + _pssaSettingsFileWatcher.Deleted -= OnSettingsFileUpdated; + + _pssaSettingsFileWatcher.Dispose(); + _pssaSettingsFileWatcher = null; + } + private void ClearOpenFileMarkers() { foreach (ScriptFile file in _workplaceService.GetOpenedFiles()) @@ -543,7 +558,8 @@ protected virtual void Dispose(bool disposing) } _diagnosticsCancellationTokenSource?.Dispose(); - _pssaSettingsFileWatcher?.Dispose(); + + DisposeCurrentSettingsFileWatcher(); } disposedValue = true; From 71c56b3b01c719c1af43d64a4fb68adf73482c71 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 12:32:25 -0800 Subject: [PATCH 06/11] Remove unused import --- .../Services/Analysis/PssaCmdletAnalysisEngine.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs b/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs index 49298b7d1..eb1617c7d 100644 --- a/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs +++ b/src/PowerShellEditorServices/Services/Analysis/PssaCmdletAnalysisEngine.cs @@ -12,7 +12,6 @@ using System.IO; using System.Linq; using System.Management.Automation; -using System.Management.Automation.Remoting; using System.Management.Automation.Runspaces; using System.Text; using System.Threading; From 7e53410022b82a134e12d471132ad4ca2bb518fb Mon Sep 17 00:00:00 2001 From: Robert Holt Date: Tue, 25 Feb 2020 14:36:56 -0800 Subject: [PATCH 07/11] Update src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs Co-Authored-By: Tyler James Leonhardt --- .../Services/Analysis/AnalysisService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index e81393110..1455a946f 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -299,7 +299,7 @@ private void InitializeAnalysisEngineToCurrentSettings() return; } - // Retrieve the current script analysis engine so we can recreate it after we've overridden in + // Retrieve the current script analysis engine so we can recreate it after we've overridden it PssaCmdletAnalysisEngine currentAnalysisEngine = AnalysisEngine; // Clear the open file markers and set the new engine factory From 7ac5c95f755a252e47a67707b7baef51b6157a8a Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 14:50:07 -0800 Subject: [PATCH 08/11] Remove unnecessary filesystemwatcher --- .../Services/Analysis/AnalysisService.cs | 64 ------------------- 1 file changed, 64 deletions(-) diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index 1455a946f..8777951b1 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -99,8 +99,6 @@ internal static string GetUniqueIdFromDiagnostic(Diagnostic diagnostic) private Lazy _analysisEngineLazy; - private FileSystemWatcher _pssaSettingsFileWatcher; - private CancellationTokenSource _diagnosticsCancellationTokenSource; /// @@ -265,19 +263,11 @@ public void OnConfigurationUpdated(object sender, LanguageServerSettings setting InitializeAnalysisEngineToCurrentSettings(); } - private void OnSettingsFileUpdated(object sender, FileSystemEventArgs args) - { - InitializeAnalysisEngineToCurrentSettings(); - } - private void InitializeAnalysisEngineToCurrentSettings() { // If script analysis has been disabled, just return null if (_configurationService.CurrentSettings.ScriptAnalysis.Enable != true) { - _pssaSettingsFileWatcher?.Dispose(); - _pssaSettingsFileWatcher = null; - if (_analysisEngineLazy != null && _analysisEngineLazy.IsValueCreated) { _analysisEngineLazy.Value.Dispose(); @@ -315,7 +305,6 @@ private PssaCmdletAnalysisEngine InstantiateAnalysisEngine() if (TryFindSettingsFile(out string settingsFilePath)) { _logger.LogInformation($"Configuring PSScriptAnalyzer with rules at '{settingsFilePath}'"); - SetSettingsFileWatcher(settingsFilePath); pssaCmdletEngineBuilder.WithSettingsFile(settingsFilePath); } else @@ -332,7 +321,6 @@ private PssaCmdletAnalysisEngine RecreateAnalysisEngine(PssaCmdletAnalysisEngine if (TryFindSettingsFile(out string settingsFilePath)) { _logger.LogInformation($"Recreating analysis engine with rules at '{settingsFilePath}'"); - SetSettingsFileWatcher(settingsFilePath); return oldAnalysisEngine.RecreateWithNewSettings(settingsFilePath); } @@ -340,41 +328,6 @@ private PssaCmdletAnalysisEngine RecreateAnalysisEngine(PssaCmdletAnalysisEngine return oldAnalysisEngine.RecreateWithRules(s_defaultRules); } - private void SetSettingsFileWatcher(string path) - { - string dirPath = Path.GetDirectoryName(path); - string fileName = Path.GetFileName(path); - - if (_pssaSettingsFileWatcher != null) - { - if (string.Equals(dirPath, _pssaSettingsFileWatcher.Path, s_osPathStringComparison)) - { - if (string.Equals(fileName, _pssaSettingsFileWatcher.Filter, s_osPathStringComparison)) - { - // The current watcher is already watching the right file, so we are done - return; - } - - // We just need to update the filter, which we can do without recreating the watcher - _pssaSettingsFileWatcher.Filter = fileName; - return; - } - - // Otherwise we need to remove the old watcher - // and create a new one - DisposeCurrentSettingsFileWatcher(); - } - - _pssaSettingsFileWatcher = new FileSystemWatcher(dirPath) - { - Filter = fileName, - EnableRaisingEvents = true, - }; - _pssaSettingsFileWatcher.Created += OnSettingsFileUpdated; - _pssaSettingsFileWatcher.Changed += OnSettingsFileUpdated; - _pssaSettingsFileWatcher.Deleted += OnSettingsFileUpdated; - } - private bool TryFindSettingsFile(out string settingsFilePath) { string configuredPath = _configurationService.CurrentSettings.ScriptAnalysis.SettingsPath; @@ -398,21 +351,6 @@ private bool TryFindSettingsFile(out string settingsFilePath) return true; } - private void DisposeCurrentSettingsFileWatcher() - { - if (_pssaSettingsFileWatcher == null) - { - return; - } - - _pssaSettingsFileWatcher.Created -= OnSettingsFileUpdated; - _pssaSettingsFileWatcher.Changed -= OnSettingsFileUpdated; - _pssaSettingsFileWatcher.Deleted -= OnSettingsFileUpdated; - - _pssaSettingsFileWatcher.Dispose(); - _pssaSettingsFileWatcher = null; - } - private void ClearOpenFileMarkers() { foreach (ScriptFile file in _workplaceService.GetOpenedFiles()) @@ -558,8 +496,6 @@ protected virtual void Dispose(bool disposing) } _diagnosticsCancellationTokenSource?.Dispose(); - - DisposeCurrentSettingsFileWatcher(); } disposedValue = true; From ac1f1d5b996a9aa59c8925ac7c795b3acde1da83 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 14:57:22 -0800 Subject: [PATCH 09/11] Remove now unused string comparison --- .../Services/Analysis/AnalysisService.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index 8777951b1..a7895fb25 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -79,10 +79,6 @@ internal static string GetUniqueIdFromDiagnostic(Diagnostic diagnostic) "PSPossibleIncorrectUsageOfRedirectionOperator" }; - private static readonly StringComparison s_osPathStringComparison = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) - ? StringComparison.Ordinal - : StringComparison.OrdinalIgnoreCase; - private readonly ILoggerFactory _loggerFactory; private readonly ILogger _logger; From e182703bb02f74ff92dde9edc67c68abcdfba909 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 15:18:14 -0800 Subject: [PATCH 10/11] Poll for settings file --- .../Services/Analysis/AnalysisService.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index a7895fb25..0b3b88939 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -97,6 +97,8 @@ internal static string GetUniqueIdFromDiagnostic(Diagnostic diagnostic) private CancellationTokenSource _diagnosticsCancellationTokenSource; + private string _pssaSettingsFilePath; + /// /// Construct a new AnalysisService. /// @@ -118,6 +120,7 @@ public AnalysisService( _analysisDelayMillis = 750; _mostRecentCorrectionsByFile = new ConcurrentDictionary(); _analysisEngineLazy = new Lazy(InstantiateAnalysisEngine); + _pssaSettingsFilePath = null; } /// @@ -140,6 +143,8 @@ public void RunScriptDiagnostics( return; } + EnsureEngineSettingsCurrent(); + // Create a cancellation token source that will cancel if we do or if the caller does var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); @@ -190,6 +195,8 @@ public Task FormatAsync(string scriptFileContents, Hashtable formatSetti return null; } + EnsureEngineSettingsCurrent(); + return AnalysisEngine.FormatAsync(scriptFileContents, formatSettings, formatRange); } @@ -259,6 +266,15 @@ public void OnConfigurationUpdated(object sender, LanguageServerSettings setting InitializeAnalysisEngineToCurrentSettings(); } + private void EnsureEngineSettingsCurrent() + { + if (_pssaSettingsFilePath != null + && !File.Exists(_pssaSettingsFilePath)) + { + InitializeAnalysisEngineToCurrentSettings(); + } + } + private void InitializeAnalysisEngineToCurrentSettings() { // If script analysis has been disabled, just return null @@ -301,6 +317,7 @@ private PssaCmdletAnalysisEngine InstantiateAnalysisEngine() if (TryFindSettingsFile(out string settingsFilePath)) { _logger.LogInformation($"Configuring PSScriptAnalyzer with rules at '{settingsFilePath}'"); + _pssaSettingsFilePath = settingsFilePath; pssaCmdletEngineBuilder.WithSettingsFile(settingsFilePath); } else @@ -317,6 +334,7 @@ private PssaCmdletAnalysisEngine RecreateAnalysisEngine(PssaCmdletAnalysisEngine if (TryFindSettingsFile(out string settingsFilePath)) { _logger.LogInformation($"Recreating analysis engine with rules at '{settingsFilePath}'"); + _pssaSettingsFilePath = settingsFilePath; return oldAnalysisEngine.RecreateWithNewSettings(settingsFilePath); } From a99fc69569befa90c60cbcf81fb52e5863b7febb Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 15:34:43 -0800 Subject: [PATCH 11/11] Fix placement of settings file check --- .../Services/Analysis/AnalysisService.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs index 0b3b88939..873a269f9 100644 --- a/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs @@ -138,13 +138,13 @@ public void RunScriptDiagnostics( ScriptFile[] filesToAnalyze, CancellationToken cancellationToken) { + EnsureEngineSettingsCurrent(); + if (AnalysisEngine == null) { return; } - EnsureEngineSettingsCurrent(); - // Create a cancellation token source that will cancel if we do or if the caller does var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); @@ -190,13 +190,13 @@ public void RunScriptDiagnostics( /// The text of the formatted PowerShell script. public Task FormatAsync(string scriptFileContents, Hashtable formatSettings, int[] formatRange = null) { + EnsureEngineSettingsCurrent(); + if (AnalysisEngine == null) { return null; } - EnsureEngineSettingsCurrent(); - return AnalysisEngine.FormatAsync(scriptFileContents, formatSettings, formatRange); }