1010using SourceBrowser . Generator . Extensions ;
1111using SourceBrowser . Generator . Model ;
1212using SourceBrowser . Generator . Model . VisualBasic ;
13+ using Microsoft . CodeAnalysis . Shared . Extensions ;
14+ using Microsoft . CodeAnalysis . FindSymbols ;
1315
1416namespace SourceBrowser . Generator . DocumentWalkers
1517{
@@ -23,7 +25,9 @@ public class VBWalker : VisualBasicSyntaxWalker, IWalker
2325 public DocumentModel DocumentModel { get ; private set ; }
2426 public string FilePath { get ; set ; }
2527
26- public VBWalker ( IProjectItem parent , Document document , ReferencesourceLinkProvider refSourceLinkProvider ) : base ( SyntaxWalkerDepth . Trivia )
28+ private Document _document ;
29+
30+ public VBWalker ( IProjectItem parent , Document document , ReferencesourceLinkProvider refSourceLinkProvider ) : base ( SyntaxWalkerDepth . Trivia )
2731 {
2832 _model = document . GetSemanticModelAsync ( ) . Result ;
2933 _refsourceLinkProvider = refSourceLinkProvider ;
@@ -33,12 +37,13 @@ public VBWalker(IProjectItem parent, Document document, ReferencesourceLinkProvi
3337 DocumentModel = new DocumentModel ( parent , document . Name , numberOfLines ) ;
3438 FilePath = document . GetRelativeFilePath ( ) ;
3539 _refsourceLinkProvider = refSourceLinkProvider ;
40+ _document = document ;
3641 }
3742
3843 public override void VisitToken ( SyntaxToken token )
3944 {
4045 Token tokenModel = null ;
41-
46+
4247 if ( token . IsKeyword ( ) )
4348 {
4449 tokenModel = ProcessKeyword ( token ) ;
@@ -47,7 +52,7 @@ public override void VisitToken(SyntaxToken token)
4752 {
4853 tokenModel = ProcessIdentifier ( token ) ;
4954 }
50- else if ( token . VisualBasicKind ( ) == SyntaxKind . StringLiteralToken )
55+ else if ( token . VisualBasicKind ( ) == SyntaxKind . StringLiteralToken )
5156 {
5257 tokenModel = ProcessStringLiteral ( token ) ;
5358 }
@@ -92,7 +97,6 @@ private Token ProcessOtherToken(SyntaxToken token)
9297 int lineNumber = token . GetLocation ( ) . GetLineSpan ( ) . StartLinePosition . Line + 1 ;
9398
9499 var tokenModel = new Token ( this . DocumentModel , fullName , value , type , lineNumber ) ;
95-
96100 return tokenModel ;
97101 }
98102
@@ -105,7 +109,6 @@ public Token ProcessKeyword(SyntaxToken token)
105109 string value = token . ToString ( ) ;
106110 string type = VisualBasicTokenTypes . KEYWORD ;
107111 int lineNumber = token . GetLocation ( ) . GetLineSpan ( ) . StartLinePosition . Line + 1 ;
108-
109112 var tokenModel = new Token ( this . DocumentModel , fullName , value , type , lineNumber ) ;
110113 return tokenModel ;
111114 }
@@ -116,24 +119,19 @@ private Token ProcessStringLiteral(SyntaxToken token)
116119 string value = token . ToString ( ) ;
117120 string type = VisualBasicTokenTypes . STRING ;
118121 int lineNumber = token . GetLocation ( ) . GetLineSpan ( ) . StartLinePosition . Line + 1 ;
119-
120122 var tokenModel = new Token ( this . DocumentModel , fullName , value , type , lineNumber ) ;
121123 return tokenModel ;
122124 }
123125
124- /// <summary>
125- /// Given a syntax token identifier that represents a declaration,
126- /// generate and return the proper HTML for this symbol.
127- /// </summary>
128- public Token ProcessDeclarationToken ( SyntaxToken token , ISymbol parentSymbol )
126+ public Token ProcessSymbolUsage ( SyntaxToken token , ISymbol symbol , bool isDeclaration )
129127 {
130- string fullName = parentSymbol . ToString ( ) ;
128+ string fullName = GetSymbolName ( symbol ) ;
131129 string value = token . ToString ( ) ;
132- string type = string . Empty ;
130+ string type = String . Empty ;
133131 int lineNumber = token . GetLocation ( ) . GetLineSpan ( ) . StartLinePosition . Line + 1 ;
134- bool isDeclaration = true ;
132+ bool isSearchable = isDeclaration ;
135133
136- if ( parentSymbol is INamedTypeSymbol )
134+ if ( symbol is INamedTypeSymbol )
137135 {
138136 type = VisualBasicTokenTypes . TYPE ;
139137 }
@@ -142,36 +140,19 @@ public Token ProcessDeclarationToken(SyntaxToken token, ISymbol parentSymbol)
142140 type = VisualBasicTokenTypes . IDENTIFIER ;
143141 }
144142
145- var tokenModel = new Token ( this . DocumentModel , fullName , value , type , lineNumber , isDeclaration ) ;
146- return tokenModel ;
147- }
148-
149- /// <summary>
150- /// Given a syntax token identifier that represents a symbol's usage
151- /// generate and return the proper HTML for this symbol
152- /// </summary>
153- public Token ProcessSymbolUsage ( SyntaxToken token , ISymbol symbol )
154- {
155- string fullName = symbol . ToString ( ) ;
156- string value = token . ToString ( ) ;
157- string type = string . Empty ;
158- int lineNumber = token . GetLocation ( ) . GetLineSpan ( ) . StartLinePosition . Line + 1 ;
159- if ( symbol is INamedTypeSymbol )
143+ //Do not allow us to search locals
144+ if ( symbol . Kind == SymbolKind . Local || symbol . Kind == SymbolKind . Parameter )
160145 {
161- type = VisualBasicTokenTypes . TYPE ;
146+ isSearchable = false ;
162147 }
163- else
164- {
165- type = VisualBasicTokenTypes . IDENTIFIER ;
166- }
167-
148+
168149 var tokenModel = new Token ( this . DocumentModel , fullName , value , type , lineNumber ) ;
169150
170151 //If we can find the declaration, we'll link it ourselves
171152 if ( symbol . DeclaringSyntaxReferences . Any ( )
172153 && ! ( symbol is INamespaceSymbol ) )
173154 {
174- var link = new SymbolLink ( referencedSymbolName : symbol . ToString ( ) ) ;
155+ var link = new SymbolLink ( referencedSymbolName : fullName ) ;
175156 tokenModel = tokenModel . WithLink ( link ) ;
176157 }
177158 //Otherwise, we try to link to the .Net Reference source
@@ -185,28 +166,41 @@ public Token ProcessSymbolUsage(SyntaxToken token, ISymbol symbol)
185166 return tokenModel ;
186167 }
187168
169+ private string GetSymbolName ( ISymbol symbol )
170+ {
171+ string fullyQualifiedName ;
172+ if ( symbol . Kind == SymbolKind . Parameter )
173+ {
174+ var containingName = symbol . ContainingSymbol . ToString ( ) ;
175+ fullyQualifiedName = containingName + VBDelimiters . PARAMETER + symbol . Name ;
176+ }
177+ else if ( symbol . Kind == SymbolKind . Local )
178+ {
179+ var containingName = symbol . ContainingSymbol . ToString ( ) ;
180+ fullyQualifiedName = containingName + VBDelimiters . LOCAL_VARIABLE + symbol . Name ;
181+ }
182+ else
183+ {
184+ fullyQualifiedName = symbol . ToString ( ) ;
185+ }
186+
187+ return fullyQualifiedName ;
188+ }
189+
188190 public Token ProcessIdentifier ( SyntaxToken token )
189191 {
190192 //Check if this token is part of a declaration
191- var parentSymbol = _model . GetDeclaredSymbol ( token . Parent ) ;
192- if ( parentSymbol != null )
193+ bool isDeclaration = false ;
194+ if ( _model . GetDeclaredSymbol ( token . Parent ) != null )
193195 {
194- if ( parentSymbol . Kind == SymbolKind . Parameter )
195- {
196- parentSymbol = parentSymbol . ContainingSymbol ;
197- }
198- return ProcessDeclarationToken ( token , parentSymbol ) ;
196+ isDeclaration = true ;
199197 }
200-
201- //Find the symbol this token references
202- var symbol = _model . GetSymbolInfo ( token . Parent ) . Symbol ;
198+ var startPosition = token . GetLocation ( ) . SourceSpan . Start ;
199+ //Note: We're using the SymbolFinder as it correctly resolves
200+ var symbol = SymbolFinder . FindSymbolAtPosition ( _model , startPosition , _document . Project . Solution . Workspace ) ;
203201 if ( symbol != null )
204202 {
205- if ( symbol . Kind == SymbolKind . Parameter )
206- {
207- symbol = symbol . ContainingSymbol ;
208- }
209- return ProcessSymbolUsage ( token , symbol ) ;
203+ return ProcessSymbolUsage ( token , symbol , isDeclaration ) ;
210204 }
211205
212206 //Otherwise it references something we don't
0 commit comments