@@ -505,8 +505,8 @@ var handlers = sync.OnceValue(func() handlerMap {
505505 registerLanguageServiceDocumentRequestHandler (handlers , lsproto .TextDocumentDocumentHighlightInfo , (* Server ).handleDocumentHighlight )
506506 registerLanguageServiceDocumentRequestHandler (handlers , lsproto .TextDocumentSelectionRangeInfo , (* Server ).handleSelectionRange )
507507
508- registerMultiProjectDocumentRequestHandler (handlers , lsproto .TextDocumentReferencesInfo , (* Server ).handleReferences )
509- registerMultiProjectDocumentRequestHandler (handlers , lsproto .TextDocumentRenameInfo , (* Server ).handleRename )
508+ registerMultiProjectDocumentRequestHandler (handlers , lsproto .TextDocumentReferencesInfo , (* Server ).handleReferences , combineReferences )
509+ registerMultiProjectDocumentRequestHandler (handlers , lsproto .TextDocumentRenameInfo , (* Server ).handleRename , combineRenameResponse )
510510
511511 registerRequestHandler (handlers , lsproto .WorkspaceSymbolInfo , (* Server ).handleWorkspaceSymbol )
512512 registerRequestHandler (handlers , lsproto .CompletionItemResolveInfo , (* Server ).handleCompletionItemResolve )
@@ -583,27 +583,70 @@ func registerLanguageServiceDocumentRequestHandler[Req lsproto.HasTextDocumentUR
583583 }
584584}
585585
586- func registerMultiProjectDocumentRequestHandler [Req lsproto.HasTextDocumentURI , Resp any ](handlers handlerMap , info lsproto.RequestInfo [Req , Resp ], fn func (* Server , context.Context , * ls.LanguageService , Req ) (Resp , error )) {
586+ func registerMultiProjectDocumentRequestHandler [Req lsproto.HasTextDocumentURI , Resp any ](
587+ handlers handlerMap ,
588+ info lsproto.RequestInfo [Req , Resp ],
589+ fn func (* Server , context.Context , * ls.LanguageService , Req ) (Resp , error ),
590+ combineResults func (* project.Project , * collections.SyncMap [tspath.Path , Resp ]) Resp ,
591+ ) {
587592 handlers [info .Method ] = func (s * Server , ctx context.Context , req * lsproto.RequestMessage ) error {
588593 var params Req
589594 // Ignore empty params.
590595 if req .Params != nil {
591596 params = req .Params .(Req )
592597 }
593598 // !!! sheetal: multiple projects that contain the file through symlinks
594- // !!! multiple projects that contain the file directly
595- ls , err := s .session .GetLanguageService (ctx , params .TextDocumentURI ())
599+ defaultProject , defaultLs , allProjects , err := s .session .GetProjectsForFile (ctx , params .TextDocumentURI ())
596600 if err != nil {
597601 return err
598602 }
599603 defer s .recover (req )
600- resp , err := fn (s , ctx , ls , params )
601- if err != nil {
602- return err
604+ var results collections.SyncMap [tspath.Path , Resp ]
605+ var workInProgress collections.SyncMap [tspath.Path , bool ]
606+ workInProgress .Store (defaultProject .Id (), true )
607+ wg := core .NewWorkGroup (false )
608+ enqueueWorkForNonDefaultProject := func (project * project.Project ) {
609+ if project == defaultProject {
610+ return
611+ }
612+ wg .Queue (func () {
613+ if ctx .Err () != nil {
614+ return
615+ }
616+ if _ , loaded := workInProgress .LoadOrStore (project .Id (), true ); loaded {
617+ return
618+ }
619+ defer s .recover (req )
620+ ls := s .session .GetLanguageServiceForProjectWithFile (ctx , project , params .TextDocumentURI ())
621+ if ls != nil {
622+ resp , err1 := fn (s , ctx , ls , params )
623+ if err1 != nil {
624+ return
625+ }
626+ results .Store (project .Id (), resp )
627+ }
628+ })
603629 }
630+
631+ // Other projects
632+ for _ , project := range allProjects {
633+ enqueueWorkForNonDefaultProject (project )
634+ }
635+
636+ // Default projects
637+ wg .Queue (func () {
638+ resp , err1 := fn (s , ctx , defaultLs , params )
639+ if err1 != nil {
640+ return
641+ }
642+ results .Store (defaultProject .Id (), resp )
643+ // TODO:: if default location needs to be add more projects to request
644+ })
645+ wg .RunAndWait ()
604646 if ctx .Err () != nil {
605647 return ctx .Err ()
606648 }
649+ resp := combineResults (defaultProject , & results )
607650 s .sendResult (req .ID , resp )
608651 return nil
609652 }
@@ -880,9 +923,36 @@ func (s *Server) handleTypeDefinition(ctx context.Context, ls *ls.LanguageServic
880923 return ls .ProvideTypeDefinition (ctx , params .TextDocument .Uri , params .Position , getTypeDefinitionClientSupportsLink (s .initializeParams ))
881924}
882925
883- func (s * Server ) handleReferences (ctx context.Context , ls * ls.LanguageService , params * lsproto.ReferenceParams ) (lsproto.ReferencesResponse , error ) {
926+ func (s * Server ) handleReferences (ctx context.Context , defaultLs * ls.LanguageService , params * lsproto.ReferenceParams ) (lsproto.ReferencesResponse , error ) {
884927 // findAllReferences
885- return ls .ProvideReferences (ctx , params )
928+ return defaultLs .ProvideReferences (ctx , params )
929+ }
930+
931+ func combineReferences (defaultProject * project.Project , results * collections.SyncMap [tspath.Path , lsproto.ReferencesResponse ]) lsproto.ReferencesResponse {
932+ var combined []lsproto.Location
933+ var seenLocations collections.Set [lsproto.Location ]
934+ if resp , ok := results .Load (defaultProject .Id ()); ok {
935+ if resp .Locations != nil {
936+ for _ , loc := range * resp .Locations {
937+ seenLocations .Add (loc )
938+ combined = append (combined , loc )
939+ }
940+ }
941+ }
942+ results .Range (func (projectID tspath.Path , resp lsproto.ReferencesResponse ) bool {
943+ if projectID != defaultProject .Id () {
944+ if resp .Locations != nil {
945+ for _ , loc := range * resp .Locations {
946+ if ! seenLocations .Has (loc ) {
947+ seenLocations .Add (loc )
948+ combined = append (combined , loc )
949+ }
950+ }
951+ }
952+ }
953+ return true
954+ })
955+ return lsproto.LocationsOrNull {Locations : & combined }
886956}
887957
888958func (s * Server ) handleImplementations (ctx context.Context , ls * ls.LanguageService , params * lsproto.ImplementationParams ) (lsproto.ImplementationResponse , error ) {
@@ -962,6 +1032,62 @@ func (s *Server) handleRename(ctx context.Context, ls *ls.LanguageService, param
9621032 return ls .ProvideRename (ctx , params )
9631033}
9641034
1035+ func combineRenameResponse (defaultProject * project.Project , results * collections.SyncMap [tspath.Path , lsproto.RenameResponse ]) lsproto.RenameResponse {
1036+ combined := make (map [lsproto.DocumentUri ][]* lsproto.TextEdit )
1037+ seenChanges := make (map [lsproto.DocumentUri ]* collections.Set [lsproto.TextEdit ])
1038+ // !!! this is not used any more so we will skip this part of deduplication and combining
1039+ // DocumentChanges *[]TextDocumentEditOrCreateFileOrRenameFileOrDeleteFile `json:"documentChanges,omitzero"`
1040+ // ChangeAnnotations *map[string]*ChangeAnnotation `json:"changeAnnotations,omitzero"`
1041+
1042+ if resp , ok := results .Load (defaultProject .Id ()); ok {
1043+ if resp .WorkspaceEdit != nil {
1044+ for doc , changes := range * resp .WorkspaceEdit .Changes {
1045+ seenSet := collections.Set [lsproto.TextEdit ]{}
1046+ seenChanges [doc ] = & seenSet
1047+ var changesForDoc []* lsproto.TextEdit
1048+ for _ , change := range changes {
1049+ seenSet .Add (* change )
1050+ changesForDoc = append (changesForDoc , change )
1051+ }
1052+ combined [doc ] = changesForDoc
1053+ }
1054+ }
1055+ }
1056+ results .Range (func (projectID tspath.Path , resp lsproto.RenameResponse ) bool {
1057+ if projectID != defaultProject .Id () {
1058+ if resp .WorkspaceEdit != nil {
1059+ for doc , changes := range * resp .WorkspaceEdit .Changes {
1060+ seenSet , ok := seenChanges [doc ]
1061+ if ! ok {
1062+ seenSet = & collections.Set [lsproto.TextEdit ]{}
1063+ seenChanges [doc ] = seenSet
1064+ }
1065+ changesForDoc , exists := combined [doc ]
1066+ if ! exists {
1067+ changesForDoc = []* lsproto.TextEdit {}
1068+ }
1069+ for _ , change := range changes {
1070+ if ! seenSet .Has (* change ) {
1071+ seenSet .Add (* change )
1072+ changesForDoc = append (changesForDoc , change )
1073+ }
1074+ }
1075+ combined [doc ] = changesForDoc
1076+ }
1077+ }
1078+ }
1079+ return true
1080+ })
1081+ if len (combined ) > 0 {
1082+ return lsproto.RenameResponse {
1083+ WorkspaceEdit : & lsproto.WorkspaceEdit {
1084+ Changes : & combined ,
1085+ },
1086+ }
1087+ }
1088+ return lsproto.RenameResponse {}
1089+ }
1090+
9651091func (s * Server ) handleDocumentHighlight (ctx context.Context , ls * ls.LanguageService , params * lsproto.DocumentHighlightParams ) (lsproto.DocumentHighlightResponse , error ) {
9661092 return ls .ProvideDocumentHighlights (ctx , params .TextDocument .Uri , params .Position )
9671093}
0 commit comments