1414// permissions and limitations under the License.
1515
1616using System ;
17- using System . Collections . Generic ;
1817using System . IO ;
1918using System . Linq ;
2019using System . Threading ;
2120using System . Threading . Tasks ;
2221using Microsoft . Python . Analysis ;
23- using Microsoft . Python . Analysis . Documents ;
24- using Microsoft . Python . Analysis . Modules ;
25- using Microsoft . Python . Analysis . Types ;
2622using Microsoft . Python . Core ;
27- using Microsoft . Python . Core . IO ;
2823using Microsoft . Python . Core . Text ;
2924using Microsoft . Python . LanguageServer . Documents ;
3025using Microsoft . Python . LanguageServer . Protocol ;
26+ using Microsoft . Python . Parsing ;
27+ using Microsoft . Python . Parsing . Ast ;
3128
3229namespace Microsoft . Python . LanguageServer . Sources {
3330 internal sealed class DocumentHighlightSource {
@@ -40,25 +37,51 @@ public DocumentHighlightSource(IServiceContainer services) {
4037
4138 public async Task < DocumentHighlight [ ] > DocumentHighlightAsync ( Uri uri , SourceLocation location , CancellationToken cancellationToken = default ) {
4239 if ( uri == null ) {
43- return Array . Empty < DocumentHighlight > ( ) ;
40+ return null ;
4441 }
4542
4643 var analysis = await Document . GetAnalysisAsync ( uri , _services , DocumentHighlightAnalysisTimeout , cancellationToken ) ;
4744 var definitionSource = new DefinitionSource ( _services ) ;
4845
4946 var definition = definitionSource . FindDefinition ( analysis , location , out var definingMember ) ;
5047 if ( definition == null || definingMember == null ) {
51- return Array . Empty < DocumentHighlight > ( ) ;
48+ return FromTokens ( analysis , location ) ;
5249 }
5350
5451 var rootDefinition = definingMember . GetRootDefinition ( ) ;
5552
5653 var result = rootDefinition . References
5754 . Where ( r => r . DocumentUri . Equals ( uri ) )
58- . Select ( ( r , i ) => new DocumentHighlight { kind = ( i == 0 ) ? DocumentHighlightKind . Write : DocumentHighlightKind . Read , range = r . Span } )
55+ . Select ( ( r , i ) => new DocumentHighlight {
56+ kind = i == 0 ? DocumentHighlightKind . Write : DocumentHighlightKind . Read , range = r . Span
57+ } )
5958 . ToArray ( ) ;
6059
6160 return result ;
6261 }
62+
63+ private static DocumentHighlight [ ] FromTokens ( IDocumentAnalysis analysis , SourceLocation location ) {
64+ var position = analysis . Ast . LocationToIndex ( location ) ;
65+ var content = analysis . Document . Content ;
66+
67+ var tokenizer = new Tokenizer ( analysis . Document . Interpreter . LanguageVersion ) ;
68+ tokenizer . Initialize ( null , new StringReader ( content ) , SourceLocation . MinValue ) ;
69+ var tokens = tokenizer . ReadTokens ( content . Length ) ;
70+
71+ var t = tokens . FirstOrDefault ( x => x . SourceSpan . Start . Index <= position && position < x . SourceSpan . End . Index ) ;
72+ if ( t . Category != TokenCategory . None ) {
73+ var length = t . SourceSpan . End . Index - t . SourceSpan . Start . Index ;
74+ return tokens
75+ . Where ( x =>
76+ x . SourceSpan . End . Index - x . SourceSpan . Start . Index == length &&
77+ string . Compare ( content , x . SourceSpan . Start . Index , content , t . SourceSpan . Start . Index , length ) == 0 )
78+ . Select ( s => new DocumentHighlight {
79+ kind = DocumentHighlightKind . Text ,
80+ range = s . SourceSpan
81+ } ) . ToArray ( ) ;
82+ }
83+
84+ return null ;
85+ }
6386 }
6487}
0 commit comments