我正在尝试使用 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()
吗?如果没有,实现这一目标的最佳方法是什么?