我创建一个SyntaxRewriter,如果类继承某种类型,则将类标记为partial,将方法标记为virtual
为了做到这一点,我从重写器内部的语义模型中查找SymbolInfo,我遇到的问题是,一旦我修改了syntaxtree以使类成为局部,我已经使SemanticModel无效并且不能用它来获取方法的SymbolInfo。
下面是重写器的一个粗略的例子,.InheritsFrom< T>()是一种扩展方法,只是遍历继承以查找特定类型的用法,我只是将IDisposable作为一个例子,但它并不是真正重要的类型。 .WithPartialModifier()只是一个将partial添加到类syntaxnode修饰符的扩展方法。
我可能需要切换我的方法或使用新的syntaxtree更新编译,但我不确定如何继续。
public class RewriterPartial : CSharpSyntaxRewriter
{
private readonly CSharpCompilation _compiler;
public RewriterPartial(CSharpCompilation compiler)
{
this._compiler = compiler;
}
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
{
var symbol = _compiler.GetSemanticModel(node.SyntaxTree).GetDeclaredSymbol(node);
if (symbol.InheritsFrom<System.IDisposable>())
{
if (!node.Modifiers.Any(SyntaxKind.PartialKeyword))
{
node = node.WithPartialModifier();
}
}
return base.VisitClassDeclaration(node);
}
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
{
var model = _compiler.GetSemanticModel(node.SyntaxTree);
// fails above here as the node modified above
// and its SyntaxTree have no CompilationUnit
// and I need to repeat the .InheritsFrom<T> call
// to check if the method comes from a class in the syntaxtree
// that inherits from the specific type
return node;
}
}
答案 0 :(得分:3)
在修改树之前,您可以先调用base.VisitClassDeclaration(node);
来访问和修改最深的节点。
尝试以下方法:
public class RewriterPartial : CSharpSyntaxRewriter
{
private readonly CSharpCompilation _compilation;
public RewriterPartial(CSharpCompilation compilation, SemanticModel model)
{
this._compilation = compilation;
}
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
{
//Visit the deepest nodes before modifying the tree.
var newNode = (ClassDeclarationSyntax)base.VisitClassDeclaration(node);
if (!newNode.Modifiers.Any(SyntaxKind.PartialKeyword))
{
newNode = newNode.WithModifiers(
SyntaxFactory.TokenList(
SyntaxFactory.Token(SyntaxKind.PartialKeyword)));
}
return newNode;
}
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
{
var model = _compilation.GetSemanticModel(node.SyntaxTree);
var symbol = model.GetDeclaredSymbol(node);
//Do whatever you need to here
return node;
}
}