我是Roslyn的新手,我必须编写一个分析器,该分析器在使用Linq时将有助于改善可为空的注释。目标是强制将.XYZOrDefault()的所有用法存储在可为空的类型变量/属性/方法签名中。例如:如果我们使用“ var x = SomeKindOfList.FirstOrDefault()”,则“ x”需要标记为可为空。我们将使用C#8,因此我指的是NRT。实现此目的的方法是:
我的编码已经到此为止:
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
Compilation compilation = context.Compilation;
var localDeclarations = context.Node.DescendantNodes().OfType<VariableDeclarationSyntax>();
foreach (var declaration in localDeclarations)
{
// Find implicitly typed variable declarations.
if (declaration.Type.IsVar)
{
foreach (var variable in declaration.Variables)
{
var variableSymbol = ((ILocalSymbol)context.SemanticModel.GetDeclaredSymbol(variable)).Type;
var invocationSymbol = context.SemanticModel.GetOperation(variable.Initializer.Value).Type;
if (!((INamedTypeSymbol)variableSymbol).IsGenericType || declaration.Type.IsVar)
{
// For all such symbols, produce a diagnostic.
var diagnostic = Diagnostic.Create(Rule, variableSymbol.Locations[0], variableSymbol.Name);
context.ReportDiagnostic(diagnostic);
}
}
}
}
我已经读到了很多关于您可以在此阶段执行的操作,这是信息过载。任何可以给我更多指导的文章,代码段或建议,都将受到高度赞赏!
最后,我们最终编写了自己的分析器作为临时解决方案,直到可以迁移到.Net5。我们想到的最基本的实现是以下代码:
private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var localDeclarations = context.Node.DescendantNodes().OfType<VariableDeclarationSyntax>();
foreach (var declaration in localDeclarations)
{
foreach (var variable in declaration.Variables)
{
ITypeSymbol? variableSymbol = ((ILocalSymbol)context.SemanticModel.GetDeclaredSymbol(variable)).Type;
IOperation? invocationOperationInfo = context.SemanticModel.GetOperation(variable.Initializer.Value);
if (invocationOperationInfo is IInvocationOperation op)
{
if (op.TargetMethod.IsGenericMethod)
{
if (!((INamedTypeSymbol)variableSymbol).IsGenericType || declaration.Type.IsVar)
{
// For all such symbols, produce a diagnostic.
var diagnostic = Diagnostic.Create(Rule, variable.GetLocation());
context.ReportDiagnostic(diagnostic);
}
}
}
}
}
}
希望这可以帮助其他可能只是在开发类似内容时寻找良好起点的人。