1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
# Gopls: Diagnostics
Gopls continuously annotates all your open files of source code with a
variety of diagnostics. Every time you edit a file or make a
configuration change, gopls asynchronously recomputes these
diagnostics and sends them to the client using the LSP
[`publishDiagnostics`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_publishDiagnostics)
notification, giving you real-time feedback that reduces the cost of
common mistakes.
Diagnostics come from two main sources: compilation errors and analysis findings.
- **Compilation errors** are those that you would obtain from running `go
build`. Gopls doesn't actually run the compiler; that would be too
slow. Instead it runs `go list` (when needed) to compute the
metadata of the compilation, then processes those packages in a similar
manner to the compiler front-end: reading, scanning, and parsing the
source files, then type-checking them. Each of these steps can
produce errors that gopls will surface as a diagnostic.
The `source` field of the LSP `Diagnostic` record indicates where
the diagnostic came from: those with source `"go list"` come from
the `go list` command, and those with source `"compiler"` come from
gopls' parsing or type checking phases, which are similar to those
used in the Go compiler.

The example above shows a `string + int` addition, causes the type
checker to report a `MismatchedTypes` error. The diagnostic contains
a link to the documentation about this class of type error.
- **Analysis findings** come from the [**Go analysis
framework**](https://golang.org/x/tools/go/analysis), the system
used by `go vet` to apply a variety of additional static checks to
your Go code. The best-known example is the [`printf`
analyzer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/printf),
which reports calls to [`fmt.Printf`](https://pkg.go.dev/fmt#Printf)
where the format "verb" doesn't match the argument, such as
`fmt.Printf("%d", "three")`.
Gopls provides dozens of analyzers aggregated from a variety of
suites; see [Analyzers](../analyzers.md) for the complete list. The
`source` field of each diagnostic produced by an analyzer records
the name of the analyzer that produced it.

The example above shows a `printf` formatting mistake. The diagnostic contains
a link to the documentation for the `printf` analyzer.
## Recomputation of diagnostics
Diagnostics are automatically recomputed each time the source files
are edited.
Compilation errors in open files are updated after a very short delay
(tens of milliseconds) after each file change, potentially after every keystroke.
This ensures rapid feedback of syntax and type errors while editing.
Compilation and analysis diagnostics for the whole workspace are much
more expensive to compute, so they are usually recomputed after a
short idle period (around 1s) following an edit.
The [`diagnosticsDelay`](../settings.md#diagnosticsDelay) setting determines
this period.
Alternatively, diagnostics may be triggered only after an edited file
is saved, using the
[`diagnosticsTrigger`](../settings.md#diagnosticsTrigger) setting.
Gopls does not currently support "pull-based" diagnostics, which are
computed synchronously when requested by the client; see golang/go#53275.
## Quick fixes
Each analyzer diagnostic may suggest one or more alternative
ways to fix the problem by editing the code.
For example, when a `return` statement has too few operands,
the [`fillreturns`](../analyzers.md#fillreturns) analyzer
suggests a fix that heuristically fills in the missing ones
with suitable values. Applying the fix eliminates the compilation error.

The screenshot above shows VS Code's Quick Fix menu for an "unused
parameter" analysis diagnostic with two alternative fixes.
(See [Remove unused parameter](transformation.md#remove-unused-parameter) for more detail.)
Suggested fixes that are indisputably safe are [code
actions](transformation.md#code-actions) whose kind is
`"source.fixAll"`.
Many client editors have a shortcut to apply all such fixes.
<!-- Note: each Code Action has exactly one kind, so a server
must offer each "safe" action twice, once with its usual kind
and once with kind "source.fixAll".
The only ones in gopls are simplify{compositelit,range,slice},
which are fixAll + quickfix.
-->
TODO(adonovan): audit all the analyzers to ensure that their
documentation is up-to-date w.r.t. any fixes they suggest.
Settings:
- The [`diagnosticsDelay`](../settings.md#diagnosticsDelay) setting determines
the idle period after an edit before diagnostics are recomputed.
- The [`diagnosticsTriggerr`](../settings.md#diagnosticsTrigger) setting determines
what events cause recomputation of diagnostics.
- The [`linkTarget`](../settings.md#linkTarget) setting specifies
the base URI for Go package links in the Diagnostic.CodeDescription field.
Client support:
- **VS Code**: Each diagnostic appears as a squiggly underline.
Hovering reveals the details, along with any suggested fixes.
- **Emacs + eglot**: Each diagnostic appears as a squiggly underline.
Hovering reveals the details. Use `M-x eglot-code-action-quickfix`
to apply available fixes; it will prompt if there are more than one.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls check file.go`
<!--
dorky details and deletia:
- The **vet suite**, of about thirty analyzers
designed to catch likely mistakes in your code.
- **Type-error fixers**. These are gopls-specific analyzers that
enrich diagnostics from the type checker by suggesting fixes for
simple problems.
For example, when a return statement has too few operands, the
[fillreturns](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillreturns) analyzer can heuristically fill in the missing ones
with suitable values.
The actual diagnostics are produced by the type checker,
so these analyzers won't cause you to see any new diagnostics;
but they add fixes to existing ones.
(The user needs to know this because the settings expose it.)
currently: fillreturns nonewvars noresultvalues stubmethods undeclaredname unusedvariable
- **Simplifiers**. These are gopls-specific analyzers that
suggest ways to rewrite your code more simply.
They do not indicate a mistake in your code,
which is why they are not part of `go vet`.
For example, the `simplifyrange` analyzer will eliminate the
unnecessary blank variable in `for _ = range v {...}`.
currently: simplifycompositelit simplifyrange simplifyslice unusedparams infertypeargs
- **Bug detectors**. Gopls has a suite of bug-detecting analyzers that
can't be part of vet for some reason. That might be because they
have dependencies that vet cannot have (e.g. nilness and
unusedwrite, which construct SSA), or because they are tightly
integrated with gopls (e.g. embeddirective, which produces lazy
fixes through the code action mechanism
[But others do that too: undeclaredname embeddirective unusedparams stubmethods]
currently: atomicalign deepequalerrors nilness sortslice unusedwrite embeddirective
- **staticcheck**: four suites:
add(simple.Analyzers, nil)
add(staticcheck.Analyzers - SA5009, SA5011
add(stylecheck.Analyzers, nil)
add(quickfix.Analyzers, nil)
- **Experimental analyzers**. Gopls has some analyzers that are not
enabled by default, because they produce too high a rate of false
positives. For example, fieldalignment, shadow, useany.
Note: fillstruct is not a real analyzer.
-->
|