Skip to content

gopls/hover: show named func type doc when hovering over func literal#633

Closed
abhay1999 wants to merge 4 commits intogolang:masterfrom
abhay1999:gopls-hover-funclittype
Closed

gopls/hover: show named func type doc when hovering over func literal#633
abhay1999 wants to merge 4 commits intogolang:masterfrom
abhay1999:gopls-hover-funclittype

Conversation

@abhay1999
Copy link
Copy Markdown
Contributor

Problem

When a func literal is implicitly converted to a named function type
(e.g. fs.WalkDirFunc), hovering over its func keyword only showed
the anonymous signature — not the documentation for the named type
that the user likely wants.

For example, hovering over func in:

filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
    ...
})

previously showed:

func(path string, d fs.DirEntry, err error) error

The user had to first jump to filepath.WalkDir's definition, then
navigate to fs.WalkDirFunc, just to see its documentation.

Fix

When cur.Node() is *ast.FuncType with the cursor at the func
token and the parent is a *ast.FuncLit, the new hoverFuncLit
function:

  1. Calls typesutil.TypesFromContext on the func literal's cursor to
    find the named function type the literal must satisfy.
  2. Loads the declaring package via NarrowestDeclaringPackage and
    extracts the doc comment and signature.
  3. Returns a hoverResult with the named type's documentation,
    signature, SymbolName, and a pkg.go.dev link.

If no named type is found (e.g. f := func(x int) int { ... }), it
falls back to the existing behavior of showing the anonymous type.

Note: FindByPos at a FuncLit's func token returns the inner
*ast.FuncType node (not *ast.FuncLit), so the code checks the
parent node to detect the FuncLit context.

Test

Added gopls/internal/test/marker/testdata/hover/funclittype.txt with:

  • A named-type case (WalkFunc): hover shows the doc + link.
  • An anonymous-type case: hover falls back to the type string.

Fixes golang/go#76191

…re a declaration

When a user places the cursor immediately after "//" (with no trailing
space) on a line directly above a declaration, gopls already suggests the
declaration name as a completion candidate. However the suggested insert
text lacked the conventional space, producing "//Name" instead of the
proper Go doc comment form "// Name".

Detect this case in populateCommentCompletions (cursor at slash+2 with
comment text exactly "//") and set a new commentNeedsLeadingSpace flag on
the completionContext. item() checks the flag and prepends a space to the
insert text (and snippet), so accepting the completion yields "// Name".

A marker test is added to comment.txt that asserts the candidate appears
when the cursor is right after "//", above a function declaration.

Fixes golang/go#76374
…es after //

Previously, commentNeedsLeadingSpace was only set when the cursor was
exactly at slash+2 and the comment text was exactly "//". This missed
the case where the user had partially typed an identifier (e.g. "//Foo")
and triggered completion mid-word.

Fix: use c.surrounding.start (the start of the edit range, set by
setSurroundingForComment) instead. If the edit range starts at slash+2,
there is no space between "//" and the identifier being replaced, so
completions should prepend a space.

Also add a marker test for the partial-prefix case.
implFuncs handles the "(" paren of a CallExpr as an entry point for
finding dynamic function-call implementations. When the call is not
dynamic (e.g. err.Error(), len(""), or a type conversion), it
previously returned a hard error "not a dynamic function call" which
blocked the method-sets fallback and produced a confusing message.

Change the non-dynamic case to return errNotHandled instead, which
lets the caller fall through to the regular method-sets algorithm.
That algorithm also cannot find an implementation from a bare "(" (it
needs an identifier), so it returns "no identifier found" — a standard
error that editors handle gracefully — rather than a gopls-specific
message.

The fix is consistent with the treatment of "(" in
textDocument/references (#76872) and preserves the intended separation
between dynamic-function-type queries (keyed by "func" or "(") and
interface-method queries (keyed by the method name identifier).

Update the affected marker tests to expect "no identifier found".

Fixes golang/go#77784
When a func literal is implicitly converted to a named function type
(e.g. fs.WalkDirFunc), hovering over its "func" keyword now shows the
documentation and signature of that named type, with a link to pkg.go.dev.

Previously, hovering over "func" in:

    filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
        ...
    })

showed only the anonymous signature "func(path string, d fs.DirEntry,
err error) error". Now it shows the docs for fs.WalkDirFunc, which is
often the information the user actually wants.

Implementation:
- Detect the case in the hover switch: when cur.Node() is *ast.FuncType
  and the cursor is at the "func" token and the parent is a *ast.FuncLit.
- Use typesutil.TypesFromContext to find the named function type the
  literal must satisfy.
- Load the declaring package and build a hoverResult with the named
  type's documentation, signature, and pkg.go.dev link.
- If no named type is found, fall back to the existing anonymous-type
  hover behavior.

Add a marker test in hover/funclittype.txt covering both cases.

Fixes golang/go#76191
@abhay1999
Copy link
Copy Markdown
Contributor Author

Replacing with a clean PR that contains only this commit (previous PR had unrelated commits from other branches).

@abhay1999 abhay1999 closed this Apr 8, 2026
@ccoVeille
Copy link
Copy Markdown

See #634 then

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

x/tools/gopls: Hover: for func literal implicitly converted to named func type, show doc for that type

2 participants