Roslyn Analyzer 分析命名空间
Roslyn Analyzer analyze Namespaces
我们有一些准则,我们希望如何使用我们的命名空间,并且对它们也有访问限制。因为有时开发人员会做错,所以我们需要分析这些规则。目前我们正在用 nDepend 做这件事,效果很好。但是,有人必须监督这个过程,找到违反这些规则的人并强迫他修复它,这个过程非常耗时。因此,在开发过程中或至少在构建当前更改之后立即得到通知会非常好。这应该是 roslyn 分析器的工作。
在过去的 3 个小时里,我已经对 roslyn 进行了自我介绍,但我对功能列表及其工作方式有点不知所措。也许你可以给我一个提示,我怎样才能实现我想要的。
我们讨论的是超过 100 万行代码和近 35000 种类型的解决方案。所以性能确实很重要。
我想做的事情:
- 获取当前class
- 获取当前class
的命名空间
- 获取所有使用过的类型及其全名
如果我能做到这一点,剩下的就相对容易了。我玩过它,也许我需要打开的 class 和编译的当前项目。但是打开这个非常耗时,因此性能会很差。
Roslyn 分析器可以注册一堆不同的代码操作,例如。在 "whole file" 级别,方法、每个语法节点或符号。根据您确切要分析的内容,其中任何一个都可能适用于您。特别是,正如您所指出的,您很关心性能。请参阅 AnalysisContext.Register*Action()
方法,可能 "hooks" 您可以添加。
得到你想要的东西:
1 获取当前class
基本上,对于其中任何一个,您应该能够获得当前的 class(如果注册语法节点或符号操作),或所有声明的 classes(例如,通过注册编译操作或语法树操作)。但最简单的选择是为 class 节点注册一个语法节点分析,你可以这样做:
context.RegisterSyntaxNodeAction(AnalyzeClassNode, SyntaxKind.ClassDeclaration);
其中AnalyzeClassNode
是分析class声明的动作。这将接收一个额外的上下文(SyntaxNodeAnalysisContext
),其中包含 class 声明语法节点。
2 获取当前class
的命名空间
为此,您需要语义模型。假设您使用了 RegisterSyntaxNodeAction
方法,并声明了一个方法 AnalyzeClassNode
,那么在正文中,您可以这样做:
var classNode = context.Node;
var model = context.SemanticModel;
var classSymbol = model.GetDeclaredSymbol(classNode);
你得到命名空间符号:
var @namespace = classSymbol.ContainingNamespace;
并且 .MetadataName
将为您提供字符串形式的命名空间。
3 获取所有使用过的类型及其全名
这要复杂得多,而且实际上取决于您要在此实现的目标。真正达到 "all dependent types, or imports" 之类的目标。您应该遍历整个 class 节点,获取每个有用节点的符号(我不知道这会带来什么),并检查它的命名空间或完整的元数据名称。
或许,您可以详细说明一下,看看这是否是正确的方法。
顺便说一句,请查看 "Learn Roslyn Now",这是一个包含大量 Roslyn 教程的网站。具体来说,您需要查看第 3 部分(语法节点)、第 7 部分(符号)和第 10 部分(分析器介绍)。
我们有一些准则,我们希望如何使用我们的命名空间,并且对它们也有访问限制。因为有时开发人员会做错,所以我们需要分析这些规则。目前我们正在用 nDepend 做这件事,效果很好。但是,有人必须监督这个过程,找到违反这些规则的人并强迫他修复它,这个过程非常耗时。因此,在开发过程中或至少在构建当前更改之后立即得到通知会非常好。这应该是 roslyn 分析器的工作。
在过去的 3 个小时里,我已经对 roslyn 进行了自我介绍,但我对功能列表及其工作方式有点不知所措。也许你可以给我一个提示,我怎样才能实现我想要的。
我们讨论的是超过 100 万行代码和近 35000 种类型的解决方案。所以性能确实很重要。
我想做的事情:
- 获取当前class
- 获取当前class 的命名空间
- 获取所有使用过的类型及其全名
如果我能做到这一点,剩下的就相对容易了。我玩过它,也许我需要打开的 class 和编译的当前项目。但是打开这个非常耗时,因此性能会很差。
Roslyn 分析器可以注册一堆不同的代码操作,例如。在 "whole file" 级别,方法、每个语法节点或符号。根据您确切要分析的内容,其中任何一个都可能适用于您。特别是,正如您所指出的,您很关心性能。请参阅 AnalysisContext.Register*Action()
方法,可能 "hooks" 您可以添加。
得到你想要的东西:
1 获取当前class
基本上,对于其中任何一个,您应该能够获得当前的 class(如果注册语法节点或符号操作),或所有声明的 classes(例如,通过注册编译操作或语法树操作)。但最简单的选择是为 class 节点注册一个语法节点分析,你可以这样做:
context.RegisterSyntaxNodeAction(AnalyzeClassNode, SyntaxKind.ClassDeclaration);
其中AnalyzeClassNode
是分析class声明的动作。这将接收一个额外的上下文(SyntaxNodeAnalysisContext
),其中包含 class 声明语法节点。
2 获取当前class
的命名空间为此,您需要语义模型。假设您使用了 RegisterSyntaxNodeAction
方法,并声明了一个方法 AnalyzeClassNode
,那么在正文中,您可以这样做:
var classNode = context.Node;
var model = context.SemanticModel;
var classSymbol = model.GetDeclaredSymbol(classNode);
你得到命名空间符号:
var @namespace = classSymbol.ContainingNamespace;
并且 .MetadataName
将为您提供字符串形式的命名空间。
3 获取所有使用过的类型及其全名
这要复杂得多,而且实际上取决于您要在此实现的目标。真正达到 "all dependent types, or imports" 之类的目标。您应该遍历整个 class 节点,获取每个有用节点的符号(我不知道这会带来什么),并检查它的命名空间或完整的元数据名称。
或许,您可以详细说明一下,看看这是否是正确的方法。
顺便说一句,请查看 "Learn Roslyn Now",这是一个包含大量 Roslyn 教程的网站。具体来说,您需要查看第 3 部分(语法节点)、第 7 部分(符号)和第 10 部分(分析器介绍)。