我正在使用Microsoft.CodeAnalysis
编写一个类生成器,它将现有类(即ITypeSymbol
实例)作为输入,并且应该生成包含{{1}的新NamespaceDeclarationSyntax
}}。基本上,生成的类是源类的外观。话虽这么说,生成的Facade类中需要相同的ClassDeclarationSyntax
和using
名称集合才能正确编译。
我正在使用自定义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}));
节点?
答案 0 :(得分:1)
使用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);
}
}