Skip to content

Commit

Permalink
Correctly map SuggestedCorrection to MarkerCorrection (#1749)
Browse files Browse the repository at this point in the history
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 <andrew@schwartzmeyer.com>
  • Loading branch information
bergmeister and andyleejordan authored Mar 31, 2022
1 parent e555dc0 commit c49fa2a
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -208,22 +208,20 @@ public async Task<string> GetCommentHelpText(string functionText, string helpLoc

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

if (analysisResults.Length == 0
|| analysisResults[0]?.Correction?.Edits == null
|| analysisResults[0].Correction.Edits.Length == 0)
if (analysisResults.Length == 0 || !analysisResults[0].Corrections.Any())
{
return null;
}

return analysisResults[0].Correction.Edits[0].Text;
return analysisResults[0].Corrections.First().Edit.Text;
}

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

Diagnostic diagnostic = GetDiagnosticFromMarker(marker);

if (marker.Correction != null)
if (marker.Corrections is not null)
{
string diagnosticId = GetUniqueIdFromDiagnostic(diagnostic);
fileCorrections.Corrections[diagnosticId] = marker.Correction;
fileCorrections.Corrections[diagnosticId] = marker.Corrections;
}

diagnostics[i] = diagnostic;
Expand Down Expand Up @@ -511,11 +509,11 @@ private class CorrectionTableEntry

public CorrectionTableEntry()
{
Corrections = new ConcurrentDictionary<string, MarkerCorrection>();
Corrections = new ConcurrentDictionary<string, IEnumerable<MarkerCorrection>>();
DiagnosticPublish = Task.CompletedTask;
}

public ConcurrentDictionary<string, MarkerCorrection> Corrections { get; }
public ConcurrentDictionary<string, IEnumerable<MarkerCorrection>> Corrections { get; }

public Task DiagnosticPublish { get; set; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public override async Task<CommandOrCodeActionContainer> Handle(CodeActionParams
return Array.Empty<CommandOrCodeAction>();
}

IReadOnlyDictionary<string, MarkerCorrection> corrections = await _analysisService.GetMostRecentCodeActionsForFileAsync(
IReadOnlyDictionary<string, IEnumerable<MarkerCorrection>> corrections = await _analysisService.GetMostRecentCodeActionsForFileAsync(
request.TextDocument.Uri)
.ConfigureAwait(false);

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

string diagnosticId = AnalysisService.GetUniqueIdFromDiagnostic(diagnostic);
if (corrections.TryGetValue(diagnosticId, out MarkerCorrection correction))
if (corrections.TryGetValue(diagnosticId, out IEnumerable<MarkerCorrection> markerCorrections))
{
foreach (ScriptRegion edit in correction.Edits)
foreach (MarkerCorrection markerCorrection in markerCorrections)
{
codeActions.Add(new CodeAction
{
Title = correction.Name,
Title = markerCorrection.Name,
Kind = CodeActionKind.QuickFix,
Edit = new WorkspaceEdit
{
Expand All @@ -93,7 +93,7 @@ public override async Task<CommandOrCodeActionContainer> Handle(CodeActionParams
{
Uri = request.TextDocument.Uri
},
Edits = new TextEditContainer(ScriptRegion.ToTextEdit(edit))
Edits = new TextEditContainer(ScriptRegion.ToTextEdit(markerCorrection.Edit))
}))
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public sealed class MarkerCorrection
public string Name { get; set; }

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

/// <summary>
Expand Down Expand Up @@ -79,9 +79,9 @@ public class ScriptFileMarker
public ScriptRegion ScriptRegion { get; set; }

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

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

// make sure psobject is of type DiagnosticRecord
if (!psObject.TypeNames.Contains(
Expand All @@ -124,32 +123,25 @@ internal static ScriptFileMarker FromDiagnosticRecord(PSObject psObject)
// the diagnostic record's properties directly i.e. <instance>.<propertyName>
// without having to go through PSObject's Members property.
dynamic diagnosticRecord = psObject;

List<MarkerCorrection> markerCorrections = new();
if (diagnosticRecord.SuggestedCorrections != null)
{
List<ScriptRegion> editRegions = new();
string correctionMessage = null;
foreach (dynamic suggestedCorrection in diagnosticRecord.SuggestedCorrections)
{
editRegions.Add(
new ScriptRegion(
diagnosticRecord.ScriptPath,
suggestedCorrection.Text,
startLineNumber: suggestedCorrection.StartLineNumber,
startColumnNumber: suggestedCorrection.StartColumnNumber,
endLineNumber: suggestedCorrection.EndLineNumber,
endColumnNumber: suggestedCorrection.EndColumnNumber,
startOffset: -1,
endOffset: -1));

correctionMessage = suggestedCorrection.Description;
markerCorrections.Add(new MarkerCorrection
{
Name = suggestedCorrection.Description ?? diagnosticRecord.Message,
Edit = new ScriptRegion(
diagnosticRecord.ScriptPath,
suggestedCorrection.Text,
startLineNumber: suggestedCorrection.StartLineNumber,
startColumnNumber: suggestedCorrection.StartColumnNumber,
startOffset: -1,
endLineNumber: suggestedCorrection.EndLineNumber,
endColumnNumber: suggestedCorrection.EndColumnNumber,
endOffset: -1),
});
}

correction = new MarkerCorrection
{
Name = correctionMessage ?? diagnosticRecord.Message,
Edits = editRegions.ToArray()
};
}

string severity = diagnosticRecord.Severity.ToString();
Expand All @@ -166,7 +158,7 @@ internal static ScriptFileMarker FromDiagnosticRecord(PSObject psObject)
RuleName = diagnosticRecord.RuleName as string ?? string.Empty,
Level = level,
ScriptRegion = ScriptRegion.Create(diagnosticRecord.Extent as IScriptExtent),
Correction = correction,
Corrections = markerCorrections,
Source = "PSScriptAnalyzer"
};
}
Expand Down

0 comments on commit c49fa2a

Please sign in to comment.