@@ -31,6 +31,7 @@ import (
3131 "golang.org/x/tools/go/ast/astutil"
3232 "golang.org/x/tools/gopls/internal/cache"
3333 "golang.org/x/tools/gopls/internal/cache/metadata"
34+ "golang.org/x/tools/gopls/internal/cache/parsego"
3435 "golang.org/x/tools/gopls/internal/file"
3536 "golang.org/x/tools/gopls/internal/fuzzy"
3637 "golang.org/x/tools/gopls/internal/golang"
@@ -218,17 +219,16 @@ type completer struct {
218219 // filename is the name of the file associated with this completion request.
219220 filename string
220221
221- // file is the AST of the file associated with this completion request.
222- file * ast .File
222+ // pgf is the AST of the file associated with this completion request.
223+ pgf * parsego .File // debugging
223224
224225 // goversion is the version of Go in force in the file, as
225226 // defined by x/tools/internal/versions. Empty if unknown.
226227 // Since go1.22 it should always be known.
227228 goversion string
228229
229- // (tokFile, pos) is the position at which the request was triggered.
230- tokFile * token.File
231- pos token.Pos
230+ // pos is the position at which the request was triggered.
231+ pos token.Pos
232232
233233 // path is the path of AST nodes enclosing the position.
234234 path []ast.Node
@@ -410,7 +410,7 @@ func (c *completer) setSurrounding(ident *ast.Ident) {
410410 content : ident .Name ,
411411 cursor : c .pos ,
412412 // Overwrite the prefix only.
413- tokFile : c .tokFile ,
413+ tokFile : c .pgf . Tok ,
414414 start : ident .Pos (),
415415 end : ident .End (),
416416 mapper : c .mapper ,
@@ -435,7 +435,7 @@ func (c *completer) getSurrounding() *Selection {
435435 c .surrounding = & Selection {
436436 content : "" ,
437437 cursor : c .pos ,
438- tokFile : c .tokFile ,
438+ tokFile : c .pgf . Tok ,
439439 start : c .pos ,
440440 end : c .pos ,
441441 mapper : c .mapper ,
@@ -609,8 +609,7 @@ func Completion(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
609609 },
610610 fh : fh ,
611611 filename : fh .URI ().Path (),
612- tokFile : pgf .Tok ,
613- file : pgf .File ,
612+ pgf : pgf ,
614613 goversion : goversion ,
615614 path : path ,
616615 pos : pos ,
@@ -711,15 +710,15 @@ func Completion(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
711710// search queue or completion items directly for different completion contexts.
712711func (c * completer ) collectCompletions (ctx context.Context ) error {
713712 // Inside import blocks, return completions for unimported packages.
714- for _ , importSpec := range c .file .Imports {
713+ for _ , importSpec := range c .pgf . File .Imports {
715714 if ! (importSpec .Path .Pos () <= c .pos && c .pos <= importSpec .Path .End ()) {
716715 continue
717716 }
718717 return c .populateImportCompletions (importSpec )
719718 }
720719
721720 // Inside comments, offer completions for the name of the relevant symbol.
722- for _ , comment := range c .file .Comments {
721+ for _ , comment := range c .pgf . File .Comments {
723722 if comment .Pos () < c .pos && c .pos <= comment .End () {
724723 c .populateCommentCompletions (comment )
725724 return nil
@@ -749,7 +748,7 @@ func (c *completer) collectCompletions(ctx context.Context) error {
749748
750749 switch n := c .path [0 ].(type ) {
751750 case * ast.Ident :
752- if c .file .Name == n {
751+ if c .pgf . File .Name == n {
753752 return c .packageNameCompletions (ctx , c .fh .URI (), n )
754753 } else if sel , ok := c .path [1 ].(* ast.SelectorExpr ); ok && sel .Sel == n {
755754 // Is this the Sel part of a selector?
@@ -921,14 +920,14 @@ func (c *completer) populateImportCompletions(searchImport *ast.ImportSpec) erro
921920 c .surrounding = & Selection {
922921 content : content ,
923922 cursor : c .pos ,
924- tokFile : c .tokFile ,
923+ tokFile : c .pgf . Tok ,
925924 start : start ,
926925 end : end ,
927926 mapper : c .mapper ,
928927 }
929928
930929 seenImports := make (map [string ]struct {})
931- for _ , importSpec := range c .file .Imports {
930+ for _ , importSpec := range c .pgf . File .Imports {
932931 if importSpec .Path .Value == importPath {
933932 continue
934933 }
@@ -1024,7 +1023,7 @@ func (c *completer) populateCommentCompletions(comment *ast.CommentGroup) {
10241023 c .setSurroundingForComment (comment )
10251024
10261025 // Using the next line pos, grab and parse the exported symbol on that line
1027- for _ , n := range c .file .Decls {
1026+ for _ , n := range c .pgf . File .Decls {
10281027 declLine := safetoken .Line (file , n .Pos ())
10291028 // if the comment is not in, directly above or on the same line as a declaration
10301029 if declLine != commentLine && declLine != commentLine + 1 &&
@@ -1080,8 +1079,33 @@ func (c *completer) populateCommentCompletions(comment *ast.CommentGroup) {
10801079
10811080 // collect receiver struct fields
10821081 if node .Recv != nil {
1083- sig := c .pkg .TypesInfo ().Defs [node .Name ].(* types.Func ).Signature ()
1084- _ , named := typesinternal .ReceiverNamed (sig .Recv ()) // may be nil if ill-typed
1082+ obj := c .pkg .TypesInfo ().Defs [node .Name ]
1083+ switch obj .(type ) {
1084+ case nil :
1085+ report := func () {
1086+ bug .Reportf ("missing def for func %s" , node .Name )
1087+ }
1088+ // Debugging golang/go#71273.
1089+ if ! slices .Contains (c .pkg .CompiledGoFiles (), c .pgf ) {
1090+ if c .snapshot .View ().Type () == cache .GoPackagesDriverView {
1091+ report ()
1092+ } else {
1093+ report ()
1094+ }
1095+ } else {
1096+ report ()
1097+ }
1098+ continue
1099+ case * types.Func :
1100+ default :
1101+ bug .Reportf ("unexpected func obj type %T for %s" , obj , node .Name )
1102+ }
1103+ sig := obj .(* types.Func ).Signature ()
1104+ recv := sig .Recv ()
1105+ if recv == nil {
1106+ continue // may be nil if ill-typed
1107+ }
1108+ _ , named := typesinternal .ReceiverNamed (recv )
10851109 if named != nil {
10861110 if recvStruct , ok := named .Underlying ().(* types.Struct ); ok {
10871111 for i := 0 ; i < recvStruct .NumFields (); i ++ {
@@ -1133,7 +1157,7 @@ func (c *completer) setSurroundingForComment(comments *ast.CommentGroup) {
11331157 c .surrounding = & Selection {
11341158 content : cursorComment .Text [start :end ],
11351159 cursor : c .pos ,
1136- tokFile : c .tokFile ,
1160+ tokFile : c .pgf . Tok ,
11371161 start : token .Pos (int (cursorComment .Slash ) + start ),
11381162 end : token .Pos (int (cursorComment .Slash ) + end ),
11391163 mapper : c .mapper ,
@@ -1437,7 +1461,7 @@ func (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {
14371461 return nil
14381462 }
14391463
1440- goversion := c .pkg .TypesInfo ().FileVersions [c .file ]
1464+ goversion := c .pkg .TypesInfo ().FileVersions [c .pgf . File ]
14411465
14421466 // Extract the package-level candidates using a quick parse.
14431467 var g errgroup.Group
@@ -1694,7 +1718,7 @@ func (c *completer) lexical(ctx context.Context) error {
16941718 // Make sure the package name isn't already in use by another
16951719 // object, and that this file doesn't import the package yet.
16961720 // TODO(adonovan): what if pkg.Path has vendor/ prefix?
1697- if _ , ok := seen [pkg .Name ()]; ! ok && pkg != c .pkg .Types () && ! alreadyImports (c .file , golang .ImportPath (pkg .Path ())) {
1721+ if _ , ok := seen [pkg .Name ()]; ! ok && pkg != c .pkg .Types () && ! alreadyImports (c .pgf . File , golang .ImportPath (pkg .Path ())) {
16981722 seen [pkg .Name ()] = struct {}{}
16991723 obj := types .NewPkgName (0 , nil , pkg .Name (), pkg )
17001724 imp := & importInfo {
0 commit comments