分析器可以验证命名空间是否与文件位置正确匹配

Oll*_*lly 6 c# roslyn

通常在C#解决方案中命名命名空间,使它们匹配项目的默认命名空间以及包含文件的任何子目录的名称.

例如,一个被调用的文件Haddock.cs位于一个被调用的目录中Fish,而默认的命名空间(在VS的项目属性的第一个选项卡中)Lakes则该文件应包含类似的内容

namespace Lakes.Fish
{
    public class Haddock
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

了StyleCop分析仪项目包含一个很好的规则,用于验证类名的文件名匹配.

有没有办法可以编写一个规则来验证命名空间名称是否正确?

Joh*_*ner 5

你可以SyntaxTreeAction使用Tree.FilePathoff 来访问文件路径SyntaxTreeContext.

获得路径后,您可以解析该路径并将其与NamesSpaceDeclarationSyntax树中节点的所有名称的名称进行比较.

不幸的是,我认为目前没有办法获得项目的默认命名空间.

这是一个快速的样本,我把它放在一起,到目前为止它做到了.处理/比较命名空间的路径是基本的,可能有更好的方法,但这应该让你开始.

public override void Initialize(AnalysisContext context)
{
    context.RegisterCompilationStartAction((compilationSyntax) =>
    {
        compilationSyntax.RegisterSyntaxTreeAction((syntaxTreeContext) =>
        {
            var semModel = compilationSyntax.Compilation.GetSemanticModel(syntaxTreeContext.Tree);
            var filePath = syntaxTreeContext.Tree.FilePath;

            if (filePath == null)
                return;

            var namespaceNodes = syntaxTreeContext.Tree.GetRoot().DescendantNodes().OfType<NamespaceDeclarationSyntax>();
            var parentDirectory = System.IO.Path.GetDirectoryName(filePath);

            // This will only work on windows and is not very robust.
            var parentDirectoryWithDots = parentDirectory.Replace("\\", ".").ToLower();

            foreach (var ns in namespaceNodes)
            {
                var symbolInfo = semModel.GetDeclaredSymbol(ns) as INamespaceSymbol;
                var name = symbolInfo.ToDisplayString();

                if (!parentDirectoryWithDots.EndsWith(name.ToLower().Trim()))
                {
                    syntaxTreeContext.ReportDiagnostic(Diagnostic.Create(
                       Rule, ns.Name.GetLocation(), parentDirectoryWithDots));
                }
            }
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!如果无法获取默认命名空间,这用途有限,因此我添加了以下内容:https://github.com/dotnet/roslyn/issues/5252。让我们希望它去某个地方! (2认同)