File: CallAnalysis\StartsEndsWith.cs
Web Access
Project: src\src\Analyzers\Microsoft.Analyzers.Extra\Microsoft.Analyzers.Extra.csproj (Microsoft.Analyzers.Extra)
// 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.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
 
namespace Microsoft.Extensions.ExtraAnalyzers.CallAnalysis;
 
/// <summary>
/// Recommends char (instead of string) versions of String.StartsWith and String.EndsWith when possible.
/// </summary>
internal sealed class StartsEndsWith
{
    public StartsEndsWith(CallAnalyzer.Registrar reg)
    {
        var stringType = reg.Compilation.GetSpecialType(SpecialType.System_String);
        var stringCompType = reg.Compilation.GetTypeByMetadataName("System.StringComparison");
 
        var startsWith = stringType.GetMembers("StartsWith").OfType<IMethodSymbol>()
            .Where(m => SymbolEqualityComparer.Default.Equals(m.Parameters[0].Type, stringType))
            .Where(m =>
                (m.Parameters.Length == 1) ||
                (m.Parameters.Length == 2 && SymbolEqualityComparer.Default.Equals(m.Parameters[1].Type, stringCompType)));
 
        var endsWith = stringType.GetMembers("EndsWith").OfType<IMethodSymbol>()
            .Where(m => SymbolEqualityComparer.Default.Equals(m.Parameters[0].Type, stringType))
            .Where(m =>
                (m.Parameters.Length == 1) ||
                (m.Parameters.Length == 2 && SymbolEqualityComparer.Default.Equals(m.Parameters[1].Type, stringCompType)));
 
        foreach (var m in startsWith)
        {
            reg.RegisterMethod(m, Handle);
        }
 
        foreach (var m in endsWith)
        {
            reg.RegisterMethod(m, Handle);
        }
 
        static void Handle(OperationAnalysisContext context, IInvocationOperation op)
        {
            var s = op.Arguments[0].Value.ConstantValue.Value as string;
 
            if (s != null && s.Length == 1)
            {
                if (op.Arguments.Length > 1 && op.Arguments[1].Value.ConstantValue.HasValue)
                {
                    var comp = (StringComparison)op.Arguments[1].Value.ConstantValue.Value!;
                    if (comp != StringComparison.Ordinal)
                    {
                        return;
                    }
                }
 
                var diagnostic = Diagnostic.Create(DiagDescriptors.StartsEndsWith, op.Syntax.GetLocation(), op.TargetMethod.Name);
                context.ReportDiagnostic(diagnostic);
            }
        }
    }
}