首页 > 解决方案 > 如何在 C# 中查找对枚举值的 .ToString() 调用

问题描述

我正在尝试使用 Roslyn 分析器来查找使用.ToString()枚举值的所有实例,以便我可以建议一个代码修复来改用该nameof()表达式。我该怎么做呢?对于字符串插值场景,我已经以一种过于复杂的方式艰难地完成了它,但对于下面列出的其他场景,我仍然需要这样做。

public void PrintStuffOut() {
    //all below lines should flag to suggest using nameof(Foo.Bar)
    Console.WriteLine(Foo.Bar);
    Console.WriteLine(Foo.Bar.ToString());
    Console.WriteLine($"Your enum is {Foo.Bar}");
    Console.WriteLine($"Your enum is {Foo.Bar.ToString()}");
    Console.WriteLine("Your enum is " + Foo.Bar);
    Console.WriteLine("Your enum is " + Foo.Bar.ToString());
}

public enum Foo {
    Bar
}

这是我到目前为止所拥有的。这行得通,但肯定可以做得更好


public override void Initialize(AnalysisContext context) {
    context.EnableConcurrentExecution();
    context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

    context.RegisterSyntaxNodeAction(AnalyzeInterpolatedString, SyntaxKind.InterpolatedStringExpression);
}

private void AnalyzeInterpolatedString(SyntaxNodeAnalysisContext ctx) {
    var interpolationSyntax = (InterpolatedStringExpressionSyntax)ctx.Node;
    foreach (var interpolatedChunk in interpolationSyntax.Contents.OfType<InterpolationSyntax>()) {
        var expTypeInfo = ctx.SemanticModel.GetTypeInfo(interpolatedChunk.Expression);
        //this if covers the case of when there is an explicit .ToString() on the enum's value in the string interpolation. Feels super hacky.
        if (expTypeInfo.Type != null && expTypeInfo.Type.SpecialType == SpecialType.System_String) {
            var childrenExpressions = interpolatedChunk.Expression.ChildNodes().OfType<MemberAccessExpressionSyntax>();
            foreach (var childExpression in childrenExpressions) {
                var childExpTypeInfo = ctx.SemanticModel.GetTypeInfo(childExpression.Expression);

                if (childExpTypeInfo.Type != null && childExpTypeInfo.Type.TypeKind == TypeKind.Enum) {
                    //super hacky way to get the enum name and value. I need to report back EnumName and Value in the example of EnumName.Value.ToString()
                    ctx.ReportDiagnostic(Diagnostic.Create(Descriptors.UseNameOfForEnum, interpolationSyntax.GetLocation(), interpolatedChunk.Expression.ToString().Split('.').Take(2).ToArray()));
                }
            }
        }
        //the else if here covers when there is no explicit .ToString() in the interpolated string
        else if (expTypeInfo.Type != null && expTypeInfo.Type.TypeKind == TypeKind.Enum) {
            //super hacky way to get the enum name and value. I need to report back EnumName and Value in the example of EnumName.Value.ToString()
            ctx.ReportDiagnostic(Diagnostic.Create(Descriptors.UseNameOfForEnum, interpolationSyntax.GetLocation(), interpolatedChunk.Expression.ToString().Split('.')));
        }
    }
}

我觉得我应该能够通过在 上注册一个动作来做一些事情SyntaxKind.InvocationExpression,检查被调用的方法是.ToString(),并且它是在枚举值上被调用的。有可能这样做吗?这会捕捉到上面我没有明确使用的场景.ToString()吗?如果没有,实现这一目标的最佳方法是什么?

标签: c#roslynroslyn-code-analysismicrosoft.codeanalysis

解决方案


推荐阅读