用于命名正确性的 Roslyn C# 语义分析器在构建中传递,但在特定情况下 Intellisense 中出现错误

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

我有一个自定义的 roslyn 分析器,它根据其父类中方法的某些实现细节强制执行命名规则,即

public abstract class ChildEntity : ParentEntity;

public abstract class ParentEntity
{
     protected void IsAwesome()
     {
          ...
     }
}

在这种情况下,我的分析器将创建一个诊断,类似于“ChildEntity 应该重命名为以“Awesome”开头,因为它继承自 Awesome Parent”。此规则和诊断功能正确,但在代码分析 Intellisense 和尝试构建

ChildEntity
ParentEntity
所属项目时都会产生错误。 但是,如果
ParentEntity
ChildEntity
位于不同的项目中,并且通过 PackageReference 引用,则只有 Intellisense 显示错误,但项目构建会通过。为什么
ParentEntity
的位置会影响这个?无论
ParentEntity
位于哪个项目中,我都需要它来使构建失败。

我的语义分析器检查

NamedType
符号(如
ChildEntity
),找到其父类,并从那里评估其方法(如果找到)。如果需要创建错误,它会在
ChildEntity
类位置创建错误,并且仅在那里。

起初我不明白哪些情况下构建通过/失败,但总是显示智能感知错误。我尝试强制分析器使用 .csproj 文件和 Director.build.props 中的各种道具运行,但没有产生任何不同的结果。最后,当我注意到父实体的位置是罪魁祸首后,我创建了一个小型测试项目,以查看行为是否以更简单的形式保持一致,事实确实如此。我不确定 roslyn 编译在 Intellisense 和实际构建之间是否有所不同,看起来确实如此。构建的详细输出显示针对每种情况运行 CoreCompile。其他分析器(例如 StyleCop)也针对每个案例运行。

我的分析器作为 nuget 包安装,而不是 VSIX 安装。分析器目标框架版本是 .Net Standard 2.0,我在运行相同版本的项目中使用分析器,以及 .Net Framework 4.7.2

c# .net visual-studio roslyn roslyn-code-analysis
1个回答
0
投票

Roslyn 分析器只能访问源编译中的语法树,因此我的分析器在检查外部

INamedTypeSymbol
(分析器运行的项目外部的父类)的符号时无法调用
DeclaringSyntaxReferenced
属性用于方法检查。该属性将产生 null 或空数组,因此不会抛出任何错误。由于父类符号是通过引用的程序集或项目引用作为“元数据”进入的,因此一旦将它们打包或编译到库或 DLL 中,它们就不会公开语法信息。然而,Intellisense 会在 IDE 中获取语法信息,并能够生成所需的诊断信息。

因此,我实现的解决方案是检查符号属性

IsInMetadata
IsInSource
并处理构建情况(当
IsInMetadata
为 TRUE 且
IsInSource
为 FALSE 时)以检查父类的名称它以“Awesome”开头,而不是尝试从语法上分析“IsAwesome”方法。在翻转情况下,例如对于智能感知(当
IsInMetadata
为 FALSE 并且
IsInSource
为 TRUE 时),我们确实执行语法分析,因为我们可以访问源编译中的语法树。

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