# 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.

  ![A diagnostic due to a type error](../assets/diagnostic-typeerror.png)

  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.

  ![A diagnostic due to an analysis finding](../assets/diagnostic-analysis.png)

  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.

![An analyzer diagnostic with two alternative fixes](../assets/remove-unusedparam-before.png)

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.

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**: Diagnostics appear as a squiggly underline.
  Hovering reveals the details, along with any suggested fixes.
- **Emacs + eglot**: Diagnostics appear 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.

-->
