Skip to content

Commit

Permalink
Merge pull request #2853 from pdelvo/SA1134NonDeterminism
Browse files Browse the repository at this point in the history
Fix that SA1134 Fix All maybe non-deterministic
  • Loading branch information
sharwell committed Dec 19, 2023
2 parents 69d477f + 5431f37 commit d91d674
Showing 1 changed file with 39 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace StyleCop.Analyzers.ReadabilityRules
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using StyleCop.Analyzers.Helpers;
using StyleCop.Analyzers.Settings.ObjectModel;

/// <summary>
/// Implements a code fix for <see cref="SA1134AttributesMustNotShareLine"/>.
Expand All @@ -31,7 +32,7 @@ internal class SA1134CodeFixProvider : CodeFixProvider
/// <inheritdoc/>
public override FixAllProvider GetFixAllProvider()
{
return CustomFixAllProviders.BatchFixer;
return FixAll.Instance;
}

/// <inheritdoc/>
Expand All @@ -58,16 +59,25 @@ private static async Task<Document> GetTransformedDocumentAsync(Document documen
{
var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, syntaxRoot.SyntaxTree, cancellationToken);
var tokensToReplace = new Dictionary<SyntaxToken, SyntaxToken>();

AddTokensToReplaceToMap(tokensToReplace, syntaxRoot, diagnostic, settings);

var newSyntaxRoot = syntaxRoot.ReplaceTokens(tokensToReplace.Keys, (original, rewritten) => tokensToReplace[original]);
var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting());

return newDocument;
}

private static void AddTokensToReplaceToMap(Dictionary<SyntaxToken, SyntaxToken> tokensToReplace, SyntaxNode syntaxRoot, Diagnostic diagnostic, StyleCopSettings settings)
{
var attributeListSyntax = (AttributeListSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan);

// use the containing type to determine the indentation level, anything else is less reliable.
var containingType = attributeListSyntax.Parent?.Parent;
var indentationSteps = (containingType != null) ? IndentationHelper.GetIndentationSteps(settings.Indentation, containingType) + 1 : 0;
var indentationTrivia = IndentationHelper.GenerateWhitespaceTrivia(settings.Indentation, indentationSteps);

var tokensToReplace = new Dictionary<SyntaxToken, SyntaxToken>();

if (diagnostic.Properties.ContainsKey(SA1134AttributesMustNotShareLine.FixWithNewLineBeforeKey))
{
var token = attributeListSyntax.OpenBracketToken;
Expand All @@ -89,11 +99,34 @@ private static async Task<Document> GetTransformedDocumentAsync(Document documen
var newLeadingTrivia = nextToken.LeadingTrivia.Insert(0, indentationTrivia);
tokensToReplace[nextToken] = nextToken.WithLeadingTrivia(newLeadingTrivia);
}
}

var newSyntaxRoot = syntaxRoot.ReplaceTokens(tokensToReplace.Keys, (original, rewritten) => tokensToReplace[original]);
var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting());
private class FixAll : DocumentBasedFixAllProvider
{
public static FixAllProvider Instance { get; } = new FixAll();

return newDocument;
protected override string CodeActionTitle => ReadabilityResources.SA1134CodeFix;

protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fixAllContext, Document document, ImmutableArray<Diagnostic> diagnostics)
{
if (diagnostics.IsEmpty)
{
return null;
}

var syntaxRoot = await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false);
var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, syntaxRoot.SyntaxTree, fixAllContext.CancellationToken);
var tokensToReplace = new Dictionary<SyntaxToken, SyntaxToken>();

foreach (var diagnostic in diagnostics)
{
AddTokensToReplaceToMap(tokensToReplace, syntaxRoot, diagnostic, settings);
}

var newSyntaxRoot = syntaxRoot.ReplaceTokens(tokensToReplace.Keys, (original, rewritten) => tokensToReplace[original]);

return newSyntaxRoot;
}
}
}
}

0 comments on commit d91d674

Please sign in to comment.