@@ -33,6 +33,7 @@ import (
3333 "github.com/bufbuild/buf/private/bufpkg/bufcheck"
3434 "github.com/bufbuild/buf/private/bufpkg/bufmodule"
3535 "github.com/bufbuild/buf/private/pkg/storage"
36+ "github.com/bufbuild/protocompile/experimental/ast"
3637 "github.com/bufbuild/protocompile/experimental/ast/predeclared"
3738 "github.com/bufbuild/protocompile/experimental/incremental"
3839 "github.com/bufbuild/protocompile/experimental/incremental/queries"
@@ -315,47 +316,54 @@ func (f *file) IndexSymbols(ctx context.Context) {
315316 }
316317
317318 // TODO: this could use a refactor, probably.
318-
319+ //
319320 // Resolve all unresolved symbols from this file
320321 for _ , sym := range unresolved {
321- ref , ok := sym .kind .(* reference )
322- if ! ok {
323- // This shouldn't happen, logging a warning
324- f .lsp .logger .Warn (
325- "found unresolved non-reference symbol" ,
326- slog .String ("file" , f .uri .Filename ()),
327- slog .Any ("symbol" , sym ),
328- )
329- continue
330- }
331- file , ok := f .workspace .PathToFile ()[ref .def .Span ().Path ()]
332- if ! ok {
333- // Check current file
334- if ref .def .Span ().Path () != f .objectInfo .Path () {
335- // This can happen if this references a predeclared type or if the file we are
336- // checking has not indexed imports.
322+ switch kind := sym .kind .(type ) {
323+ case * reference :
324+ def := f .resolveASTDefinition (kind .def , kind .fullName )
325+ sym .def = def
326+ if def == nil {
327+ // In the case where the symbol is not resolved, we continue
337328 continue
338329 }
339- file = f
340- }
341- def , ok := file .referenceableSymbols [ref .fullName ]
342- if ! ok {
343- // This could happen in the case where we are in the cache for example, and we do not
344- // have access to a buildable workspace.
345- continue
346- }
347- sym .def = def
348- referenceable , ok := def .kind .(* referenceable )
349- if ! ok {
330+ referenceable , ok := def .kind .(* referenceable )
331+ if ! ok {
332+ // This shouldn't happen, logging a warning
333+ f .lsp .logger .Warn (
334+ "found non-referenceable symbol in index" ,
335+ slog .String ("file" , f .uri .Filename ()),
336+ slog .Any ("symbol" , def ),
337+ )
338+ continue
339+ }
340+ referenceable .references = append (referenceable .references , sym )
341+ case * option :
342+ def := f .resolveASTDefinition (kind .def , kind .defFullName )
343+ sym .def = def
344+ if def != nil {
345+ referenceable , ok := def .kind .(* referenceable )
346+ if ! ok {
347+ // This shouldn't happen, logging a warning
348+ f .lsp .logger .Warn (
349+ "found non-referenceable symbol in index" ,
350+ slog .String ("file" , f .uri .Filename ()),
351+ slog .Any ("symbol" , def ),
352+ )
353+ } else {
354+ referenceable .references = append (referenceable .references , sym )
355+ }
356+ }
357+ typeDef := f .resolveASTDefinition (kind .typeDef , kind .typeDefFullName )
358+ sym .typeDef = typeDef
359+ default :
350360 // This shouldn't happen, logging a warning
351361 f .lsp .logger .Warn (
352- "found non-referenceable symbol in index " ,
362+ "found unresolved non-reference and non-option symbol " ,
353363 slog .String ("file" , f .uri .Filename ()),
354- slog .Any ("symbol" , def ),
364+ slog .Any ("symbol" , sym ),
355365 )
356- continue
357366 }
358- referenceable .references = append (referenceable .references , sym )
359367 }
360368
361369 // Resolve all references outside of this file to symbols in this file
@@ -364,20 +372,28 @@ func (f *file) IndexSymbols(ctx context.Context) {
364372 continue // ignore self
365373 }
366374 for _ , sym := range file .referenceSymbols {
367- ref , ok := sym .kind .(* reference )
368- if ! ok {
375+ var fullName ir.FullName
376+ switch kind := sym .kind .(type ) {
377+ case * reference :
378+ if kind .def .Span ().Path () != f .objectInfo .Path () {
379+ continue
380+ }
381+ fullName = kind .fullName
382+ case * option :
383+ if kind .def .Span ().Path () != f .objectInfo .Path () {
384+ continue
385+ }
386+ fullName = kind .defFullName
387+ default :
369388 // This shouldn't happen, logging a warning
370389 f .lsp .logger .Warn (
371- "found unresolved non-reference symbol" ,
390+ "found unresolved non-reference and non-option symbol" ,
372391 slog .String ("file" , f .uri .Filename ()),
373392 slog .Any ("symbol" , sym ),
374393 )
375394 continue
376395 }
377- if ref .def .Span ().Path () != f .objectInfo .Path () {
378- continue
379- }
380- def , ok := f .referenceableSymbols [ref .fullName ]
396+ def , ok := f .referenceableSymbols [fullName ]
381397 if ! ok {
382398 // This shouldn't happen, if a symbol is pointing at this file, all definitions
383399 // should be resolved, logging a warning
@@ -524,12 +540,12 @@ func (f *file) irToSymbols(irSymbol ir.Symbol) ([]*symbol, []*symbol) {
524540 resolved = append (resolved , tag )
525541 unresolved = append (unresolved , f .messageToSymbols (irSymbol .AsMember ().Options ())... )
526542 case ir .SymbolKindExtension :
527- // TODO: we should figure out if we need to do any resolution here .
543+ // The symbol only includes the extension field name .
528544 ext := & symbol {
529545 ir : irSymbol ,
530546 file : f ,
531547 span : irSymbol .AsMember ().AST ().AsExtend ().Extendee .Span (),
532- kind : & static {
548+ kind : & referenceable {
533549 ast : irSymbol .AsMember ().AST (),
534550 },
535551 }
@@ -687,19 +703,15 @@ func (f *file) messageToSymbolsHelper(msg ir.MessageValue, index int, parents []
687703 // NOTE: no [ir.Symbol] for option elements
688704 file : f ,
689705 span : span ,
690- kind : & reference {
691- def : element .Field ().AST (),
692- fullName : element .Field ().FullName (),
706+ kind : & option {
707+ def : element .Field ().AST (),
708+ defFullName : element .Field ().FullName (),
709+ typeDef : element .Type ().AST (),
710+ typeDefFullName : element .Type ().FullName (),
693711 },
694- isOption : true ,
695712 }
696713 symbols = append (symbols , sym )
697714 if ! element .AsMessage ().IsZero () {
698- // For message value elements, we use the Type AST.
699- sym .kind = & reference {
700- def : element .Type ().AST (),
701- fullName : element .Type ().FullName (),
702- }
703715 symbols = append (symbols , f .messageToSymbolsHelper (element .AsMessage (), index + 1 , symbols )... )
704716 }
705717
@@ -725,11 +737,12 @@ func (f *file) messageToSymbolsHelper(msg ir.MessageValue, index int, parents []
725737 // NOTE: no [ir.Symbol] for option elements
726738 file : f ,
727739 span : component .Span (),
728- kind : & reference {
729- def : parentType .Type ().AST (),
730- fullName : parentType .Type ().FullName (),
740+ kind : & option {
741+ def : parentType .AsValue ().Field ().AST (),
742+ defFullName : parentType .AsValue ().Field ().FullName (),
743+ typeDef : parentType .Type ().AST (),
744+ typeDefFullName : parentType .Type ().FullName (),
731745 },
732- isOption : true ,
733746 }
734747 symbols = append (symbols , sym )
735748 }
@@ -741,6 +754,23 @@ func (f *file) messageToSymbolsHelper(msg ir.MessageValue, index int, parents []
741754 return symbols
742755}
743756
757+ // resolveASTDefinition is a helper for resolving the [ast.DeclDef] to the *[symbol], if
758+ // there is a matching indexed *[symbol].
759+ func (f * file ) resolveASTDefinition (def ast.DeclDef , defName ir.FullName ) * symbol {
760+ file , ok := f .workspace .PathToFile ()[def .Span ().Path ()]
761+ if ! ok {
762+ // Check current file
763+ if def .Span ().Path () != f .objectInfo .Path () {
764+ // If there is no file for the [ast.DeclDef] span, which can if it is a predeclared
765+ // type, for example, or if the file we are checking has not indexed imports, then
766+ // we return nil.
767+ return nil
768+ }
769+ file = f
770+ }
771+ return file .referenceableSymbols [defName ]
772+ }
773+
744774// SymbolAt finds a symbol in this file at the given cursor position, if one exists.
745775//
746776// Returns nil if no symbol is found.
@@ -766,7 +796,15 @@ func (f *file) SymbolAt(ctx context.Context, cursor protocol.Position) *symbol {
766796 }
767797 symbol = before
768798 }
769- f .lsp .logger .DebugContext (ctx , "symbol at" , slog .Int ("line" , int (cursor .Line )), slog .Int ("character" , int (cursor .Character )), slog .Any ("symbol" , symbol ))
799+ if symbol != nil {
800+ f .lsp .logger .DebugContext (
801+ ctx ,
802+ "symbol at" ,
803+ slog .Int ("line" , int (cursor .Line )),
804+ slog .Int ("character" , int (cursor .Character )),
805+ slog .Any ("symbol" , symbol ),
806+ )
807+ }
770808 return symbol
771809}
772810
0 commit comments