从具有ITypeSymbol

时间:2018-04-22 21:16:46

标签: c# roslyn

我正在使用Microsoft.CodeAnalysis编写一个类生成器,它将现有类(即ITypeSymbol实例)作为输入,并且应该生成包含{{1}的新NamespaceDeclarationSyntax }}。基本上,生成的类是源类的外观。话虽这么说,生成的Facade类中需要相同的ClassDeclarationSyntaxusing名称集合才能正确编译。

我正在使用自定义namespace后代处理源代码。从CSharpSyntaxRewriter方法调用外观生成逻辑。我使用VisitClassDeclaration来检索相应的SemanticModel.GetDeclaredSymbol

为了构建所有适用的ITypeSymbol的列表,并构建完全限定的命名空间名称,我想执行以下操作:

using

问题是(1)我看不到一种简单的方法来将语法树从给定的// collect usings and construct namespace name SyntaxList<UsingDirectiveSyntax> allUsings = SyntaxFactory.List<UsingDirectiveSyntax>(); var nmspace = ClassSymbol.ContainingNamespace; string namespaceName = null; while (nmspace != null) { if (!nmspace.IsGlobalNamespace) { if (namespaceName == null) namespaceName = nmspace.Name; else namespaceName = nmspace.Name + "." + namespaceName; } // here nmspace.DeclaringSyntaxReferences contains all occurrences in the given assembly var syntax = nmspace.DeclaringSyntaxReferences.First().GetSyntax(); if (syntax is NamespaceDeclarationSyntax) allUsings = allUsings.AddRange(((NamespaceDeclarationSyntax) syntax).Usings); else if (syntax is CompilationUnitSyntax) allUsings = allUsings.AddRange(((CompilationUnitSyntax) syntax).Usings); nmspace = nmspace.ContainingNamespace; } 遍历回根,以及(2)甚至如何检索一个精确的{{1}封闭给定的SyntaxNode

最后,我想像这样构建一个新的NamespaceDeclarationSyntax

ClassDeclarationSyntax

问题:如果有任何给定NamespaceDeclarationSyntax,如何将树遍历回根return SyntaxFactory.NamespaceDeclaration( SyntaxFactory.ParseName(namespaceName), SyntaxFactory.List<ExternAliasDirectiveSyntax>(), allUsings, SyntaxFactory.List(new[] {(MemberDeclarationSyntax) generatedClass})); 节点?

1 个答案:

答案 0 :(得分:1)

使用AncestorsAncestorsAndSelf属性检索所有父级备份SyntaxTree。

从给定SyntaxNode到根CompilationUnitSyntax收集所有使用的代码如下所示:

// collect usings
SyntaxList<UsingDirectiveSyntax> allUsings = SyntaxFactory.List<UsingDirectiveSyntax>();
foreach (var syntaxRef in ClassSymbol.DeclaringSyntaxReferences)
{
    foreach (var parent in syntaxRef.GetSyntax().Ancestors(false))
    {
        if (parent is NamespaceDeclarationSyntax)
            allUsings = allUsings.AddRange(((NamespaceDeclarationSyntax)parent).Usings);
        else if (parent is CompilationUnitSyntax)
            allUsings = allUsings.AddRange(((CompilationUnitSyntax)parent).Usings);
    }
}