Skip to content

Commit c7ccb51

Browse files
adonovangopherbot
authored andcommitted
gopls/doc/design: rewrite the architecture overview
Change-Id: Ice7f00c2109f999bcc3619acb979ae265caadf28 Reviewed-on: https://go-review.googlesource.com/c/tools/+/555977 Auto-Submit: Alan Donovan <[email protected]> Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 39a2545 commit c7ccb51

File tree

2 files changed

+162
-34
lines changed

2 files changed

+162
-34
lines changed

gopls/doc/design/architecture.svg

Lines changed: 1 addition & 0 deletions
Loading

gopls/doc/design/implementation.md

Lines changed: 161 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,173 @@
1-
# gopls implementation documentation
21

3-
This is not intended as a complete description of the implementation, for the most the part the package godoc, code comments and the code itself hold that.
4-
Instead this is meant to be a guide into finding parts of the implementation, and understanding some core concepts used throughout the implementation.
2+
# Gopls architecture
53

6-
## View/Session/Cache
4+
Last major update: Jan 16 2024
75

8-
Throughout the code there are references to these three concepts, and they build on each other.
6+
This doc presents a high-level overview of the structure of gopls to
7+
help new contributors find their way. It is not intended to be a
8+
complete description of the implementation, nor even of any key
9+
components; for that, the package documentation (linked below) and
10+
other comments within the code are a better guide.
911

10-
At the base is the *Cache*. This is the level at which we hold information that is global in nature, for instance information about the file system and its contents.
12+
The diagram below shows selected components of the gopls module and
13+
their relationship to each other according to the Go import graph.
14+
Tests and test infrastructure are not shown, nor are utility packages,
15+
nor packages from the [x/tools] module. For brevity, packages are
16+
referred to by their last segment, which is usually unambiguous.
1117

12-
Above that is the *Session*, which holds information for a connection to an editor. This layer hold things like the edited files (referred to as overlays).
18+
The height of each blob corresponds loosely to its technical depth.
19+
Some blocks are wide and shallow, such as [protocol], which declares
20+
Go types for the entire LSP protocol. Others are deep, such as [cache]
21+
and [source], as they contain a lot of dense logic and algorithms.
1322

14-
The top layer is called the *View*. This holds the configuration, and the mapping to configured packages.
23+
<!-- Source: https://docs.google.com/drawings/d/1CK6YSLt7G3svRoZf7skJI-lxRol2VI90YOxHcYS0DP4 -->
24+
![Gopls architecture](architecture.svg)
1525

16-
The purpose of this layering is to allow a single editor session to have multiple views active whilst still sharing as much information as possible for efficiency.
17-
In theory if only the View layer existed, the results would be identical, but slower and using more memory.
26+
Starting from the bottom, we'll describe the various components.
1827

19-
## Code location
28+
The lowest layer defines the request and response types of the
29+
Language Server Protocol:
2030

21-
gopls will be developed in the [x/tools] Go repository; the core packages are in [internal/lsp], and the binary and integration tests are located in [gopls].
31+
- The [protocol] package defines the standard protocol; it is mostly
32+
generated mechanically from the schema definition provided by
33+
Microsoft.
34+
The most important type is DocumentURI, which represents a `file:`
35+
URL that identifies a client editor document. It also provides
36+
`Mapper`, which maps between the different coordinate systems used
37+
for source positions: UTF-8, UTF-16, and token.Pos.
2238

23-
Below is a list of the core packages of gopls, and their primary purpose:
39+
- The [command] package defines Gopls's non-standard commands, which
40+
are all invoked through the `workspace/executeCommand` extension
41+
mechanism. These commands are typically returned by the server as
42+
continuations of Code Actions or Code Lenses; most clients do not
43+
construct calls to them directly.
2444

25-
Package | Description
26-
--- | ---
27-
[gopls] | the main binary, plugins and integration tests
28-
[internal/lsp] | the core message handling package
29-
[internal/lsp/cache] | the cache layer
30-
[internal/cmd] | the gopls command line layer
31-
[internal/debug] | features to aid in debugging gopls
32-
[internal/lsp/protocol] | the types of LSP request and response messages
33-
[internal/lsp/source] | the core feature implementations
34-
[internal/memoize] | a function invocation cache used to reduce the work done
35-
[internal/jsonrpc2] | an implementation of the JSON RPC2 specification
45+
The next layer defines a number of important and very widely used data structures:
3646

37-
[gopls]: https://github.com/golang/tools/tree/master/gopls
38-
[internal/jsonrpc2]: https://github.com/golang/tools/tree/master/internal/jsonrpc2
39-
[internal/lsp]: https://github.com/golang/tools/tree/master/gopls/internal/lsp
40-
[internal/lsp/cache]: https://github.com/golang/tools/tree/master/gopls/internal/lsp/cache
41-
[internal/cmd]: https://github.com/golang/tools/tree/master/gopls/internal/cmd
42-
[internal/debug]: https://github.com/golang/tools/tree/master/gopls/internal/lsp/debug
43-
[internal/lsp/source]: https://github.com/golang/tools/tree/master/gopls/internal/lsp/source
44-
[internal/memoize]: https://github.com/golang/tools/tree/master/internal/memoize
45-
[internal/lsp/protocol]: https://github.com/golang/tools/tree/master/gopls/internal/lsp/protocol
46-
[x/tools]: https://github.com/golang/tools
47+
- The [file] package defines the primary abstractions of a client
48+
file: its `Identity` (URI and content hash), and its `Handle` (which
49+
additionally provides the version and content of a particular
50+
snapshot of the file.
51+
52+
- The [parsego] package defines `File`, the parsed form of a Go source
53+
file, including its content, syntax tree, and coordinary mappings
54+
(Mapper and token.File). The package performs various kinds of tree
55+
repair to work around error-recovery shortcomings of the Go parser.
56+
57+
- The [metadata] package defines `Package`, an abstraction of the
58+
metadata of a Go package, similar to the output of `go list -json`.
59+
Metadata is produced from [go/packages], which takes
60+
care of invoking `go list`. (Users report that it works to some extent
61+
with a GOPACKAGESDRIVER for Bazel, though we maintain no tests for this
62+
scenario.)
63+
64+
The package also provides `Graph`, the complete import graph for a
65+
workspace; each graph node is a `Package`.
66+
67+
The [settings] layer defines the data structure (effectively a large
68+
tree) for gopls configuration options, along with its JSON encoding.
69+
70+
The [cache] layer is the largest and most complex component of gopls.
71+
It is concerned with state management, dependency analysis, and invalidation:
72+
the `Session` of communication with the client;
73+
the `Folder`s that the client has opened;
74+
the `View` of a particular workspace tree with particular build
75+
options;
76+
the `Snapshot` of the state of all files in the workspace after a
77+
particular edit operation;
78+
the contents of all files, whether saved to disk (`DiskFile`) or
79+
edited and unsaved (`Overlay`);
80+
the `Cache` of in-memory memoized computations,
81+
such as parsing go.mod files or build the symbol index;
82+
and the `Package`, which holds the results of type checking a package
83+
from Go syntax.
84+
85+
The cache layer depends on various auxiliary packages, including:
86+
87+
- The [filecache] package, which manages gopls' persistent, transactional,
88+
file-based key/value store.
89+
90+
- The [xrefs], [methodsets], and [typerefs] packages define algorithms
91+
for constructing indexes of information derived from type-checking,
92+
and for encoding and decoding these serializable indexes in the file
93+
cache.
94+
95+
Together these packages enable the fast restart, reduced memory
96+
consumption, and synergy across processes that were delivered by the
97+
v0.12 redesign and described in ["Scaling gopls for the growing Go
98+
ecosystem"](https://go.dev/blog/gopls-scalability).
99+
100+
The cache also defines gopls's [go/analysis] driver, which runs
101+
modular analysis (similar to `go vet`) across the workspace.
102+
Gopls also includes a number of analysis passes that are not part of vet.
103+
104+
The next layer defines four packages, each for handling files in a
105+
particular language:
106+
[mod] for go.mod files;
107+
[work] for go.work files;
108+
[template] for files in `text/template` syntax; and
109+
[source], for files in Go itself.
110+
This package, by far the largest, provides the main features of gopls:
111+
navigation, analysis, and refactoring of Go code.
112+
As most users imagine it, this package _is_ gopls.
113+
114+
The [server] package defines the LSP service implementation, with one
115+
handler method per LSP request type. Each handler switches on the type
116+
of the file and dispatches to one of the four language-specific
117+
packages.
118+
119+
The [lsprpc] package connects the service interface to our [JSON RPC](jsonrpc2)
120+
server.
121+
122+
Bear in mind that the diagram is a dependency graph, a "static"
123+
viewpoint of the program's structure. A more dynamic viewpoint would
124+
order the packages based on the sequence in which they are encountered
125+
during processing of a particular request; in such a view, the bottom
126+
layer would represent the "wire" (protocol and command), the next
127+
layer up would hold the RPC-related packages (lsprpc and server), and
128+
features (e.g. source, mod, work, template) would be at the top.
129+
130+
<!--
131+
A dynamic view would be an interesting topic for another article.
132+
This slide deck [requires Google network]
133+
The Life of a (gopls) Query (Oct 2021)
134+
https://docs.google.com/presentation/d/1c8XJaIldzii-F3YvEOPWHK_MQJ_o8ua5Bct1yDa3ZlU
135+
provides useful (if somewhat out of date) information.
136+
-->
137+
138+
The [cmd] package defines the command-line interface of the `gopls`
139+
command, around which gopls's main package is just a trivial wrapper.
140+
It is usually run without arguments, causing it to start a server and
141+
listen indefinitely.
142+
It also provides a number of subcommands that start a server, make a
143+
single request to it, and exit, providing traditional batch-command
144+
access to server functionality. These subcommands are primarily
145+
provided as a debugging aid (but see
146+
[#63693](https://github.com/golang/go/issues/63693)).
147+
148+
[cache]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp/cache
149+
[cmd]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cmd
150+
[command]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp/command
151+
[debug]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp/debug
152+
[file]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/file
153+
[filecache]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/filecache
154+
[go/analysis]: https://pkg.go.dev/golang.org/x/tools@master/go/analysis
155+
[go/packages]: https://pkg.go.dev/golang.org/x/tools@master/go/packages
156+
[gopls]: https://pkg.go.dev/golang.org/x/tools/gopls@master
157+
[jsonrpc2]: https://pkg.go.dev/golang.org/x/tools@master/internal/jsonrpc2
158+
[lsp]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp
159+
[lsprpc]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp/lsprpc
160+
[memoize]: https://github.com/golang/tools/tree/master/internal/memoize
161+
[metadata]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/metadata
162+
[methodsets]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp/cache/methodsets
163+
[mod]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/mod
164+
[parsego]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp/cache/parsego
165+
[protocol]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp/protocol
166+
[server]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/server
167+
[settings]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/settings
168+
[source]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp/source
169+
[template]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/template
170+
[typerefs]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp/cache/typerefs
171+
[work]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/work
172+
[x/tools]: https://github.com/golang/tools@master
173+
[xrefs]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsp/cache/xrefs

0 commit comments

Comments
 (0)