Roslyn:如何获取与标识符关联的 ITypeSymbol?
Roslyn: How to get the ITypeSymbol associated with an identifier?
我正在尝试编写一个 Roslyn 分析器来检测在数组上调用 Enumerable.Count()
的用法。这是我的分析器中的相关代码:
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeInvocationExpression, SyntaxKind.InvocationExpression);
}
private static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
{
var invocation = (InvocationExpressionSyntax)context.Node;
var memberAccess = invocation.Expression as MemberAccessExpressionSyntax;
if (!memberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression))
{
return;
}
Debug.Assert(memberAccess != null);
var ident = memberAccess.Name.Identifier;
// Check whether the method is Count() and there is no parameter list before we try to use the Symbol APIs.
if (ident.ToString() != nameof(Enumerable.Count))
{
return;
}
var arguments = invocation.ArgumentList.Arguments;
if (arguments.Count > 0)
{
return;
}
// Make sure that the subject is an array.
var subject = memberAccess.Expression;
var subjectSymbol = context.SemanticModel.GetSymbolInfo(subject).Symbol;
if (subjectSymbol == null)
{
return;
}
// ???
}
我无法确定调用 Count()
的对象是否是一个数组。我扫描了一下 API,我看到有一个 ILocalSymbol
和 Type
属性,还有一个 IFieldSymbol
和 Type
属性 这可能都会让你得到对象的类型。但是,我不知道我正在分析的对象是否是方法 call/etc 的 local/field/result,所以我希望 IFieldSymbol
和 ILocalSymbol
例如共享一些通用的基本接口,比如 IVariableSymbol
,它为您提供 Type
,而无需知道变量可能来自的所有可能位置。但是,这两个接口似乎都直接派生自 ISymbol
.
做这样的事情是最好的解决方案吗?
internal static class SymbolUtilities
{
public static ITypeSymbol GetType(ISymbol symbol)
{
if (symbol is IFieldSymbol)
{
return ((IFieldSymbol)symbol).Type;
}
if (symbol is ILocalSymbol)
{
return ((ILocalSymbol)symbol).Type;
}
...
}
}
您可以使用 SemanticModel
class 的方法 GetTypeInfo
获取有关类型的信息:
ITypeSymbol subjectType = context.SemanticModel.GetTypeInfo(subject).Type;
您将在文章中找到更多详细信息
我正在尝试编写一个 Roslyn 分析器来检测在数组上调用 Enumerable.Count()
的用法。这是我的分析器中的相关代码:
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeInvocationExpression, SyntaxKind.InvocationExpression);
}
private static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
{
var invocation = (InvocationExpressionSyntax)context.Node;
var memberAccess = invocation.Expression as MemberAccessExpressionSyntax;
if (!memberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression))
{
return;
}
Debug.Assert(memberAccess != null);
var ident = memberAccess.Name.Identifier;
// Check whether the method is Count() and there is no parameter list before we try to use the Symbol APIs.
if (ident.ToString() != nameof(Enumerable.Count))
{
return;
}
var arguments = invocation.ArgumentList.Arguments;
if (arguments.Count > 0)
{
return;
}
// Make sure that the subject is an array.
var subject = memberAccess.Expression;
var subjectSymbol = context.SemanticModel.GetSymbolInfo(subject).Symbol;
if (subjectSymbol == null)
{
return;
}
// ???
}
我无法确定调用 Count()
的对象是否是一个数组。我扫描了一下 API,我看到有一个 ILocalSymbol
和 Type
属性,还有一个 IFieldSymbol
和 Type
属性 这可能都会让你得到对象的类型。但是,我不知道我正在分析的对象是否是方法 call/etc 的 local/field/result,所以我希望 IFieldSymbol
和 ILocalSymbol
例如共享一些通用的基本接口,比如 IVariableSymbol
,它为您提供 Type
,而无需知道变量可能来自的所有可能位置。但是,这两个接口似乎都直接派生自 ISymbol
.
做这样的事情是最好的解决方案吗?
internal static class SymbolUtilities
{
public static ITypeSymbol GetType(ISymbol symbol)
{
if (symbol is IFieldSymbol)
{
return ((IFieldSymbol)symbol).Type;
}
if (symbol is ILocalSymbol)
{
return ((ILocalSymbol)symbol).Type;
}
...
}
}
您可以使用 SemanticModel
class 的方法 GetTypeInfo
获取有关类型的信息:
ITypeSymbol subjectType = context.SemanticModel.GetTypeInfo(subject).Type;
您将在文章中找到更多详细信息