从 Roslyn SyntaxRewriter 中修改后的 SyntaxNode 访问 SymbolInfo
Accessing SymbolInfo from modified SyntaxNode in Roslyn SyntaxRewriter
我正在创建一个 SyntaxRewriter,如果 class 继承自某种类型
,它会将 classes 标记为部分,将方法标记为虚拟
为此,我正在重写器中的语义模型中查找 SymbolInfo,我遇到的问题是,一旦我修改了语法树以生成 class 部分,我就已经失效SemanticModel 并且不能使用它来获取方法的 SymbolInfo。
下面是一个重写器的粗略示例,.InheritsFrom< T >() 是一种扩展方法,它只是遍历继承以查找特定类型的用法,我只是将 IDisposable 作为示例插入其中,但它不是类型是什么非常重要。
.WithPartialModifier() 再次只是一种扩展方法,用于将部分添加到 class syntaxnode 修饰符。
可能我需要改变我的方法或使用新的语法树更新编译,但我不确定如何继续。
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;
}
}
您可以先访问和修改最深的节点,方法是在修改树之前调用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;
}
}
我正在创建一个 SyntaxRewriter,如果 class 继承自某种类型
,它会将 classes 标记为部分,将方法标记为虚拟为此,我正在重写器中的语义模型中查找 SymbolInfo,我遇到的问题是,一旦我修改了语法树以生成 class 部分,我就已经失效SemanticModel 并且不能使用它来获取方法的 SymbolInfo。
下面是一个重写器的粗略示例,.InheritsFrom< T >() 是一种扩展方法,它只是遍历继承以查找特定类型的用法,我只是将 IDisposable 作为示例插入其中,但它不是类型是什么非常重要。 .WithPartialModifier() 再次只是一种扩展方法,用于将部分添加到 class syntaxnode 修饰符。
可能我需要改变我的方法或使用新的语法树更新编译,但我不确定如何继续。
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;
}
}
您可以先访问和修改最深的节点,方法是在修改树之前调用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;
}
}