Skip to content

Commit

Permalink
gopls/internal/golang: Implementations for func types
Browse files Browse the repository at this point in the history
This CL adds support to the Implementations query for function
types. The query relates two sets of locations:

  1. the "func" token of each function declaration (FuncDecl or
     FuncLit). These are analogous to declarations of concrete
     methods.

  2. uses of abstract functions:

     (a) the "func" token of each FuncType that is not part of
     Func{Decl,Lit}. These are analogous to interface{...} types.

     (b) the "(" paren of each dynamic call on a value of an
     abstract function type. These are analogous to references to
     interface method names, but no names are involved, which has
     historically made them hard to search for.

An Implementations query on a location in set 1 returns set 2,
and vice versa.

Only the local algorithm is implemented for now; the global
one (using an index analogous to methodsets) will follow.

This CL supersedes CL 448035 and CL 619515, both of which attempt
to unify the treatment of functions and interfaces in the methodsets
algorithm and in the index; but the two problems are not precisely
analogous, and I think we'll end up with more but simpler code
if we implement themn separately.

+ tests, docs, relnotes

Updates golang/go#56572

Change-Id: I18e1a7cc2f6c320112b9f3589323d04f9a52ef3c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/654556
Commit-Queue: Alan Donovan <[email protected]>
Reviewed-by: Jonathan Amsterdam <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
Auto-Submit: Alan Donovan <[email protected]>
  • Loading branch information
adonovan authored and gopherbot committed Mar 5, 2025
1 parent db6008c commit 25a90be
Show file tree
Hide file tree
Showing 6 changed files with 403 additions and 33 deletions.
22 changes: 21 additions & 1 deletion gopls/doc/features/navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ Client support:

The LSP
[`textDocument/implementation`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_implementation)
request queries the "implements" relation between interfaces and concrete types:
request queries the relation between abstract and concrete types and
their methods.

Interfaces and concrete types are matched using method sets:

- When invoked on a reference to an **interface type**, it returns the
location of the declaration of each type that implements
Expand All @@ -111,6 +114,17 @@ types with methods due to embedding) may be missing from the results.
but that is not consistent with the "scalable" gopls design.
-->

Functions, `func` types, and dynamic function calls are matched using signatures:

- When invoked on the `func` token of a **function definition**,
it returns the locations of the matching signature types
and dynamic call expressions.
- When invoked on the `func` token of a **signature type**,
it returns the locations of the matching concrete function definitions.
- When invoked on the `(` token of a **dynamic function call**,
it returns the locations of the matching concrete function
definitions.

If either the target type or the candidate type are generic, the
results will include the candidate type if there is any instantiation
of the two types that would allow one to implement the other.
Expand All @@ -120,6 +134,12 @@ types, without regard to consistency of substitutions across the
method set or even within a single method.
This may lead to occasional spurious matches.)

Since a type may be both a function type and a named type with methods
(for example, `http.HandlerFunc`), it may participate in both kinds of
implementation queries (by method-sets and function signatures).
Queries using method-sets should be invoked on the type or method name,
and queries using signatures should be invoked on a `func` or `(` token.

Client support:
- **VS Code**: Use [Go to Implementations](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-implementation) (`⌘F12`).
- **Emacs + eglot**: Use `M-x eglot-find-implementation`.
Expand Down
27 changes: 27 additions & 0 deletions gopls/doc/release/v0.19.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,33 @@

# New features

## "Implementations" supports signature types

The Implementations query reports the correspondence between abstract
and concrete types and their methods based on their method sets.
Now, it also reports the correspondence between function types,
dynamic function calls, and function definitions, based on their signatures.

To use it, invoke an Implementations query on the `func` token of the
definition of a named function, named method, or function literal.
Gopls reports the set of function signature types that abstract this
function, and the set of dynamic calls through values of such types.

Conversely, an Implementations query on the `func` token of a
signature type, or on the `(` paren of a dynamic function call,
reports the set of concrete functions that the signature abstracts
or that the call dispatches to.

Since a type may be both a function type and a named type with methods
(for example, `http.HandlerFunc`), it may participate in both kinds of
Implements queries (method-sets and function signatures).
Queries using method-sets should be invoked on the type or method name,
and queries using signatures should be invoked on a `func` or `(` token.

Only the local (same-package) algorithm is currently supported.
TODO: implement global.


## "Eliminate dot import" code action

This code action, available on a dotted import, will offer to replace
Expand Down
Loading

0 comments on commit 25a90be

Please sign in to comment.