Skip to content

Commit c49fa2a

Browse files
Correctly map SuggestedCorrection to MarkerCorrection (#1749)
With the recent fix in PR #1718, PSES processes now all Correction objects from PSSA but the message specifically was just taken from the last correction here. I did not notice this at first because I thought I had to tweak my rule first to emit two different messages until I realized it was another bug in PSES. Related: PowerShell/PSScriptAnalyzer#1782 Co-authored-by: Andy Schwartzmeyer <[email protected]>
1 parent e555dc0 commit c49fa2a

File tree

3 files changed

+31
-41
lines changed

3 files changed

+31
-41
lines changed

src/PowerShellEditorServices/Services/Analysis/AnalysisService.cs

+7-9
Original file line numberDiff line numberDiff line change
@@ -208,22 +208,20 @@ public async Task<string> GetCommentHelpText(string functionText, string helpLoc
208208

209209
ScriptFileMarker[] analysisResults = await AnalysisEngine.AnalyzeScriptAsync(functionText, commentHelpSettings).ConfigureAwait(false);
210210

211-
if (analysisResults.Length == 0
212-
|| analysisResults[0]?.Correction?.Edits == null
213-
|| analysisResults[0].Correction.Edits.Length == 0)
211+
if (analysisResults.Length == 0 || !analysisResults[0].Corrections.Any())
214212
{
215213
return null;
216214
}
217215

218-
return analysisResults[0].Correction.Edits[0].Text;
216+
return analysisResults[0].Corrections.First().Edit.Text;
219217
}
220218

221219
/// <summary>
222220
/// Get the most recent corrections computed for a given script file.
223221
/// </summary>
224222
/// <param name="documentUri">The URI string of the file to get code actions for.</param>
225223
/// <returns>A threadsafe readonly dictionary of the code actions of the particular file.</returns>
226-
public async Task<IReadOnlyDictionary<string, MarkerCorrection>> GetMostRecentCodeActionsForFileAsync(DocumentUri uri)
224+
public async Task<IReadOnlyDictionary<string, IEnumerable<MarkerCorrection>>> GetMostRecentCodeActionsForFileAsync(DocumentUri uri)
227225
{
228226
if (!_workspaceService.TryGetFile(uri, out ScriptFile file)
229227
|| !_mostRecentCorrectionsByFile.TryGetValue(file, out CorrectionTableEntry corrections))
@@ -404,10 +402,10 @@ private void PublishScriptDiagnostics(ScriptFile scriptFile, IReadOnlyList<Scrip
404402

405403
Diagnostic diagnostic = GetDiagnosticFromMarker(marker);
406404

407-
if (marker.Correction != null)
405+
if (marker.Corrections is not null)
408406
{
409407
string diagnosticId = GetUniqueIdFromDiagnostic(diagnostic);
410-
fileCorrections.Corrections[diagnosticId] = marker.Correction;
408+
fileCorrections.Corrections[diagnosticId] = marker.Corrections;
411409
}
412410

413411
diagnostics[i] = diagnostic;
@@ -511,11 +509,11 @@ private class CorrectionTableEntry
511509

512510
public CorrectionTableEntry()
513511
{
514-
Corrections = new ConcurrentDictionary<string, MarkerCorrection>();
512+
Corrections = new ConcurrentDictionary<string, IEnumerable<MarkerCorrection>>();
515513
DiagnosticPublish = Task.CompletedTask;
516514
}
517515

518-
public ConcurrentDictionary<string, MarkerCorrection> Corrections { get; }
516+
public ConcurrentDictionary<string, IEnumerable<MarkerCorrection>> Corrections { get; }
519517

520518
public Task DiagnosticPublish { get; set; }
521519
}

src/PowerShellEditorServices/Services/TextDocument/Handlers/CodeActionHandler.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public override async Task<CommandOrCodeActionContainer> Handle(CodeActionParams
5252
return Array.Empty<CommandOrCodeAction>();
5353
}
5454

55-
IReadOnlyDictionary<string, MarkerCorrection> corrections = await _analysisService.GetMostRecentCodeActionsForFileAsync(
55+
IReadOnlyDictionary<string, IEnumerable<MarkerCorrection>> corrections = await _analysisService.GetMostRecentCodeActionsForFileAsync(
5656
request.TextDocument.Uri)
5757
.ConfigureAwait(false);
5858

@@ -75,13 +75,13 @@ public override async Task<CommandOrCodeActionContainer> Handle(CodeActionParams
7575
}
7676

7777
string diagnosticId = AnalysisService.GetUniqueIdFromDiagnostic(diagnostic);
78-
if (corrections.TryGetValue(diagnosticId, out MarkerCorrection correction))
78+
if (corrections.TryGetValue(diagnosticId, out IEnumerable<MarkerCorrection> markerCorrections))
7979
{
80-
foreach (ScriptRegion edit in correction.Edits)
80+
foreach (MarkerCorrection markerCorrection in markerCorrections)
8181
{
8282
codeActions.Add(new CodeAction
8383
{
84-
Title = correction.Name,
84+
Title = markerCorrection.Name,
8585
Kind = CodeActionKind.QuickFix,
8686
Edit = new WorkspaceEdit
8787
{
@@ -93,7 +93,7 @@ public override async Task<CommandOrCodeActionContainer> Handle(CodeActionParams
9393
{
9494
Uri = request.TextDocument.Uri
9595
},
96-
Edits = new TextEditContainer(ScriptRegion.ToTextEdit(edit))
96+
Edits = new TextEditContainer(ScriptRegion.ToTextEdit(markerCorrection.Edit))
9797
}))
9898
}
9999
});

src/PowerShellEditorServices/Services/TextDocument/ScriptFileMarker.cs

+19-27
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ public sealed class MarkerCorrection
2121
public string Name { get; set; }
2222

2323
/// <summary>
24-
/// Gets or sets the list of ScriptRegions that define the edits to be made by the correction.
24+
/// Gets or sets the ScriptRegion that define the edit to be made by the correction.
2525
/// </summary>
26-
public ScriptRegion[] Edits { get; set; }
26+
public ScriptRegion Edit { get; set; }
2727
}
2828

2929
/// <summary>
@@ -79,9 +79,9 @@ public class ScriptFileMarker
7979
public ScriptRegion ScriptRegion { get; set; }
8080

8181
/// <summary>
82-
/// Gets or sets an optional code correction that can be applied based on this marker.
82+
/// Gets or sets a optional code corrections that can be applied based on its marker.
8383
/// </summary>
84-
public MarkerCorrection Correction { get; set; }
84+
public IEnumerable<MarkerCorrection> Corrections { get; set; }
8585

8686
/// <summary>
8787
/// Gets or sets the name of the marker's source like "PowerShell"
@@ -110,7 +110,6 @@ internal static ScriptFileMarker FromParseError(
110110
internal static ScriptFileMarker FromDiagnosticRecord(PSObject psObject)
111111
{
112112
Validate.IsNotNull(nameof(psObject), psObject);
113-
MarkerCorrection correction = null;
114113

115114
// make sure psobject is of type DiagnosticRecord
116115
if (!psObject.TypeNames.Contains(
@@ -124,32 +123,25 @@ internal static ScriptFileMarker FromDiagnosticRecord(PSObject psObject)
124123
// the diagnostic record's properties directly i.e. <instance>.<propertyName>
125124
// without having to go through PSObject's Members property.
126125
dynamic diagnosticRecord = psObject;
127-
126+
List<MarkerCorrection> markerCorrections = new();
128127
if (diagnosticRecord.SuggestedCorrections != null)
129128
{
130-
List<ScriptRegion> editRegions = new();
131-
string correctionMessage = null;
132129
foreach (dynamic suggestedCorrection in diagnosticRecord.SuggestedCorrections)
133130
{
134-
editRegions.Add(
135-
new ScriptRegion(
136-
diagnosticRecord.ScriptPath,
137-
suggestedCorrection.Text,
138-
startLineNumber: suggestedCorrection.StartLineNumber,
139-
startColumnNumber: suggestedCorrection.StartColumnNumber,
140-
endLineNumber: suggestedCorrection.EndLineNumber,
141-
endColumnNumber: suggestedCorrection.EndColumnNumber,
142-
startOffset: -1,
143-
endOffset: -1));
144-
145-
correctionMessage = suggestedCorrection.Description;
131+
markerCorrections.Add(new MarkerCorrection
132+
{
133+
Name = suggestedCorrection.Description ?? diagnosticRecord.Message,
134+
Edit = new ScriptRegion(
135+
diagnosticRecord.ScriptPath,
136+
suggestedCorrection.Text,
137+
startLineNumber: suggestedCorrection.StartLineNumber,
138+
startColumnNumber: suggestedCorrection.StartColumnNumber,
139+
startOffset: -1,
140+
endLineNumber: suggestedCorrection.EndLineNumber,
141+
endColumnNumber: suggestedCorrection.EndColumnNumber,
142+
endOffset: -1),
143+
});
146144
}
147-
148-
correction = new MarkerCorrection
149-
{
150-
Name = correctionMessage ?? diagnosticRecord.Message,
151-
Edits = editRegions.ToArray()
152-
};
153145
}
154146

155147
string severity = diagnosticRecord.Severity.ToString();
@@ -166,7 +158,7 @@ internal static ScriptFileMarker FromDiagnosticRecord(PSObject psObject)
166158
RuleName = diagnosticRecord.RuleName as string ?? string.Empty,
167159
Level = level,
168160
ScriptRegion = ScriptRegion.Create(diagnosticRecord.Extent as IScriptExtent),
169-
Correction = correction,
161+
Corrections = markerCorrections,
170162
Source = "PSScriptAnalyzer"
171163
};
172164
}

0 commit comments

Comments
 (0)