Skip to content

Commit 3c6b478

Browse files
cherry pick #888 Add new ParseError level to ScriptFileMarkerLevel and only have it send parse errors (#891)
1 parent a96b282 commit 3c6b478

File tree

5 files changed

+60
-61
lines changed

5 files changed

+60
-61
lines changed

src/PowerShellEditorServices.Protocol/Server/LanguageServer.cs

+18-7
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,7 @@ protected async Task HandleCommentHelpRequest(
12151215
funcText = string.Join("\n", lines);
12161216
}
12171217

1218-
ScriptFileMarker[] analysisResults = await this.editorSession.AnalysisService.GetSemanticMarkersAsync(
1218+
List<ScriptFileMarker> analysisResults = await this.editorSession.AnalysisService.GetSemanticMarkersAsync(
12191219
funcText,
12201220
AnalysisService.GetCommentHelpRuleSettings(
12211221
enable: true,
@@ -1728,6 +1728,15 @@ private static async Task DelayThenInvokeDiagnostics(
17281728
catch (TaskCanceledException)
17291729
{
17301730
// If the task is cancelled, exit directly
1731+
foreach (var script in filesToAnalyze)
1732+
{
1733+
await PublishScriptDiagnostics(
1734+
script,
1735+
script.DiagnosticMarkers,
1736+
correctionIndex,
1737+
eventSender);
1738+
}
1739+
17311740
return;
17321741
}
17331742

@@ -1741,7 +1750,7 @@ private static async Task DelayThenInvokeDiagnostics(
17411750
// Get the requested files
17421751
foreach (ScriptFile scriptFile in filesToAnalyze)
17431752
{
1744-
ScriptFileMarker[] semanticMarkers = null;
1753+
List<ScriptFileMarker> semanticMarkers = null;
17451754
if (isScriptAnalysisEnabled && editorSession.AnalysisService != null)
17461755
{
17471756
using (Logger.LogExecutionTime($"Script analysis of {scriptFile.FilePath} completed."))
@@ -1753,13 +1762,15 @@ private static async Task DelayThenInvokeDiagnostics(
17531762
{
17541763
// Semantic markers aren't available if the AnalysisService
17551764
// isn't available
1756-
semanticMarkers = new ScriptFileMarker[0];
1765+
semanticMarkers = new List<ScriptFileMarker>();
17571766
}
17581767

1768+
scriptFile.DiagnosticMarkers.AddRange(semanticMarkers);
1769+
17591770
await PublishScriptDiagnostics(
17601771
scriptFile,
17611772
// Concat script analysis errors to any existing parse errors
1762-
scriptFile.SyntaxMarkers.Concat(semanticMarkers).ToArray(),
1773+
scriptFile.DiagnosticMarkers,
17631774
correctionIndex,
17641775
eventSender);
17651776
}
@@ -1770,14 +1781,14 @@ private async Task ClearMarkers(ScriptFile scriptFile, EventContext eventContext
17701781
// send empty diagnostic markers to clear any markers associated with the given file
17711782
await PublishScriptDiagnostics(
17721783
scriptFile,
1773-
new ScriptFileMarker[0],
1784+
new List<ScriptFileMarker>(),
17741785
this.codeActionsPerFile,
17751786
eventContext);
17761787
}
17771788

17781789
private static async Task PublishScriptDiagnostics(
17791790
ScriptFile scriptFile,
1780-
ScriptFileMarker[] markers,
1791+
List<ScriptFileMarker> markers,
17811792
Dictionary<string, Dictionary<string, MarkerCorrection>> correctionIndex,
17821793
EventContext eventContext)
17831794
{
@@ -1790,7 +1801,7 @@ await PublishScriptDiagnostics(
17901801

17911802
private static async Task PublishScriptDiagnostics(
17921803
ScriptFile scriptFile,
1793-
ScriptFileMarker[] markers,
1804+
List<ScriptFileMarker> markers,
17941805
Dictionary<string, Dictionary<string, MarkerCorrection>> correctionIndex,
17951806
Func<NotificationType<PublishDiagnosticsNotification, object>, PublishDiagnosticsNotification, Task> eventSender)
17961807
{

src/PowerShellEditorServices/Analysis/AnalysisService.cs

+11-14
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,6 @@ public class AnalysisService : IDisposable
5252
/// </summary>
5353
private static readonly PSObject[] s_emptyDiagnosticResult = new PSObject[0];
5454

55-
/// <summary>
56-
/// An empty script marker result to return when no script markers can be returned.
57-
/// </summary>
58-
private static readonly ScriptFileMarker[] s_emptyScriptMarkerResult = new ScriptFileMarker[0];
59-
6055
private static readonly string[] s_emptyGetRuleResult = new string[0];
6156

6257
/// <summary>
@@ -266,7 +261,7 @@ public static Hashtable GetPSSASettingsHashtable(IDictionary<string, Hashtable>
266261
/// </summary>
267262
/// <param name="file">The ScriptFile which will be analyzed for semantic markers.</param>
268263
/// <returns>An array of ScriptFileMarkers containing semantic analysis results.</returns>
269-
public async Task<ScriptFileMarker[]> GetSemanticMarkersAsync(ScriptFile file)
264+
public async Task<List<ScriptFileMarker>> GetSemanticMarkersAsync(ScriptFile file)
270265
{
271266
return await GetSemanticMarkersAsync<string>(file, ActiveRules, SettingsPath);
272267
}
@@ -277,7 +272,7 @@ public async Task<ScriptFileMarker[]> GetSemanticMarkersAsync(ScriptFile file)
277272
/// <param name="file">The ScriptFile to be analyzed.</param>
278273
/// <param name="settings">ScriptAnalyzer settings</param>
279274
/// <returns></returns>
280-
public async Task<ScriptFileMarker[]> GetSemanticMarkersAsync(ScriptFile file, Hashtable settings)
275+
public async Task<List<ScriptFileMarker>> GetSemanticMarkersAsync(ScriptFile file, Hashtable settings)
281276
{
282277
return await GetSemanticMarkersAsync<Hashtable>(file, null, settings);
283278
}
@@ -288,7 +283,7 @@ public async Task<ScriptFileMarker[]> GetSemanticMarkersAsync(ScriptFile file, H
288283
/// <param name="scriptContent">The script content to be analyzed.</param>
289284
/// <param name="settings">ScriptAnalyzer settings</param>
290285
/// <returns></returns>
291-
public async Task<ScriptFileMarker[]> GetSemanticMarkersAsync(
286+
public async Task<List<ScriptFileMarker>> GetSemanticMarkersAsync(
292287
string scriptContent,
293288
Hashtable settings)
294289
{
@@ -379,7 +374,7 @@ public async Task<string> Format(
379374

380375
#region Private Methods
381376

382-
private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
377+
private async Task<List<ScriptFileMarker>> GetSemanticMarkersAsync<TSettings>(
383378
ScriptFile file,
384379
string[] rules,
385380
TSettings settings) where TSettings : class
@@ -394,11 +389,11 @@ private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
394389
else
395390
{
396391
// Return an empty marker list
397-
return s_emptyScriptMarkerResult;
392+
return new List<ScriptFileMarker>();
398393
}
399394
}
400395

401-
private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
396+
private async Task<List<ScriptFileMarker>> GetSemanticMarkersAsync<TSettings>(
402397
string scriptContent,
403398
string[] rules,
404399
TSettings settings) where TSettings : class
@@ -407,12 +402,12 @@ private async Task<ScriptFileMarker[]> GetSemanticMarkersAsync<TSettings>(
407402
&& (rules != null || settings != null))
408403
{
409404
var scriptFileMarkers = await GetDiagnosticRecordsAsync(scriptContent, rules, settings);
410-
return scriptFileMarkers.Select(ScriptFileMarker.FromDiagnosticRecord).ToArray();
405+
return scriptFileMarkers.Select(ScriptFileMarker.FromDiagnosticRecord).ToList();
411406
}
412407
else
413408
{
414409
// Return an empty marker list
415-
return s_emptyScriptMarkerResult;
410+
return new List<ScriptFileMarker>();
416411
}
417412
}
418413

@@ -514,7 +509,9 @@ private async Task<PSObject[]> GetDiagnosticRecordsAsync<TSettings>(
514509
new Dictionary<string, object>
515510
{
516511
{ "ScriptDefinition", scriptContent },
517-
{ settingParameter, settingArgument }
512+
{ settingParameter, settingArgument },
513+
// We ignore ParseErrors from PSSA because we already send them when we parse the file.
514+
{ "Severity", new [] { ScriptFileMarkerLevel.Error, ScriptFileMarkerLevel.Information, ScriptFileMarkerLevel.Warning }}
518515
});
519516

520517
diagnosticRecords = result?.Output;

src/PowerShellEditorServices/Workspace/ScriptFile.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public string Contents
100100
/// Gets the list of syntax markers found by parsing this
101101
/// file's contents.
102102
/// </summary>
103-
public ScriptFileMarker[] SyntaxMarkers
103+
public List<ScriptFileMarker> DiagnosticMarkers
104104
{
105105
get;
106106
private set;
@@ -662,10 +662,10 @@ private void ParseFileContents()
662662
}
663663

664664
// Translate parse errors into syntax markers
665-
this.SyntaxMarkers =
665+
this.DiagnosticMarkers =
666666
parseErrors
667667
.Select(ScriptFileMarker.FromParseError)
668-
.ToArray();
668+
.ToList();
669669

670670
// Untitled files have no directory
671671
// Discussed in https://github.com/PowerShell/PowerShellEditorServices/pull/815.

src/PowerShellEditorServices/Workspace/ScriptFileMarker.cs

+26-35
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,22 @@ public class MarkerCorrection
3333
/// </summary>
3434
public enum ScriptFileMarkerLevel
3535
{
36-
/// <summary>
37-
/// The marker represents an informational message.
38-
/// </summary>
39-
Information = 0,
40-
41-
/// <summary>
42-
/// The marker represents a warning message.
43-
/// </summary>
44-
Warning,
45-
46-
/// <summary>
47-
/// The marker represents an error message.
48-
/// </summary>
49-
Error
36+
/// <summary>
37+
        /// Information: This warning is trivial, but may be useful. They are recommended by PowerShell best practice.
38+
        /// </summary>
39+
        Information = 0,
40+
        /// <summary>
41+
        /// WARNING: This warning may cause a problem or does not follow PowerShell's recommended guidelines.
42+
        /// </summary>
43+
        Warning = 1,
44+
        /// <summary>
45+
        /// ERROR: This warning is likely to cause a problem or does not follow PowerShell's required guidelines.
46+
        /// </summary>
47+
        Error = 2,
48+
        /// <summary>
49+
        /// ERROR: This diagnostic is caused by an actual parsing error, and is generated only by the engine.
50+
        /// </summary>
51+
        ParseError = 3
5052
};
5153

5254
/// <summary>
@@ -62,7 +64,7 @@ public class ScriptFileMarker
6264
/// Gets or sets the marker's message string.
6365
/// </summary>
6466
public string Message { get; set; }
65-
67+
6668
/// <summary>
6769
/// Gets or sets the ruleName associated with this marker.
6870
/// </summary>
@@ -162,36 +164,25 @@ internal static ScriptFileMarker FromDiagnosticRecord(PSObject psObject)
162164
};
163165
}
164166

167+
string severity = diagnosticRecord.Severity.ToString();
168+
if (!Enum.TryParse(severity, out ScriptFileMarkerLevel level))
169+
{
170+
throw new ArgumentException(
171+
$"The provided DiagnosticSeverity value '{severity}' is unknown.",
172+
"diagnosticSeverity");
173+
}
174+
165175
return new ScriptFileMarker
166176
{
167177
Message = $"{diagnosticRecord.Message as string}",
168178
RuleName = $"{diagnosticRecord.RuleName as string}",
169-
Level = GetMarkerLevelFromDiagnosticSeverity((diagnosticRecord.Severity as Enum).ToString()),
179+
Level = level,
170180
ScriptRegion = ScriptRegion.Create(diagnosticRecord.Extent as IScriptExtent),
171181
Correction = correction,
172182
Source = "PSScriptAnalyzer"
173183
};
174184
}
175185

176-
private static ScriptFileMarkerLevel GetMarkerLevelFromDiagnosticSeverity(
177-
string diagnosticSeverity)
178-
{
179-
switch (diagnosticSeverity)
180-
{
181-
case "Information":
182-
return ScriptFileMarkerLevel.Information;
183-
case "Warning":
184-
return ScriptFileMarkerLevel.Warning;
185-
case "Error":
186-
return ScriptFileMarkerLevel.Error;
187-
default:
188-
throw new ArgumentException(
189-
string.Format(
190-
"The provided DiagnosticSeverity value '{0}' is unknown.",
191-
diagnosticSeverity),
192-
"diagnosticSeverity");
193-
}
194-
}
195186
#endregion
196187
}
197188
}

test/PowerShellEditorServices.Test/Session/ScriptFileTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ public void PropertiesInitializedCorrectlyForFile()
548548
Assert.True(scriptFile.IsAnalysisEnabled);
549549
Assert.False(scriptFile.IsInMemory);
550550
Assert.Empty(scriptFile.ReferencedFiles);
551-
Assert.Empty(scriptFile.SyntaxMarkers);
551+
Assert.Empty(scriptFile.DiagnosticMarkers);
552552
Assert.Single(scriptFile.ScriptTokens);
553553
Assert.Single(scriptFile.FileLines);
554554
}
@@ -574,7 +574,7 @@ public void PropertiesInitializedCorrectlyForUntitled()
574574
Assert.True(scriptFile.IsAnalysisEnabled);
575575
Assert.True(scriptFile.IsInMemory);
576576
Assert.Empty(scriptFile.ReferencedFiles);
577-
Assert.Empty(scriptFile.SyntaxMarkers);
577+
Assert.Empty(scriptFile.DiagnosticMarkers);
578578
Assert.Equal(10, scriptFile.ScriptTokens.Length);
579579
Assert.Equal(3, scriptFile.FileLines.Count);
580580
}

0 commit comments

Comments
 (0)