【问题标题】:Roslyn analyser: Nullable annotations in LinqRoslyn 分析器:Linq 中的可空注释
【发布时间】:2020-04-07 13:08:56
【问题描述】:

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

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

我的编码已经走到了这一步:

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

我已经阅读了很多关于在这个阶段你可以做什么的信息,这是一个信息过载。任何可以给我更多方向的文章、代码 sn-ps 或建议将不胜感激!

【问题讨论】:

  • 对目的感到困惑。 FirstOrDefault()boolint 等值类型返回非空值。除非我弄错了,否则它只为引用类型返回 null。您指的是可为空的引用类型吗?
  • 假设您在谈论 NRT(不清楚):请注意,这将在 .NET 5 中工作——FirstOrDefault 将被正确注释。在此之前,您可以使用 ReferenceAssemblyAnnotator 获取 BCL 的最新注释
  • 也许您可以添加一些代码,您的分析器会使用这些代码?目前尚不清楚您是指 NRT(您确实将其标记为 C# 8)还是 Nullable&lt;T&gt;
  • 抱歉,是的,我指的是 NRT。我将更新问题以明确这一点。
  • 您的代码以System.Nullable1 为条件,与NRT 无关。这让我很困惑。

标签: linq generics roslyn c#-8.0 nullable-reference-types


【解决方案1】:

最后,我们最终编写了自己的分析器作为临时解决方案,直到我们可以迁移到 .Net 5。我们提出的最基本的实现是以下代码:

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

希望这可以帮助那些在不得不开发类似的东西时可能只是在寻找一个好的起点的人。

【讨论】:

    猜你喜欢
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    • 2017-03-04
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 2019-03-22
    • 2022-10-24
    相关资源
    最近更新 更多