Skip to content

Commit 88e95c9

Browse files
authored
Implement Go To Implementations command (#1430)
1 parent 7c16fa3 commit 88e95c9

File tree

4 files changed

+63
-22
lines changed

4 files changed

+63
-22
lines changed

internal/ast/ast.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -605,15 +605,13 @@ func (n *Node) Type() *Node {
605605
return n.AsCommonJSExport().Type
606606
case KindBinaryExpression:
607607
return n.AsBinaryExpression().Type
608-
case KindEnumMember, KindBindingElement:
609-
return nil
610608
default:
611609
funcLike := n.FunctionLikeData()
612610
if funcLike != nil {
613611
return funcLike.Type
614612
}
615613
}
616-
panic("Unhandled case in Node.Type: " + n.Kind.String())
614+
return nil
617615
}
618616

619617
func (n *Node) Initializer() *Node {

internal/ls/definition.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func getDeclarationNameForKeyword(node *ast.Node) *ast.Node {
119119
if decl := core.FirstOrNil(node.Parent.AsVariableDeclarationList().Declarations.Nodes); decl != nil && decl.Name() != nil {
120120
return decl.Name()
121121
}
122-
} else if node.Parent.Name() != nil && node.Pos() < node.Parent.Name().Pos() {
122+
} else if node.Parent.DeclarationData() != nil && node.Parent.Name() != nil && node.Pos() < node.Parent.Name().Pos() {
123123
return node.Parent.Name()
124124
}
125125
}

internal/ls/findallreferences.go

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,10 @@ func newNodeEntryWithKind(node *ast.Node, kind entryKind) *referenceEntry {
128128

129129
func 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
}

internal/lsp/server.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,8 @@ func (s *Server) handleRequestOrNotification(ctx context.Context, req *lsproto.R
488488
return s.handleCompletion(ctx, req)
489489
case *lsproto.ReferenceParams:
490490
return s.handleReferences(ctx, req)
491+
case *lsproto.ImplementationParams:
492+
return s.handleImplementations(ctx, req)
491493
case *lsproto.SignatureHelpParams:
492494
return s.handleSignatureHelp(ctx, req)
493495
case *lsproto.DocumentFormattingParams:
@@ -560,6 +562,9 @@ func (s *Server) handleInitialize(req *lsproto.RequestMessage) {
560562
ReferencesProvider: &lsproto.BooleanOrReferenceOptions{
561563
Boolean: ptrTo(true),
562564
},
565+
ImplementationProvider: &lsproto.BooleanOrImplementationOptionsOrImplementationRegistrationOptions{
566+
Boolean: ptrTo(true),
567+
},
563568
DiagnosticProvider: &lsproto.DiagnosticOptionsOrDiagnosticRegistrationOptions{
564569
DiagnosticOptions: &lsproto.DiagnosticOptions{
565570
InterFileDependencies: true,
@@ -725,6 +730,17 @@ func (s *Server) handleReferences(ctx context.Context, req *lsproto.RequestMessa
725730
return nil
726731
}
727732

733+
func (s *Server) handleImplementations(ctx context.Context, req *lsproto.RequestMessage) error {
734+
// goToImplementation
735+
params := req.Params.(*lsproto.ImplementationParams)
736+
project := s.projectService.EnsureDefaultProjectForURI(params.TextDocument.Uri)
737+
languageService, done := project.GetLanguageServiceForRequest(ctx)
738+
defer done()
739+
locations := languageService.ProvideImplementations(params)
740+
s.sendResult(req.ID, locations)
741+
return nil
742+
}
743+
728744
func (s *Server) handleCompletion(ctx context.Context, req *lsproto.RequestMessage) error {
729745
params := req.Params.(*lsproto.CompletionParams)
730746
project := s.projectService.EnsureDefaultProjectForURI(params.TextDocument.Uri)

0 commit comments

Comments
 (0)