diff --git a/gopls/internal/golang/type_definition.go b/gopls/internal/golang/type_definition.go
index 3de9230..51f8126 100644
--- a/gopls/internal/golang/type_definition.go
+++ b/gopls/internal/golang/type_definition.go
@@ -31,9 +31,9 @@
if err != nil {
return nil, err
}
- cur, ok := pgf.Cursor.FindByPos(start, end)
- if !ok {
- return nil, fmt.Errorf("no enclosing syntax") // can't happen
+ cur, _, _, err := astutil.Select(pgf.Cursor, start, end)
+ if err != nil {
+ return nil, err
}
// Find innermost enclosing expression that has a type.
diff --git a/internal/astutil/util.go b/internal/astutil/util.go
index 6986a51..a022995 100644
--- a/internal/astutil/util.go
+++ b/internal/astutil/util.go
@@ -178,6 +178,10 @@
//
// Select returns the enclosing BlockStmt, the f() CallExpr, and the g() CallExpr.
//
+// If the selection does not wholly enclose any nodes (for example, a
+// point selection at a token position, or a selection of only whitespace),
+// enclosing is returned with zero start and end Cursors.
+//
// Callers that require exactly one syntax tree (e.g. just f() or just
// g()) should check that the returned start and end nodes are
// identical.
@@ -190,7 +194,7 @@
func Select(curFile inspector.Cursor, start, end token.Pos) (_enclosing, _start, _end inspector.Cursor, _ error) {
curEnclosing, ok := curFile.FindByPos(start, end)
if !ok {
- return noCursor, noCursor, noCursor, fmt.Errorf("invalid selection")
+ return NoCursor, NoCursor, NoCursor, fmt.Errorf("invalid selection")
}
// Find the first and last node wholly within the (start, end) range.
@@ -214,7 +218,11 @@
}
}
if !CursorValid(curStart) {
- return noCursor, noCursor, noCursor, fmt.Errorf("no syntax selected")
+ // The selection is valid (inside curEnclosing) but contains no
+ // complete nodes. This happens for point selections (start == end),
+ // or selections covering only tokens/whitespace.
+ // Return the enclosing node so the caller can still use the context.
+ return curEnclosing, NoCursor, NoCursor, nil
}
return curEnclosing, curStart, curEnd, nil
}
@@ -230,4 +238,8 @@
return cur.Inspector() != nil
}
-var noCursor inspector.Cursor
+// NoCursor is the zero value of a Cursor, representing an invalid or
+// absent node. It is returned by functions like Select when no syntax
+// node matches the query. Callers may compare a Cursor against NoCursor
+// to check if it is valid.
+var NoCursor inspector.Cursor