private static ImmutableArray <OperationReplacer> GetOperationReplacers(RequiredSymbols symbols) { return(ImmutableArray.Create <OperationReplacer>( new StringStringCaseReplacer(symbols), new StringStringBoolReplacer(symbols), new StringStringStringComparisonReplacer(symbols))); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { var document = context.Document; var token = context.CancellationToken; var semanticModel = await document.GetSemanticModelAsync(token).ConfigureAwait(false); _ = RequiredSymbols.TryGetSymbols(semanticModel.Compilation, out var symbols); RoslynDebug.Assert(symbols is not null); var root = await document.GetSyntaxRootAsync(token).ConfigureAwait(false); var node = root.FindNode(context.Span, getInnermostNodeForTie: true); if (semanticModel.GetOperation(node, token) is not IBinaryOperation violation) { return; } // Get the replacer that applies to the reported violation. var replacer = GetOperationReplacers(symbols).First(x => x.IsMatch(violation)); var codeAction = CodeAction.Create( Resx.UseStringEqualsOverStringCompareCodeFixTitle, CreateChangedDocument, nameof(Resx.UseStringEqualsOverStringCompareCodeFixTitle)); context.RegisterCodeFix(codeAction, context.Diagnostics); return; // Local functions async Task <Document> CreateChangedDocument(CancellationToken token) { var editor = await DocumentEditor.CreateAsync(document, token).ConfigureAwait(false); var replacementNode = replacer.CreateReplacementExpression(violation, editor.Generator); editor.ReplaceNode(violation.Syntax, replacementNode); return(editor.GetChangedDocument()); } }
protected OperationReplacer(RequiredSymbols symbols) { Symbols = symbols; }
public StringStringStringComparisonReplacer(RequiredSymbols symbols) : base(symbols) { }
public StringStringBoolReplacer(RequiredSymbols symbols) : base(symbols) { }