[英]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
节点?
使用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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.