| File: Microsoft.NetCore.Analyzers\Runtime\CSharpUseOrdinalStringComparison.Fixer.cs | Web Access |
| Project: src\sdk\src\Microsoft.CodeAnalysis.NetAnalyzers\src\Microsoft.CodeAnalysis.CSharp.NetAnalyzers\Microsoft.CodeAnalysis.CSharp.NetAnalyzers.csproj (Microsoft.CodeAnalysis.CSharp.NetAnalyzers) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Composition; using System.Threading; using System.Threading.Tasks; using Analyzer.Utilities; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.NetCore.Analyzers.Runtime; namespace Microsoft.NetCore.CSharp.Analyzers.Runtime { [ExportCodeFixProvider(LanguageNames.CSharp), Shared] public class CSharpUseOrdinalStringComparisonFixer : UseOrdinalStringComparisonFixerBase { protected override bool IsInArgumentContext(SyntaxNode node) { return node.IsKind(SyntaxKind.Argument) && ((ArgumentSyntax)node).Expression.IsKind(SyntaxKind.SimpleMemberAccessExpression); } protected override Task<Document> FixArgumentAsync(Document document, SyntaxGenerator generator, SyntaxNode root, SyntaxNode argument) { if (((ArgumentSyntax)argument)?.Expression is MemberAccessExpressionSyntax memberAccess) { // preserve the "IgnoreCase" suffix if present bool isIgnoreCase = memberAccess.Name.GetText().ToString().EndsWith(UseOrdinalStringComparisonAnalyzer.IgnoreCaseText, StringComparison.Ordinal); string newOrdinalText = isIgnoreCase ? UseOrdinalStringComparisonAnalyzer.OrdinalIgnoreCaseText : UseOrdinalStringComparisonAnalyzer.OrdinalText; SyntaxNode newIdentifier = generator.IdentifierName(newOrdinalText); MemberAccessExpressionSyntax newMemberAccess = memberAccess.WithName((SimpleNameSyntax)newIdentifier).WithAdditionalAnnotations(Formatter.Annotation); SyntaxNode newRoot = root.ReplaceNode(memberAccess, newMemberAccess); return Task.FromResult(document.WithSyntaxRoot(newRoot)); } return Task.FromResult(document); } protected override bool IsInIdentifierNameContext(SyntaxNode node) { return node.IsKind(SyntaxKind.IdentifierName) && node?.Parent?.FirstAncestorOrSelf<InvocationExpressionSyntax>() != null; } protected override async Task<Document> FixIdentifierNameAsync(Document document, SyntaxGenerator generator, SyntaxNode root, SyntaxNode identifier, CancellationToken cancellationToken) { if (identifier?.Parent?.FirstAncestorOrSelf<InvocationExpressionSyntax>() is InvocationExpressionSyntax invokeParent) { SemanticModel model = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.GetSymbolInfo((IdentifierNameSyntax)identifier!, cancellationToken).Symbol is IMethodSymbol methodSymbol && CanAddStringComparison(methodSymbol, model)) { // append a new StringComparison.Ordinal argument SyntaxNode newArg = generator.Argument(CreateOrdinalMemberAccess(generator, model)) .WithAdditionalAnnotations(Formatter.Annotation); InvocationExpressionSyntax newInvoke = invokeParent.AddArgumentListArguments((ArgumentSyntax)newArg).WithAdditionalAnnotations(Formatter.Annotation); SyntaxNode newRoot = root.ReplaceNode(invokeParent, newInvoke); return document.WithSyntaxRoot(newRoot); } } return document; } } }