@@ -31,6 +31,7 @@ import (
31
31
"golang.org/x/tools/go/ast/astutil"
32
32
"golang.org/x/tools/gopls/internal/cache"
33
33
"golang.org/x/tools/gopls/internal/cache/metadata"
34
+ "golang.org/x/tools/gopls/internal/cache/parsego"
34
35
"golang.org/x/tools/gopls/internal/file"
35
36
"golang.org/x/tools/gopls/internal/fuzzy"
36
37
"golang.org/x/tools/gopls/internal/golang"
@@ -218,17 +219,16 @@ type completer struct {
218
219
// filename is the name of the file associated with this completion request.
219
220
filename string
220
221
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
223
224
224
225
// goversion is the version of Go in force in the file, as
225
226
// defined by x/tools/internal/versions. Empty if unknown.
226
227
// Since go1.22 it should always be known.
227
228
goversion string
228
229
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
232
232
233
233
// path is the path of AST nodes enclosing the position.
234
234
path []ast.Node
@@ -410,7 +410,7 @@ func (c *completer) setSurrounding(ident *ast.Ident) {
410
410
content : ident .Name ,
411
411
cursor : c .pos ,
412
412
// Overwrite the prefix only.
413
- tokFile : c .tokFile ,
413
+ tokFile : c .pgf . Tok ,
414
414
start : ident .Pos (),
415
415
end : ident .End (),
416
416
mapper : c .mapper ,
@@ -435,7 +435,7 @@ func (c *completer) getSurrounding() *Selection {
435
435
c .surrounding = & Selection {
436
436
content : "" ,
437
437
cursor : c .pos ,
438
- tokFile : c .tokFile ,
438
+ tokFile : c .pgf . Tok ,
439
439
start : c .pos ,
440
440
end : c .pos ,
441
441
mapper : c .mapper ,
@@ -609,8 +609,7 @@ func Completion(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
609
609
},
610
610
fh : fh ,
611
611
filename : fh .URI ().Path (),
612
- tokFile : pgf .Tok ,
613
- file : pgf .File ,
612
+ pgf : pgf ,
614
613
goversion : goversion ,
615
614
path : path ,
616
615
pos : pos ,
@@ -711,15 +710,15 @@ func Completion(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
711
710
// search queue or completion items directly for different completion contexts.
712
711
func (c * completer ) collectCompletions (ctx context.Context ) error {
713
712
// Inside import blocks, return completions for unimported packages.
714
- for _ , importSpec := range c .file .Imports {
713
+ for _ , importSpec := range c .pgf . File .Imports {
715
714
if ! (importSpec .Path .Pos () <= c .pos && c .pos <= importSpec .Path .End ()) {
716
715
continue
717
716
}
718
717
return c .populateImportCompletions (importSpec )
719
718
}
720
719
721
720
// 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 {
723
722
if comment .Pos () < c .pos && c .pos <= comment .End () {
724
723
c .populateCommentCompletions (comment )
725
724
return nil
@@ -749,7 +748,7 @@ func (c *completer) collectCompletions(ctx context.Context) error {
749
748
750
749
switch n := c .path [0 ].(type ) {
751
750
case * ast.Ident :
752
- if c .file .Name == n {
751
+ if c .pgf . File .Name == n {
753
752
return c .packageNameCompletions (ctx , c .fh .URI (), n )
754
753
} else if sel , ok := c .path [1 ].(* ast.SelectorExpr ); ok && sel .Sel == n {
755
754
// Is this the Sel part of a selector?
@@ -921,14 +920,14 @@ func (c *completer) populateImportCompletions(searchImport *ast.ImportSpec) erro
921
920
c .surrounding = & Selection {
922
921
content : content ,
923
922
cursor : c .pos ,
924
- tokFile : c .tokFile ,
923
+ tokFile : c .pgf . Tok ,
925
924
start : start ,
926
925
end : end ,
927
926
mapper : c .mapper ,
928
927
}
929
928
930
929
seenImports := make (map [string ]struct {})
931
- for _ , importSpec := range c .file .Imports {
930
+ for _ , importSpec := range c .pgf . File .Imports {
932
931
if importSpec .Path .Value == importPath {
933
932
continue
934
933
}
@@ -1024,7 +1023,7 @@ func (c *completer) populateCommentCompletions(comment *ast.CommentGroup) {
1024
1023
c .setSurroundingForComment (comment )
1025
1024
1026
1025
// 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 {
1028
1027
declLine := safetoken .Line (file , n .Pos ())
1029
1028
// if the comment is not in, directly above or on the same line as a declaration
1030
1029
if declLine != commentLine && declLine != commentLine + 1 &&
@@ -1080,8 +1079,33 @@ func (c *completer) populateCommentCompletions(comment *ast.CommentGroup) {
1080
1079
1081
1080
// collect receiver struct fields
1082
1081
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 )
1085
1109
if named != nil {
1086
1110
if recvStruct , ok := named .Underlying ().(* types.Struct ); ok {
1087
1111
for i := 0 ; i < recvStruct .NumFields (); i ++ {
@@ -1133,7 +1157,7 @@ func (c *completer) setSurroundingForComment(comments *ast.CommentGroup) {
1133
1157
c .surrounding = & Selection {
1134
1158
content : cursorComment .Text [start :end ],
1135
1159
cursor : c .pos ,
1136
- tokFile : c .tokFile ,
1160
+ tokFile : c .pgf . Tok ,
1137
1161
start : token .Pos (int (cursorComment .Slash ) + start ),
1138
1162
end : token .Pos (int (cursorComment .Slash ) + end ),
1139
1163
mapper : c .mapper ,
@@ -1437,7 +1461,7 @@ func (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {
1437
1461
return nil
1438
1462
}
1439
1463
1440
- goversion := c .pkg .TypesInfo ().FileVersions [c .file ]
1464
+ goversion := c .pkg .TypesInfo ().FileVersions [c .pgf . File ]
1441
1465
1442
1466
// Extract the package-level candidates using a quick parse.
1443
1467
var g errgroup.Group
@@ -1694,7 +1718,7 @@ func (c *completer) lexical(ctx context.Context) error {
1694
1718
// Make sure the package name isn't already in use by another
1695
1719
// object, and that this file doesn't import the package yet.
1696
1720
// 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 ())) {
1698
1722
seen [pkg .Name ()] = struct {}{}
1699
1723
obj := types .NewPkgName (0 , nil , pkg .Name (), pkg )
1700
1724
imp := & importInfo {
0 commit comments