从具有ITypeSymbol的所有封闭名称空间收集使用

我正在编写一个类生成器Microsoft.CodeAnalysis,它使用一个现有类(即ITypeSymbol实例)作为输入,并应该生成一个NamespaceDeclarationSyntax包含的新类ClassDeclarationSyntax。本质上,生成的类是源类的外观。就是说,在生成的代码中需要相同的usings集和相同的namespace名称,以使生成的Facade类正确编译。


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


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


// 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;

}

问题是(1)我看不到一种简单的方法来将语法树从给定遍历SyntaxNode到根,以及(2)甚至如何检索一个精确地NamespaceDeclarationSyntax包围给定的ClassDeclarationSyntax。


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


return SyntaxFactory.NamespaceDeclaration(

    SyntaxFactory.ParseName(namespaceName), 

    SyntaxFactory.List<ExternAliasDirectiveSyntax>(), 

    allUsings, 

    SyntaxFactory.List(new[] {(MemberDeclarationSyntax) generatedClass}));

问题:有了给定的条件后SyntaxNode,如何遍历树回到CompilationUnitSyntax根节点?


江户川乱折腾
浏览 189回答 1
1回答

暮色呼如

使用Ancestors或AncestorsAndSelf属性检索所有父级,以备份SyntaxTree。从给定SyntaxNode直到根收集所有使用的代码CompilationUnitSyntax如下所示:// collect usingsSyntaxList<UsingDirectiveSyntax> allUsings = SyntaxFactory.List<UsingDirectiveSyntax>();foreach (var syntaxRef in ClassSymbol.DeclaringSyntaxReferences){&nbsp; &nbsp; foreach (var parent in syntaxRef.GetSyntax().Ancestors(false))&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (parent is NamespaceDeclarationSyntax)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allUsings = allUsings.AddRange(((NamespaceDeclarationSyntax)parent).Usings);&nbsp; &nbsp; &nbsp; &nbsp; else if (parent is CompilationUnitSyntax)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allUsings = allUsings.AddRange(((CompilationUnitSyntax)parent).Usings);&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP