Roslyn分析器:Linq中的可空注释

问题描述 投票:0回答:1

我是Roslyn的新手,我必须编写一个分析器,该分析器在使用Linq时将有助于改善可为空的注释。目标是强制将.XYZOrDefault()的所有用法存储在可为空的类型变量/属性/方法签名中。例如:如果我们使用“ var x = SomeKindOfList.FirstOrDefault()”,则“ x”需要标记为可为空。我们将使用C#8,因此我指的是NRT。实现此目的的方法是:

  1. 确定是否在变量中使用泛型类型或方法声明
  2. 使用语义模型确定左手是否表达式类型的一侧是可空类型
  3. 如果表达式的左侧不是可为null的类型,请产生一个诊断

我的编码已经到此为止:

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);
                    }
                }
            }
        }

我已经读到了很多关于您可以在此阶段执行的操作,这是信息过载。任何可以给我更多指导的文章,代码段或建议,都将受到高度赞赏!

linq generics roslyn c#-8.0 nullable-reference-types
1个回答
0
投票

最后,我们最终编写了自己的分析器作为临时解决方案,直到可以迁移到.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);
                        }
                    }
                }
            }
        }
    }

希望这可以帮助其他可能只是在开发类似内容时寻找良好起点的人。

© www.soinside.com 2019 - 2024. All rights reserved.