繁体   English   中英

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

[英]Collect usings from all enclosing namespaces having an ITypeSymbol

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

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

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

// 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)甚至如何检索包含给定ClassDeclarationSyntax的一个确切的NamespaceDeclarationSyntax

最后,我要构造一个新的NamespaceDeclarationSyntax如下所示:

return SyntaxFactory.NamespaceDeclaration(
    SyntaxFactory.ParseName(namespaceName), 
    SyntaxFactory.List<ExternAliasDirectiveSyntax>(), 
    allUsings, 
    SyntaxFactory.List(new[] {(MemberDeclarationSyntax) generatedClass}));

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

使用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);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM