diff --git a/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs b/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs index 0e97b8edd4..2099c71705 100644 --- a/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs +++ b/src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs @@ -1192,7 +1192,7 @@ protected async Task HandleCommentHelpRequestAsync( funcText = string.Join("\n", lines); } - ScriptFileMarker[] analysisResults = await this.editorSession.AnalysisService.GetSemanticMarkersAsync( + List analysisResults = await this.editorSession.AnalysisService.GetSemanticMarkersAsync( funcText, AnalysisService.GetCommentHelpRuleSettings( enable: true, @@ -1743,7 +1743,7 @@ await PublishScriptDiagnosticsAsync( // Get the requested files foreach (ScriptFile scriptFile in filesToAnalyze) { - ScriptFileMarker[] semanticMarkers = null; + List semanticMarkers = null; if (isScriptAnalysisEnabled && editorSession.AnalysisService != null) { using (Logger.LogExecutionTime($"Script analysis of {scriptFile.FilePath} completed.")) @@ -1755,13 +1755,16 @@ await PublishScriptDiagnosticsAsync( { // Semantic markers aren't available if the AnalysisService // isn't available - semanticMarkers = new ScriptFileMarker[0]; + semanticMarkers = new List(); } + // First we remove any + scriptFile.SyntaxMarkers = semanticMarkers; + await PublishScriptDiagnosticsAsync( scriptFile, // Concat script analysis errors to any existing parse errors - scriptFile.SyntaxMarkers.Concat(semanticMarkers).ToArray(), + scriptFile.SyntaxMarkers, correctionIndex, eventSender); } @@ -1772,14 +1775,14 @@ private async Task ClearMarkersAsync(ScriptFile scriptFile, EventContext eventCo // send empty diagnostic markers to clear any markers associated with the given file await PublishScriptDiagnosticsAsync( scriptFile, - new ScriptFileMarker[0], + new List(), this.codeActionsPerFile, eventContext); } private static async Task PublishScriptDiagnosticsAsync( ScriptFile scriptFile, - ScriptFileMarker[] markers, + List markers, Dictionary> correctionIndex, EventContext eventContext) { @@ -1792,7 +1795,7 @@ await PublishScriptDiagnosticsAsync( private static async Task PublishScriptDiagnosticsAsync( ScriptFile scriptFile, - ScriptFileMarker[] markers, + List markers, Dictionary> correctionIndex, Func, PublishDiagnosticsNotification, Task> eventSender) { diff --git a/src/PowerShellEditorServices/Analysis/AnalysisService.cs b/src/PowerShellEditorServices/Analysis/AnalysisService.cs index d872263775..4b43cd2479 100644 --- a/src/PowerShellEditorServices/Analysis/AnalysisService.cs +++ b/src/PowerShellEditorServices/Analysis/AnalysisService.cs @@ -55,7 +55,7 @@ public class AnalysisService : IDisposable /// /// An empty script marker result to return when no script markers can be returned. /// - private static readonly ScriptFileMarker[] s_emptyScriptMarkerResult = new ScriptFileMarker[0]; + private static readonly List s_emptyScriptMarkerResult = new List(); private static readonly string[] s_emptyGetRuleResult = new string[0]; @@ -266,7 +266,7 @@ public static Hashtable GetPSSASettingsHashtable(IDictionary /// /// The ScriptFile which will be analyzed for semantic markers. /// An array of ScriptFileMarkers containing semantic analysis results. - public async Task GetSemanticMarkersAsync(ScriptFile file) + public async Task> GetSemanticMarkersAsync(ScriptFile file) { return await GetSemanticMarkersAsync(file, ActiveRules, SettingsPath); } @@ -277,7 +277,7 @@ public async Task GetSemanticMarkersAsync(ScriptFile file) /// The ScriptFile to be analyzed. /// ScriptAnalyzer settings /// - public async Task GetSemanticMarkersAsync(ScriptFile file, Hashtable settings) + public async Task> GetSemanticMarkersAsync(ScriptFile file, Hashtable settings) { return await GetSemanticMarkersAsync(file, null, settings); } @@ -288,7 +288,7 @@ public async Task GetSemanticMarkersAsync(ScriptFile file, H /// The script content to be analyzed. /// ScriptAnalyzer settings /// - public async Task GetSemanticMarkersAsync( + public async Task> GetSemanticMarkersAsync( string scriptContent, Hashtable settings) { @@ -379,7 +379,7 @@ public async Task FormatAsync( #region Private Methods - private async Task GetSemanticMarkersAsync( + private async Task> GetSemanticMarkersAsync( ScriptFile file, string[] rules, TSettings settings) where TSettings : class @@ -398,7 +398,7 @@ private async Task GetSemanticMarkersAsync( } } - private async Task GetSemanticMarkersAsync( + private async Task> GetSemanticMarkersAsync( string scriptContent, string[] rules, TSettings settings) where TSettings : class @@ -407,7 +407,7 @@ private async Task GetSemanticMarkersAsync( && (rules != null || settings != null)) { var scriptFileMarkers = await GetDiagnosticRecordsAsync(scriptContent, rules, settings); - return scriptFileMarkers.Select(ScriptFileMarker.FromDiagnosticRecord).ToArray(); + return scriptFileMarkers.Select(ScriptFileMarker.FromDiagnosticRecord).ToList(); } else { diff --git a/src/PowerShellEditorServices/Workspace/ScriptFile.cs b/src/PowerShellEditorServices/Workspace/ScriptFile.cs index c2806a7fb2..4a9b5e0f15 100644 --- a/src/PowerShellEditorServices/Workspace/ScriptFile.cs +++ b/src/PowerShellEditorServices/Workspace/ScriptFile.cs @@ -100,11 +100,7 @@ public string Contents /// Gets the list of syntax markers found by parsing this /// file's contents. /// - public ScriptFileMarker[] SyntaxMarkers - { - get; - private set; - } + public List SyntaxMarkers { get; set; } /// /// Gets the list of strings for each line of the file. @@ -589,13 +585,11 @@ private void SetFileContents(string fileContents) } /// - /// Parses the current file contents to get the AST, tokens, - /// and parse errors. + /// Parses the current file contents to get the AST and tokens. + /// Parse errors are ignored because PSScriptAnalyzer provides those to us. /// private void ParseFileContents() { - ParseError[] parseErrors = null; - // First, get the updated file range int lineCount = this.FileLines.Count; if (lineCount > 0) @@ -627,7 +621,7 @@ private void ParseFileContents() this.Contents, this.FilePath, out scriptTokens, - out parseErrors); + errors: out _); } else { @@ -635,30 +629,17 @@ private void ParseFileContents() Parser.ParseInput( this.Contents, out scriptTokens, - out parseErrors); + errors: out _); } this.ScriptTokens = scriptTokens; } - catch (RuntimeException ex) + catch (RuntimeException) { - var parseError = - new ParseError( - null, - ex.ErrorRecord.FullyQualifiedErrorId, - ex.Message); - - parseErrors = new[] { parseError }; this.ScriptTokens = new Token[0]; this.ScriptAst = null; } - // Translate parse errors into syntax markers - this.SyntaxMarkers = - parseErrors - .Select(ScriptFileMarker.FromParseError) - .ToArray(); - // Untitled files have no directory // Discussed in https://github.com/PowerShell/PowerShellEditorServices/pull/815. // Rather than working hard to enable things for untitled files like a phantom directory, diff --git a/src/PowerShellEditorServices/Workspace/ScriptFileMarker.cs b/src/PowerShellEditorServices/Workspace/ScriptFileMarker.cs index 0a36b313ae..b48107bc3c 100644 --- a/src/PowerShellEditorServices/Workspace/ScriptFileMarker.cs +++ b/src/PowerShellEditorServices/Workspace/ScriptFileMarker.cs @@ -164,31 +164,27 @@ internal static ScriptFileMarker FromDiagnosticRecord(PSObject psObject) }; } + string severity = diagnosticRecord.Severity.ToString(); + if(!Enum.TryParse(severity, out ScriptFileMarkerLevel level)) + { + throw new ArgumentException( + string.Format( + "The provided DiagnosticSeverity value '{0}' is unknown.", + severity), + "diagnosticSeverity"); + } + return new ScriptFileMarker { Message = $"{diagnosticRecord.Message as string}", RuleName = $"{diagnosticRecord.RuleName as string}", - Level = GetMarkerLevelFromDiagnosticSeverity((diagnosticRecord.Severity as Enum).ToString()), + Level = level, ScriptRegion = ScriptRegion.Create(diagnosticRecord.Extent as IScriptExtent), Correction = correction, Source = "PSScriptAnalyzer" }; } - private static ScriptFileMarkerLevel GetMarkerLevelFromDiagnosticSeverity( - string diagnosticSeverity) - { - if(Enum.TryParse(diagnosticSeverity, out ScriptFileMarkerLevel level)) - { - return level; - } - - throw new ArgumentException( - string.Format( - "The provided DiagnosticSeverity value '{0}' is unknown.", - diagnosticSeverity), - "diagnosticSeverity"); - } #endregion } }