0

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?

Pang
  • 9,564
  • 146
  • 81
  • 122
Joginder S Nahil
  • 791
  • 1
  • 6
  • 17

1 Answers1

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

George Alexandria
  • 2,841
  • 2
  • 16
  • 24
  • Any idea why the startLine and endLine be the same value? – Joginder S Nahil Jun 14 '18 at 15:56
  • @JoginderSNahil, it means that you have a some declaration that may be located fully on the one line, for example `FieldDeclarationSyntax`,`PropertyDeclarationSyntax` (without `Get`, `Set`), `MethodStatementSyntax` (for `MustOverride` method) can be located at the one line and etc., so startLine and endLine will be the same, but the startPosition and endPosition of course will be different. – George Alexandria Jun 14 '18 at 20:37
  • I only analysed Namespace and Class declarations and they are not on the same line. Does the logic works for you? – Joginder S Nahil Jun 17 '18 at 09:07
  • @JoginderSNahil, my apologies, I really believed that `ISymbol.Locations` contains the full span of item, not just a start of declaration. I updated answer changed usages of `Locations` at `DeclaringSyntaxReferences` – George Alexandria Jun 17 '18 at 09:49
  • Your changes work perfectly. Many thanks for providing the answer in such a detail. – Joginder S Nahil Jun 18 '18 at 17:57
  • @JoginderSNahil, is it you downvoted the answer by mistake or someone else? :) – George Alexandria Jun 18 '18 at 18:03
  • I had not realised that I have done that! How can I put it right? – Joginder S Nahil Jun 18 '18 at 21:29
  • @JoginderSNahil, try to upvote if you can (want), else I don't know a way to revert it and we don't worry about it :) – George Alexandria Jun 18 '18 at 21:50