我正在编写一个类生成器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);
}
}
- 1 回答
- 0 关注
- 183 浏览
添加回答
举报
0/150
提交
取消