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

旧街凉风 提交于 2019-12-04 05:56:52

问题


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

var members = SyntaxTree.GetRoot().DescendantNodes().Where(node =>
                          node is ClassStatementSyntax ||
                          node is FunctionAggregationSyntax ||
                          node is IncompleteMemberSyntax ||
                          node is MethodBaseSyntax ||
                          node is ModuleStatementSyntax ||
                          node is NamespaceStatementSyntax ||
                          node is PropertyStatementSyntax ||
                          node is SubNewStatementSyntax
                        );

How do get the member name, StarLineNumber and EndLineNumber of each member?


回答1:


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



来源:https://stackoverflow.com/questions/50120799/using-roslyn-how-to-enumerate-members-namespaces-classes-etc-details-in-visu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!