blob: 2bf4411d29273daff60c841a5383c86d39298b63 [file] [log] [blame] [view]
Alan Donovan799a4712024-05-03 18:53:37 -04001# Gopls: Navigation features
2
3This page documents gopls features for navigating your source code.
4
5## Definition
6
7The LSP [`textDocument/definition`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition)
8request returns the location of the declaration of the symbol under the cursor.
9Most editors provide a command to navigate directly to that location.
10
11A definition query also works in these unexpected places:
12
13- On an **import path**, it returns the list of locations, of
14 each package declaration in the files of the imported package.
15- On a **package declaration**, it returns the location of
16 the package declaration that provides the documentation of that package.
17- On a symbol in a **[`go:linkname` directive](https://pkg.go.dev/cmd/compile)**,
18 it returns the location of that symbol's declaration.
19- On a **[doc link](https://tip.golang.org/doc/comment#doclinks)**, it returns
20 (like [`hover`](passive.md#Hover)) the location of the linked symbol.
21- On a file name in a **[`go:embed` directive](https://pkg.go.dev/embed)**,
22 it returns the location of the embedded file.
23
24<!-- On a built-in symbol such as `append` or `unsafe.Pointer`, `definition` reports
25the location of the declaration in the builtin or unsafe pseudo-packages,
26which are just documentation. -->
27
28Client support:
29- **VS Code**: Use [Go to Definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition) (`F12` or `⌘`-click).
30 If the cursor is already at the declaration, the request is instead interpreted as "Go to References".
31- **Emacs + eglot**: use [`M-x xref-find-definitions`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html).
32- **Vim + coc.nvim**: ??
33- **CLI**: `gopls definition file.go:#offset`
34
35## References
36
37The LSP [`textDocument/references`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_references)
38request returns the locations of all identifiers that refers to the symbol under the cursor.
39
40The references algorithm handles various parts of syntax as follows:
41
42- The references to a **symbol** report all uses of that symbol.
43 In the case of exported this may include locations in other packages.
44- The references to a **package declaration** are all the
45 direct imports of the package, along with all the other package
46 declarations in the same package.
47- It is an error to request the references to a **built-in symbol**
48 such as `int` or `append`,
49 as they are presumed too numerous to be of interest.
50- The references to an **interface method** include references to
51 concrete types that implement the interface. Similarly, the
52 references to a **method of a concrete type** include references to
53 corresponding interface methods.
54- An **embedded field** `T` in a struct type such as `struct{T}` is
55 unique in Go in that it is both a reference (to a type) and a
56 definition (of a field).
57 The `references` operation reports only the references to it [as a field](golang/go#63521).
58 To find references to the type, jump to the type declararation first.
59
60Be aware that a references query returns information only about the
61build configuration used to analyze the selected file, so if you ask
62for the references to a symbol defined in `foo_windows.go`, the result
63will never include the file `bar_linux.go`, even if that file refers
64to a symbol of the same name; see golang/go#65755.
65
66Clients can request that the the declaration be included among the
67references; most do.
68
69Client support:
70- **VS Code**: Use [`Go to References`](https://code.visualstudio.com/docs/editor/editingevolved#_peek) to quickly "peek" at the references,
71 or `Find all References` to open the references panel.
72- **Emacs + eglot**: Via [`xref` package](https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html): use `M-x xref-find-references`.
73- **Vim + coc.nvim**: ??
74- **CLI**: `gopls references file.go:#offset`
75
76## Implementation
77
78The LSP
79[`textDocument/implementation`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_implementation)
80request queries the "implements" relation between interfaces and concrete types:
81
82- When invoked on a reference to an **interface type**, it returns the
83 location of the declaration of each type that implements
84 the interface.
85- When invoked on a **concrete type**,
86 it returns the locations of the matching interface types.
87- When invoked on an **interface method**, it returns the corresponding
88 methods of the types that satisfy the interface.
89- When invoked on a **concrete method**,
90 it returns the locations of the matching interface methods.
91
92Only non-trivial interfaces are considered; no implementations are
93reported for type `any`.
94
95Within the same package, all matching types/methods are reported.
96However, across packages, only exported package-level types and their
97methods are reported, so local types (whether interfaces, or struct
98types with methods due to embedding) may be missing from the results.
99<!-- Reason: assignability of local types such as I and J defined thus:
100 package p; func P() {type I interface {...}}
101 package q; func Q() {type J struct {...}}
102 depends on them both being in the same types.Importer "realm",
103 but that is not consistent with the "scalable" gopls design.
104-->
105
106Generic types are currently not fully supported; see golang/go#59224.
107
108Client support:
109- **VS Code**: Use [Go to Implementations](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-implementation) (`⌘F12`).
110- **Emacs + eglot**: Use `M-x eglot-find-implementation`.
111- **Vim + coc.nvim**: ??
112- **CLI**: `gopls implementation file.go:#offset`
113
114
115## TypeDefinition
116
117The LSP
118[`textDocument/typeDefinition`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_typeDefinition)
119request returns the location of the type of the selected symbol.
120
121For example, if the selection is the name `buf` of a local variable of
122type `*bytes.Buffer`, a `typeDefinition` query will return the
123location of the type `bytes.Buffer`.
124Clients typically navigate to that location.
125
126Type constructors such as pointer, array, slice, channel, and map are
127stripped off the selected type in the search for a named type. For
128example, if x is of type `chan []*T`, the reported type definition
129will be that of `T`.
130Similarly, if the symbol's type is a function with one "interesting"
131(named, non-`error`) result type, the function's result type is used.
132
133Gopls currently requires that a `typeDefinition` query be applied to a
134symbol, not to an arbitrary expression; see golang/go#67890 for
135potential extensions of this functionality.
136<!-- e.g. selecting a struct field, package name, or other piece of syntax. -->
137
138Client support:
139- **VS Code**: Use [Go to Type Definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-implementation).
140- **Emacs + eglot**: Use `M-x eglot-find-typeDefinition`.
141- **Vim + coc.nvim**: ??
142- **CLI**: not supported
143
144## DocumentSymbol
145
146The `textDocument/documentSymbol` LSP query reports the list of
147top-level declarations in this file. Clients may use this information
148to present an overview of the file, and an index for faster navigation.
149
150Gopls responds with the newer
151[`DocumentSymbol`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbol)
152type if the client indicates
153[`hierarchicalDocumentSymbolSupport`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbolClientCapabilities);
154otherwise it returns the older
155[`SymbolInformation`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#symbolInformation).
156
157Client support:
158- **VS Code**: Use the [Outline view](https://code.visualstudio.com/docs/getstarted/userinterface#_outline-view) for navigation.
159- **Emacs + eglot**: Use [`M-x imenu`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Imenu.html#Imenu) to jump to a symbol.
160- **Vim + coc.nvim**: ??
161- **CLI**: `gopls links file.go`
162
163
164## Symbol
165
166The
167[`workspace/symbol`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_symbol)
168LSP query searches an index of all the symbols in the workspace.
169
170The default symbol matching algorithm (`fastFuzzy`), inspired by the
171popular fuzzy matcher [FZF](https://github.com/junegunn/fzf), attempts
172a variety of inexact matches to correct for misspellings in your
173query. For example, it considers `DocSym` a match for `DocumentSymbol`.
174
175<!--
176It also supports the following special characters within queries:
177
178| Character | Usage | Match |
179| --------- | --------- | ------------ |
180| `'` | `'abc` | exact |
181| `^` | `^printf` | exact prefix |
182| `$` | `printf$` | exact suffix |
183
184However, VS Code does its own fuzzy matching afterward, so these
185aren't effective in that client.
186-->
187
188TODO: screenshot
189
190Settings:
191- The [`symbolMatcher`](../settings.md#symbolMatcher) setting controls the algorithm used for symbol matching.
192- The [`symbolStyle`](../settings.md#symbolStyle) setting controls how symbols are qualified in symbol responses.
193- The [`symbolScope`](../settings.md#symbolScope) setting determines the scope of the query.
194- The [`directoryFilters`](../settings.md#directoryFilters) setting specifies directories to be excluded from the search.
195
196Client support:
197- **VS Code**: Use ⌘T to open [Go to Symbol](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-symbol) with workspace scope. (Alternatively, use Ctrl-Shift-O, and add a `@` prefix to search within the file or a `#` prefix to search throughout the workspace.)
198- **Emacs + eglot**: Use [`M-x xref-find-apropos`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Looking-Up-Identifiers.html) to show symbols that match a search term.
199- **Vim + coc.nvim**: ??
200- **CLI**: `gopls links file.go`
201
202
203## SelectionRange
204
205The
206[`textDocument/selectionRange`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_selectionRange)
207LSP query returns information about the lexical extent of each piece
208of syntax enclosing the current selection.
209Clients may use it to provide an operation to expand the selection
210to successively larger expressions.
211
212Client support:
213- **VSCode**: Use `⌘⇧^→` to expand the selection or `⌘⇧^←` to contract it again; watch this [video](https://www.youtube.com/watch?v=dO4SGAMl7uQ).
214- **Emacs + eglot**: Not standard. Use `M-x eglot-expand-selection` defined in [this configuration snippet](https://github.com/joaotavora/eglot/discussions/1220#discussioncomment-9321061).
215- **Vim + coc.nvim**: ??
216- **CLI**: not supported
217
218## CallHierarchy
219
220The LSP CallHierarchy mechanism consists of three queries that
221together enable clients to present a hierarchical view of a portion of
222the static call graph:
223
224- [`textDocument/prepareCallHierarchy`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_prepareCallHierarchy) returns a list of [items](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyItem) for a given position, each representing a named function or method enclosing the position;
225- [`callHierarchyItem/incomingCalls`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchy_incomingCalls) returns the set of call sites that call the selected item; and
226- [`callHierarchy/outgoingCalls`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchy_incomingCalls) returns the set of functions called by the selected item.
227
228Invoke the command while selecting the name in a function declaration.
229
230Dynamic calls are not included, because it is not analytically
231practical to detect them. So, beware that the results may not be
232exhaustive, and perform a [References](#references) query if necessary.
233
234The hierarchy does not consider a nested function distinct from its
235enclosing named function. (Without the ability to detect dynamic
236calls, it would make little sense do so.)
237
238The screenshot below shows the outgoing call tree rooted at `f`. The
239tree has been expanded to show a path from `f` to the `String` method
240of `fmt.Stringer` through the guts of `fmt.Sprint:`
241
242<img title="Outgoing calls of f" src="../assets/outgoingcalls.png" width="640">
243
244Caveats:
245- In some cases dynamic function calls are (erroneously) included in
246 the output; see golang/go#68153.
247
248Client support:
249- **VS Code**: `Show Call Hierarchy` menu item (`⌥⇧H`) opens [Call hierarchy view](https://code.visualstudio.com/docs/cpp/cpp-ide#_call-hierarchy) (note: docs refer to C++ but the idea is the same for Go).
250- **Emacs + eglot**: Not standard; install with `(package-vc-install "https://github.com/dolmens/eglot-hierarchy")`. Use `M-x eglot-hierarchy-call-hierarchy` to show the direct incoming calls to the selected function; use a prefix argument (`C-u`) to show the direct outgoing calls. There is no way to expand the tree.
251- **CLI**: `gopls call_hierarchy file.go:#offset` shows outgoing and incoming calls.