2015-02-14 1 views
4

Я создаю SyntaxRewriter, ознаменовавший классы как частичные и методы, как виртуальный, если класс наследует от определенного типаДоступ SymbolInfo из модифицированного SyntaxNode в Рослин SyntaxRewriter

Чтобы сделать это, я, глядя на SymbolInfo от Семантическая модель внутри Rewriter, проблема, с которой я сталкиваюсь, заключается в том, что как только я изменяю syntaxtree для частичного класса, я аннулировал SemanticModel и не могу использовать его для получения методов SymbolInfo для методов.

Приведенный ниже пример переписывания .InheritsFrom < T>() - это метод расширения, который просто наследует наследование, чтобы найти способы использования определенного типа, я просто застрял на IDisposable в качестве примера, но на самом деле это не так. важно, что такое тип. .WithPartialModifier() снова просто метод расширения для добавления частичного к модификаторам синтаксического кода класса.

Возможно, мне нужно переключить мой подход или обновить компиляцию с помощью нового 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; 
    } 
} 

ответ

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; 
    } 
} 
+0

Это идеальный вариант, спасибо. –