@@ -128,14 +128,10 @@ func newNodeEntryWithKind(node *ast.Node, kind entryKind) *referenceEntry {
128128
129129func newNodeEntry (node * ast.Node ) * referenceEntry {
130130 // creates nodeEntry with `kind == entryKindNode`
131- n := node
132- if node != nil && node .Name () != nil {
133- n = node .Name ()
134- }
135131 return & referenceEntry {
136132 kind : entryKindNode ,
137- node : node ,
138- context : getContextNodeForNodeEntry (n ),
133+ node : core . OrElse ( node . Name (), node ) ,
134+ context : getContextNodeForNodeEntry (node ),
139135 }
140136}
141137
@@ -410,22 +406,53 @@ func (l *LanguageService) ProvideReferences(params *lsproto.ReferenceParams) []*
410406
411407 symbolsAndEntries := l .getReferencedSymbolsForNode (position , node , program , program .GetSourceFiles (), options , nil )
412408
413- return core .FlatMap (symbolsAndEntries , l .convertSymbolAndEntryToLocation )
409+ return core .FlatMap (symbolsAndEntries , l .convertSymbolAndEntriesToLocations )
410+ }
411+
412+ func (l * LanguageService ) ProvideImplementations (params * lsproto.ImplementationParams ) []* lsproto.Location {
413+ program , sourceFile := l .getProgramAndFile (params .TextDocument .Uri )
414+ position := int (l .converters .LineAndCharacterToPosition (sourceFile , params .Position ))
415+ node := astnav .GetTouchingPropertyName (sourceFile , position )
416+
417+ var seenNodes collections.Set [* ast.Node ]
418+ var entries []* referenceEntry
419+ queue := l .getImplementationReferenceEntries (program , node , position )
420+ for len (queue ) != 0 {
421+ entry := queue [0 ]
422+ queue = queue [1 :]
423+ if ! seenNodes .Has (entry .node ) {
424+ seenNodes .Add (entry .node )
425+ entries = append (entries , entry )
426+ queue = append (queue , l .getImplementationReferenceEntries (program , entry .node , entry .node .Pos ())... )
427+ }
428+ }
429+
430+ return l .convertEntriesToLocations (entries )
431+ }
432+
433+ func (l * LanguageService ) getImplementationReferenceEntries (program * compiler.Program , node * ast.Node , position int ) []* referenceEntry {
434+ options := refOptions {use : referenceUseReferences , implementations : true }
435+ symbolsAndEntries := l .getReferencedSymbolsForNode (position , node , program , program .GetSourceFiles (), options , nil )
436+ return core .FlatMap (symbolsAndEntries , func (s * SymbolAndEntries ) []* referenceEntry { return s .references })
414437}
415438
416439// == functions for conversions ==
417- func (l * LanguageService ) convertSymbolAndEntryToLocation (s * SymbolAndEntries ) []* lsproto.Location {
418- var locations []* lsproto.Location
419- for _ , ref := range s .references {
420- if ref .textRange == nil {
421- sourceFile := ast .GetSourceFileOfNode (ref .node )
422- ref .textRange = l .getRangeOfNode (ref .node , sourceFile , nil /*endNode*/ )
423- ref .fileName = sourceFile .FileName ()
440+ func (l * LanguageService ) convertSymbolAndEntriesToLocations (s * SymbolAndEntries ) []* lsproto.Location {
441+ return l .convertEntriesToLocations (s .references )
442+ }
443+
444+ func (l * LanguageService ) convertEntriesToLocations (entries []* referenceEntry ) []* lsproto.Location {
445+ locations := make ([]* lsproto.Location , len (entries ))
446+ for i , entry := range entries {
447+ if entry .textRange == nil {
448+ sourceFile := ast .GetSourceFileOfNode (entry .node )
449+ entry .textRange = l .getRangeOfNode (entry .node , sourceFile , nil /*endNode*/ )
450+ entry .fileName = sourceFile .FileName ()
451+ }
452+ locations [i ] = & lsproto.Location {
453+ Uri : FileNameToDocumentURI (entry .fileName ),
454+ Range : * entry .textRange ,
424455 }
425- locations = append (locations , & lsproto.Location {
426- Uri : FileNameToDocumentURI (ref .fileName ),
427- Range : * ref .textRange ,
428- })
429456 }
430457 return locations
431458}
0 commit comments