为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
江户川乱折腾 2021-04-29 13:08:35
我正在编写一个类生成器Microsoft.CodeAnalysis,它使用一个现有类(即ITypeSymbol实例)作为输入,并应该生成一个NamespaceDeclarationSyntax包含的新类ClassDeclarationSyntax。本质上,生成的类是源类的外观。就是说,在生成的代码中需要相同的usings集和相同的namespace名称,以使生成的Facade类正确编译。我正在使用自定义CSharpSyntaxRewriter后代来处理源代码。从该VisitClassDeclaration方法调用外观生成逻辑。我SemanticModel.GetDeclaredSymbol用来检索对应的ITypeSymbol。为了构建所有适用的usings的列表,并构建完全限定的名称空间名称,我想执行以下操作:// collect usings and construct namespace nameSyntaxList<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根节点?
查看完整描述

1 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

使用Ancestors或AncestorsAndSelf属性检索所有父级,以备份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);

    }

}


查看完整回答
反对 回复 2021-05-08
  • 1 回答
  • 0 关注
  • 159 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信