Using Roslyn, how to enumerate members (Namespaces, classes etc) details in Visual Basic Document?

后端 未结 1 1691
渐次进展
渐次进展 2021-01-28 15:33

Using Roslyn, the only mechanism for determining members of Visual Basic document appears to be:

var members = SyntaxTree.GetRoot().DescendantNodes().Where(node          


        
相关标签:
1条回答
  • 2021-01-28 15:47

    Exists not only the one way to get it:

    1) As you try: I willn't show this way for all of kind member (they count are huge and the logic is the similar), but only a one of them, for example ClassStatementSyntax:

    • to achive it name just get ClassStatementSyntax.Identifier.ValueText
    • to get start line you can use Location as one of ways:
    var location = Location.Create(SyntaxTree, ClassStatementSyntax.Identifier.Span);
    var startLine = location.GetLineSpan().StartLinePosition.Line;
    
    • logic for retrieving the end line looks like a logic to receive the start line but it dependents on the corresponding closing statement (some kind of end statement or self)

    2) More useful way – use SemanticModel to get a data that you want: In this way you will need to receive semantic info only for ClassStatementSyntax, ModuleStatementSyntxt and NamespaceStatementSyntax, and all of their members will be received just calling GetMembers():

    ...
    
      SemanticModel semanticModel = // usually it is received from the corresponding compilation
      var typeSyntax = // ClassStatementSyntax, ModuleStatementSyntxt or NamespaceStatementSyntax
      string name = null;
      int startLine;
      int endLine;
    
      var info = semanticModel.GetSymbolInfo(typeSyntax);
      if (info.Symbol is INamespaceOrTypeSymbol typeSymbol)
      {
          name = typeSymbol.Name; // retrieve Name
          startLine = semanticModel.SyntaxTree.GetLineSpan(typeSymbol.DeclaringSyntaxReferences[0].Span).StartLinePosition.Line; //retrieve start line
          endLine = semanticModel.SyntaxTree.GetLineSpan(typeSymbol.DeclaringSyntaxReferences[0].Span).EndLinePosition.Line; //retrieve end line
          foreach (var item in typeSymbol.GetMembers())
          {
              // do the same logic for retrieving name and lines for all others members without calling GetMembers()
          }
      }
      else if (semanticModel.GetDeclaredSymbol(typeSyntax) is INamespaceOrTypeSymbol typeSymbol2)
      {
          name = typeSymbol2.Name; // retrieve Name
          startLine = semanticModel.SyntaxTree.GetLineSpan(typeSymbol2.DeclaringSyntaxReferences[0].Span).StartLinePosition.Line; //retrieve start line
          endLine = semanticModel.SyntaxTree.GetLineSpan(typeSymbol2.DeclaringSyntaxReferences[0].Span).EndLinePosition.Line; //retrieve end line
    
          foreach (var item in typeSymbol2.GetMembers())
          {
              // do the same logic for retrieving name and lines for all others members without calling GetMembers()
          }
      }
    

    But attention, when you have a partial declaration your DeclaringSyntaxReferences will have a couple items, so you need to filter SyntaxReference by your current SyntaxTree

    0 讨论(0)
提交回复
热议问题