Skip to content

Commit ad49351

Browse files
committed
Multi project incoming calls
1 parent 51eadd5 commit ad49351

File tree

6 files changed

+262
-28
lines changed

6 files changed

+262
-28
lines changed

internal/ls/callhierarchy.go

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"slices"
66
"strings"
7+
"sync"
78

89
"github.com/microsoft/typescript-go/internal/ast"
910
"github.com/microsoft/typescript-go/internal/astnav"
@@ -567,24 +568,78 @@ func (l *LanguageService) convertCallSiteGroupToIncomingCall(program *compiler.P
567568
}
568569
}
569570

571+
type incomingEntry struct {
572+
ls *LanguageService
573+
node *ast.Node
574+
575+
sourceFileOnce sync.Once
576+
sourceFile *ast.SourceFile
577+
578+
documentUriOnce sync.Once
579+
documentUri lsproto.DocumentUri
580+
581+
positionOnce sync.Once
582+
position lsproto.Position
583+
}
584+
585+
var _ lsproto.HasTextDocumentPosition = (*incomingEntry)(nil)
586+
587+
func (d *incomingEntry) getSourceFile() *ast.SourceFile {
588+
d.sourceFileOnce.Do(func() {
589+
d.sourceFile = ast.GetSourceFileOfNode(d.node)
590+
})
591+
return d.sourceFile
592+
}
593+
594+
func (d *incomingEntry) TextDocumentURI() lsproto.DocumentUri {
595+
d.documentUriOnce.Do(func() {
596+
d.documentUri = lsconv.FileNameToDocumentURI(d.getSourceFile().FileName())
597+
})
598+
return d.documentUri
599+
}
600+
601+
func (d *incomingEntry) TextDocumentPosition() lsproto.Position {
602+
d.positionOnce.Do(func() {
603+
start := scanner.GetTokenPosOfNode(d.node, d.getSourceFile(), false /*includeJsDoc*/)
604+
d.position = d.ls.createLspPosition(start, d.getSourceFile())
605+
})
606+
return d.position
607+
}
608+
570609
// Gets the call sites that call into the provided call hierarchy declaration.
571-
func (l *LanguageService) getIncomingCalls(ctx context.Context, program *compiler.Program, declaration *ast.Node) []*lsproto.CallHierarchyIncomingCall {
610+
func (l *LanguageService) getIncomingCalls(ctx context.Context, program *compiler.Program, declaration *ast.Node, orchestrator CrossProjectOrchestrator) (lsproto.CallHierarchyIncomingCallsResponse, error) {
572611
// Source files and modules have no incoming calls.
573612
if ast.IsSourceFile(declaration) || ast.IsModuleDeclaration(declaration) || ast.IsClassStaticBlockDeclaration(declaration) {
574-
return nil
613+
return lsproto.CallHierarchyIncomingCallsOrNull{}, nil
575614
}
576615

577616
location := getCallHierarchyDeclarationReferenceNode(declaration)
578617
if location == nil {
579-
return nil
618+
return lsproto.CallHierarchyIncomingCallsOrNull{}, nil
580619
}
581620

582-
sourceFiles := program.GetSourceFiles()
583-
options := refOptions{use: referenceUseReferences}
584-
symbolsAndEntries := l.getReferencedSymbolsForNode(ctx, 0, location, program, sourceFiles, options, nil)
621+
incomingEntry := &incomingEntry{
622+
ls: l,
623+
node: location,
624+
}
625+
626+
return handleCrossProject(
627+
l,
628+
ctx,
629+
incomingEntry,
630+
orchestrator,
631+
(*LanguageService).symbolAndEntriesToIncomingCalls,
632+
combineIncomingCalls,
633+
false,
634+
false,
635+
symbolEntryTransformOptions{},
636+
)
637+
}
585638

639+
func (l *LanguageService) symbolAndEntriesToIncomingCalls(ctx context.Context, params *incomingEntry, data SymbolAndEntriesData, options symbolEntryTransformOptions) (lsproto.CallHierarchyIncomingCallsResponse, error) {
640+
program := l.GetProgram()
586641
var refEntries []*ReferenceEntry
587-
for _, symbolAndEntry := range symbolsAndEntries {
642+
for _, symbolAndEntry := range data.SymbolsAndEntries {
588643
refEntries = append(refEntries, symbolAndEntry.references...)
589644
}
590645

@@ -596,7 +651,7 @@ func (l *LanguageService) getIncomingCalls(ctx context.Context, program *compile
596651
}
597652

598653
if len(callSites) == 0 {
599-
return nil
654+
return lsproto.CallHierarchyIncomingCallsOrNull{}, nil
600655
}
601656

602657
grouped := make(map[ast.NodeId][]*callSite)
@@ -620,7 +675,7 @@ func (l *LanguageService) getIncomingCalls(ctx context.Context, program *compile
620675
return lsproto.CompareRanges(&a.FromRanges[0], &b.FromRanges[0])
621676
})
622677

623-
return result
678+
return lsproto.CallHierarchyIncomingCallsOrNull{CallHierarchyIncomingCalls: &result}, nil
624679
}
625680

626681
type callSiteCollector struct {
@@ -947,6 +1002,7 @@ func (l *LanguageService) ProvidePrepareCallHierarchy(
9471002
func (l *LanguageService) ProvideCallHierarchyIncomingCalls(
9481003
ctx context.Context,
9491004
item *lsproto.CallHierarchyItem,
1005+
orchestrator CrossProjectOrchestrator,
9501006
) (lsproto.CallHierarchyIncomingCallsResponse, error) {
9511007
program := l.GetProgram()
9521008
fileName := item.Uri.FileName()
@@ -986,11 +1042,7 @@ func (l *LanguageService) ProvideCallHierarchyIncomingCalls(
9861042
return lsproto.CallHierarchyIncomingCallsOrNull{}, nil
9871043
}
9881044

989-
calls := l.getIncomingCalls(ctx, program, decl)
990-
if calls == nil {
991-
return lsproto.CallHierarchyIncomingCallsOrNull{}, nil
992-
}
993-
return lsproto.CallHierarchyIncomingCallsOrNull{CallHierarchyIncomingCalls: &calls}, nil
1045+
return l.getIncomingCalls(ctx, program, decl, orchestrator)
9941046
}
9951047

9961048
func (l *LanguageService) ProvideCallHierarchyOutgoingCalls(

internal/ls/crossproject.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,3 +345,18 @@ func combineRenameResponse(results iter.Seq[lsproto.RenameResponse]) lsproto.Ren
345345
}
346346
return lsproto.RenameResponse{}
347347
}
348+
349+
func combineIncomingCalls(results iter.Seq[lsproto.CallHierarchyIncomingCallsResponse]) lsproto.CallHierarchyIncomingCallsResponse {
350+
var combined []*lsproto.CallHierarchyIncomingCall
351+
var seenCalls collections.Set[lsproto.Location]
352+
for resp := range results {
353+
if resp.CallHierarchyIncomingCalls != nil {
354+
for _, call := range *resp.CallHierarchyIncomingCalls {
355+
if seenCalls.AddIfAbsent(call.From.GetLocation()) {
356+
combined = append(combined, call)
357+
}
358+
}
359+
}
360+
}
361+
return lsproto.CallHierarchyIncomingCallsResponse{CallHierarchyIncomingCalls: &combined}
362+
}

internal/ls/documenthighlights.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55

66
"github.com/microsoft/typescript-go/internal/ast"
77
"github.com/microsoft/typescript-go/internal/astnav"
8-
"github.com/microsoft/typescript-go/internal/collections"
98
"github.com/microsoft/typescript-go/internal/compiler"
109
"github.com/microsoft/typescript-go/internal/ls/lsutil"
1110
"github.com/microsoft/typescript-go/internal/scanner"
@@ -52,7 +51,7 @@ func (l *LanguageService) ProvideDocumentHighlights(ctx context.Context, documen
5251

5352
func (l *LanguageService) getSemanticDocumentHighlights(ctx context.Context, position int, node *ast.Node, program *compiler.Program, sourceFile *ast.SourceFile) []*lsproto.DocumentHighlight {
5453
options := refOptions{use: referenceUseNone}
55-
referenceEntries := l.getReferencedSymbolsForNode(ctx, position, node, program, []*ast.SourceFile{sourceFile}, options, &collections.Set[string]{})
54+
referenceEntries := l.getReferencedSymbolsForNode(ctx, position, node, program, []*ast.SourceFile{sourceFile}, options)
5655
if referenceEntries == nil {
5756
return nil
5857
}

internal/ls/findallreferences.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ func (l *LanguageService) getSymbolAndEntries(
648648
options.use = referenceUseRename
649649
options.useAliasesForRename = true
650650
}
651-
return l.getReferencedSymbolsForNode(ctx, position, node, program, program.GetSourceFiles(), options, nil)
651+
return l.getReferencedSymbolsForNode(ctx, position, node, program, program.GetSourceFiles(), options)
652652
}
653653

654654
func (l *LanguageService) ProvideReferences(ctx context.Context, params *lsproto.ReferenceParams, orchestrator CrossProjectOrchestrator) (lsproto.ReferencesResponse, error) {
@@ -928,13 +928,11 @@ func (l *LanguageService) mergeReferences(program *compiler.Program, referencesT
928928

929929
// === functions for find all ref implementation ===
930930

931-
func (l *LanguageService) getReferencedSymbolsForNode(ctx context.Context, position int, node *ast.Node, program *compiler.Program, sourceFiles []*ast.SourceFile, options refOptions, sourceFilesSet *collections.Set[string]) []*SymbolAndEntries {
931+
func (l *LanguageService) getReferencedSymbolsForNode(ctx context.Context, position int, node *ast.Node, program *compiler.Program, sourceFiles []*ast.SourceFile, options refOptions) []*SymbolAndEntries {
932932
// !!! cancellationToken
933-
if sourceFilesSet == nil || sourceFilesSet.Len() == 0 {
934-
sourceFilesSet = collections.NewSetWithSizeHint[string](len(sourceFiles))
935-
for _, file := range sourceFiles {
936-
sourceFilesSet.Add(file.FileName())
937-
}
933+
sourceFilesSet := collections.NewSetWithSizeHint[string](len(sourceFiles))
934+
for _, file := range sourceFiles {
935+
sourceFilesSet.Add(file.FileName())
938936
}
939937

940938
if options.use == referenceUseReferences || options.use == referenceUseRename {

internal/lsp/server.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,13 +1135,13 @@ func (s *Server) handlePrepareCallHierarchy(
11351135
func (s *Server) handleCallHierarchyIncomingCalls(
11361136
ctx context.Context,
11371137
params *lsproto.CallHierarchyIncomingCallsParams,
1138-
_ *lsproto.RequestMessage,
1138+
reqMsg *lsproto.RequestMessage,
11391139
) (lsproto.CallHierarchyIncomingCallsResponse, error) {
1140-
languageService, err := s.session.GetLanguageService(ctx, params.Item.Uri)
1140+
defaultProject, defaultLs, allProjects, err := s.session.GetLanguageServiceAndProjectsForFile(ctx, params.Item.Uri)
11411141
if err != nil {
11421142
return lsproto.CallHierarchyIncomingCallsOrNull{}, err
11431143
}
1144-
return languageService.ProvideCallHierarchyIncomingCalls(ctx, params.Item)
1144+
return defaultLs.ProvideCallHierarchyIncomingCalls(ctx, params.Item, &crossProjectOrchestrator{s, reqMsg, defaultProject, allProjects})
11451145
}
11461146

11471147
func (s *Server) handleCallHierarchyOutgoingCalls(

0 commit comments

Comments
 (0)