github.com/jhump/golang-x-tools@v0.0.0-20220218190644-4958d6d39439/internal/lsp/source/view.go (about)

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package source
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"fmt"
    11  	"go/ast"
    12  	"go/scanner"
    13  	"go/token"
    14  	"go/types"
    15  	"io"
    16  	"strings"
    17  
    18  	"golang.org/x/mod/modfile"
    19  	"golang.org/x/mod/module"
    20  	"github.com/jhump/golang-x-tools/go/analysis"
    21  	"github.com/jhump/golang-x-tools/internal/gocommand"
    22  	"github.com/jhump/golang-x-tools/internal/imports"
    23  	"github.com/jhump/golang-x-tools/internal/lsp/progress"
    24  	"github.com/jhump/golang-x-tools/internal/lsp/protocol"
    25  	"github.com/jhump/golang-x-tools/internal/span"
    26  	errors "golang.org/x/xerrors"
    27  )
    28  
    29  // Snapshot represents the current state for the given view.
    30  type Snapshot interface {
    31  	ID() uint64
    32  
    33  	// View returns the View associated with this snapshot.
    34  	View() View
    35  
    36  	// BackgroundContext returns a context used for all background processing
    37  	// on behalf of this snapshot.
    38  	BackgroundContext() context.Context
    39  
    40  	// Fileset returns the Fileset used to parse all the Go files in this snapshot.
    41  	FileSet() *token.FileSet
    42  
    43  	// ValidBuildConfiguration returns true if there is some error in the
    44  	// user's workspace. In particular, if they are both outside of a module
    45  	// and their GOPATH.
    46  	ValidBuildConfiguration() bool
    47  
    48  	// WriteEnv writes the view-specific environment to the io.Writer.
    49  	WriteEnv(ctx context.Context, w io.Writer) error
    50  
    51  	// FindFile returns the FileHandle for the given URI, if it is already
    52  	// in the given snapshot.
    53  	FindFile(uri span.URI) VersionedFileHandle
    54  
    55  	// GetVersionedFile returns the VersionedFileHandle for a given URI,
    56  	// initializing it if it is not already part of the snapshot.
    57  	GetVersionedFile(ctx context.Context, uri span.URI) (VersionedFileHandle, error)
    58  
    59  	// GetFile returns the FileHandle for a given URI, initializing it if it is
    60  	// not already part of the snapshot.
    61  	GetFile(ctx context.Context, uri span.URI) (FileHandle, error)
    62  
    63  	// AwaitInitialized waits until the snapshot's view is initialized.
    64  	AwaitInitialized(ctx context.Context)
    65  
    66  	// IsOpen returns whether the editor currently has a file open.
    67  	IsOpen(uri span.URI) bool
    68  
    69  	// IgnoredFile reports if a file would be ignored by a `go list` of the whole
    70  	// workspace.
    71  	IgnoredFile(uri span.URI) bool
    72  
    73  	// Templates returns the .tmpl files
    74  	Templates() map[span.URI]VersionedFileHandle
    75  
    76  	// ParseGo returns the parsed AST for the file.
    77  	// If the file is not available, returns nil and an error.
    78  	ParseGo(ctx context.Context, fh FileHandle, mode ParseMode) (*ParsedGoFile, error)
    79  
    80  	// PosToField is a cache of *ast.Fields by token.Pos. This allows us
    81  	// to quickly find corresponding *ast.Field node given a *types.Var.
    82  	// We must refer to the AST to render type aliases properly when
    83  	// formatting signatures and other types.
    84  	PosToField(ctx context.Context, pkg Package, pos token.Pos) (*ast.Field, error)
    85  
    86  	// PosToDecl maps certain objects' positions to their surrounding
    87  	// ast.Decl. This mapping is used when building the documentation
    88  	// string for the objects.
    89  	PosToDecl(ctx context.Context, pkg Package, pos token.Pos) (ast.Decl, error)
    90  
    91  	// DiagnosePackage returns basic diagnostics, including list, parse, and type errors
    92  	// for pkg, grouped by file.
    93  	DiagnosePackage(ctx context.Context, pkg Package) (map[span.URI][]*Diagnostic, error)
    94  
    95  	// Analyze runs the analyses for the given package at this snapshot.
    96  	Analyze(ctx context.Context, pkgID string, analyzers []*Analyzer) ([]*Diagnostic, error)
    97  
    98  	// RunGoCommandPiped runs the given `go` command, writing its output
    99  	// to stdout and stderr. Verb, Args, and WorkingDir must be specified.
   100  	RunGoCommandPiped(ctx context.Context, mode InvocationFlags, inv *gocommand.Invocation, stdout, stderr io.Writer) error
   101  
   102  	// RunGoCommandDirect runs the given `go` command. Verb, Args, and
   103  	// WorkingDir must be specified.
   104  	RunGoCommandDirect(ctx context.Context, mode InvocationFlags, inv *gocommand.Invocation) (*bytes.Buffer, error)
   105  
   106  	// RunGoCommands runs a series of `go` commands that updates the go.mod
   107  	// and go.sum file for wd, and returns their updated contents.
   108  	RunGoCommands(ctx context.Context, allowNetwork bool, wd string, run func(invoke func(...string) (*bytes.Buffer, error)) error) (bool, []byte, []byte, error)
   109  
   110  	// RunProcessEnvFunc runs fn with the process env for this snapshot's view.
   111  	// Note: the process env contains cached module and filesystem state.
   112  	RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error
   113  
   114  	// ModFiles are the go.mod files enclosed in the snapshot's view and known
   115  	// to the snapshot.
   116  	ModFiles() []span.URI
   117  
   118  	// ParseMod is used to parse go.mod files.
   119  	ParseMod(ctx context.Context, fh FileHandle) (*ParsedModule, error)
   120  
   121  	// ModWhy returns the results of `go mod why` for the module specified by
   122  	// the given go.mod file.
   123  	ModWhy(ctx context.Context, fh FileHandle) (map[string]string, error)
   124  
   125  	// ModTidy returns the results of `go mod tidy` for the module specified by
   126  	// the given go.mod file.
   127  	ModTidy(ctx context.Context, pm *ParsedModule) (*TidiedModule, error)
   128  
   129  	// GoModForFile returns the URI of the go.mod file for the given URI.
   130  	GoModForFile(uri span.URI) span.URI
   131  
   132  	// ParseWork is used to parse go.work files.
   133  	ParseWork(ctx context.Context, fh FileHandle) (*ParsedWorkFile, error)
   134  
   135  	// BuiltinFile returns information about the special builtin package.
   136  	BuiltinFile(ctx context.Context) (*ParsedGoFile, error)
   137  
   138  	// IsBuiltin reports whether uri is part of the builtin package.
   139  	IsBuiltin(ctx context.Context, uri span.URI) bool
   140  
   141  	// PackagesForFile returns the packages that this file belongs to, checked
   142  	// in mode.
   143  	PackagesForFile(ctx context.Context, uri span.URI, mode TypecheckMode, includeTestVariants bool) ([]Package, error)
   144  
   145  	// PackageForFile returns a single package that this file belongs to,
   146  	// checked in mode and filtered by the package policy.
   147  	PackageForFile(ctx context.Context, uri span.URI, mode TypecheckMode, selectPackage PackageFilter) (Package, error)
   148  
   149  	// GetActiveReverseDeps returns the active files belonging to the reverse
   150  	// dependencies of this file's package, checked in TypecheckWorkspace mode.
   151  	GetReverseDependencies(ctx context.Context, id string) ([]Package, error)
   152  
   153  	// CachedImportPaths returns all the imported packages loaded in this
   154  	// snapshot, indexed by their import path and checked in TypecheckWorkspace
   155  	// mode.
   156  	CachedImportPaths(ctx context.Context) (map[string]Package, error)
   157  
   158  	// KnownPackages returns all the packages loaded in this snapshot, checked
   159  	// in TypecheckWorkspace mode.
   160  	KnownPackages(ctx context.Context) ([]Package, error)
   161  
   162  	// ActivePackages returns the packages considered 'active' in the workspace.
   163  	//
   164  	// In normal memory mode, this is all workspace packages. In degraded memory
   165  	// mode, this is just the reverse transitive closure of open packages.
   166  	ActivePackages(ctx context.Context) ([]Package, error)
   167  
   168  	// Symbols returns all symbols in the snapshot.
   169  	Symbols(ctx context.Context) (map[span.URI][]Symbol, error)
   170  
   171  	// Metadata returns package metadata associated with the given file URI.
   172  	MetadataForFile(ctx context.Context, uri span.URI) ([]Metadata, error)
   173  
   174  	// GetCriticalError returns any critical errors in the workspace.
   175  	GetCriticalError(ctx context.Context) *CriticalError
   176  
   177  	// BuildGoplsMod generates a go.mod file for all modules in the workspace.
   178  	// It bypasses any existing gopls.mod.
   179  	BuildGoplsMod(ctx context.Context) (*modfile.File, error)
   180  }
   181  
   182  // PackageFilter sets how a package is filtered out from a set of packages
   183  // containing a given file.
   184  type PackageFilter int
   185  
   186  const (
   187  	// NarrowestPackage picks the "narrowest" package for a given file.
   188  	// By "narrowest" package, we mean the package with the fewest number of
   189  	// files that includes the given file. This solves the problem of test
   190  	// variants, as the test will have more files than the non-test package.
   191  	NarrowestPackage PackageFilter = iota
   192  
   193  	// WidestPackage returns the Package containing the most files.
   194  	// This is useful for something like diagnostics, where we'd prefer to
   195  	// offer diagnostics for as many files as possible.
   196  	WidestPackage
   197  )
   198  
   199  // InvocationFlags represents the settings of a particular go command invocation.
   200  // It is a mode, plus a set of flag bits.
   201  type InvocationFlags int
   202  
   203  const (
   204  	// Normal is appropriate for commands that might be run by a user and don't
   205  	// deliberately modify go.mod files, e.g. `go test`.
   206  	Normal InvocationFlags = iota
   207  	// WriteTemporaryModFile is for commands that need information from a
   208  	// modified version of the user's go.mod file, e.g. `go mod tidy` used to
   209  	// generate diagnostics.
   210  	WriteTemporaryModFile
   211  	// LoadWorkspace is for packages.Load, and other operations that should
   212  	// consider the whole workspace at once.
   213  	LoadWorkspace
   214  
   215  	// AllowNetwork is a flag bit that indicates the invocation should be
   216  	// allowed to access the network.
   217  	AllowNetwork InvocationFlags = 1 << 10
   218  )
   219  
   220  func (m InvocationFlags) Mode() InvocationFlags {
   221  	return m & (AllowNetwork - 1)
   222  }
   223  
   224  func (m InvocationFlags) AllowNetwork() bool {
   225  	return m&AllowNetwork != 0
   226  }
   227  
   228  // View represents a single workspace.
   229  // This is the level at which we maintain configuration like working directory
   230  // and build tags.
   231  type View interface {
   232  	// Name returns the name this view was constructed with.
   233  	Name() string
   234  
   235  	// Folder returns the folder with which this view was created.
   236  	Folder() span.URI
   237  
   238  	// Shutdown closes this view, and detaches it from its session.
   239  	Shutdown(ctx context.Context)
   240  
   241  	// Options returns a copy of the Options for this view.
   242  	Options() *Options
   243  
   244  	// SetOptions sets the options of this view to new values.
   245  	// Calling this may cause the view to be invalidated and a replacement view
   246  	// added to the session. If so the new view will be returned, otherwise the
   247  	// original one will be.
   248  	SetOptions(context.Context, *Options) (View, error)
   249  
   250  	// Snapshot returns the current snapshot for the view.
   251  	Snapshot(ctx context.Context) (Snapshot, func())
   252  
   253  	// Rebuild rebuilds the current view, replacing the original view in its session.
   254  	Rebuild(ctx context.Context) (Snapshot, func(), error)
   255  
   256  	// IsGoPrivatePath reports whether target is a private import path, as identified
   257  	// by the GOPRIVATE environment variable.
   258  	IsGoPrivatePath(path string) bool
   259  
   260  	// ModuleUpgrades returns known module upgrades.
   261  	ModuleUpgrades() map[string]string
   262  
   263  	// RegisterModuleUpgrades registers that upgrades exist for the given modules.
   264  	RegisterModuleUpgrades(upgrades map[string]string)
   265  
   266  	// FileKind returns the type of a file
   267  	FileKind(FileHandle) FileKind
   268  }
   269  
   270  // A FileSource maps uris to FileHandles. This abstraction exists both for
   271  // testability, and so that algorithms can be run equally on session and
   272  // snapshot files.
   273  type FileSource interface {
   274  	// GetFile returns the FileHandle for a given URI.
   275  	GetFile(ctx context.Context, uri span.URI) (FileHandle, error)
   276  }
   277  
   278  // A ParsedGoFile contains the results of parsing a Go file.
   279  type ParsedGoFile struct {
   280  	URI  span.URI
   281  	Mode ParseMode
   282  	File *ast.File
   283  	Tok  *token.File
   284  	// Source code used to build the AST. It may be different from the
   285  	// actual content of the file if we have fixed the AST.
   286  	Src      []byte
   287  	Mapper   *protocol.ColumnMapper
   288  	ParseErr scanner.ErrorList
   289  }
   290  
   291  // A ParsedModule contains the results of parsing a go.mod file.
   292  type ParsedModule struct {
   293  	URI         span.URI
   294  	File        *modfile.File
   295  	Mapper      *protocol.ColumnMapper
   296  	ParseErrors []*Diagnostic
   297  }
   298  
   299  // A ParsedWorkFile contains the results of parsing a go.work file.
   300  type ParsedWorkFile struct {
   301  	URI         span.URI
   302  	File        *modfile.WorkFile
   303  	Mapper      *protocol.ColumnMapper
   304  	ParseErrors []*Diagnostic
   305  }
   306  
   307  // A TidiedModule contains the results of running `go mod tidy` on a module.
   308  type TidiedModule struct {
   309  	// Diagnostics representing changes made by `go mod tidy`.
   310  	Diagnostics []*Diagnostic
   311  	// The bytes of the go.mod file after it was tidied.
   312  	TidiedContent []byte
   313  }
   314  
   315  // Metadata represents package metadata retrieved from go/packages.
   316  type Metadata interface {
   317  	// PackageName is the package name.
   318  	PackageName() string
   319  
   320  	// PackagePath is the package path.
   321  	PackagePath() string
   322  }
   323  
   324  // Session represents a single connection from a client.
   325  // This is the level at which things like open files are maintained on behalf
   326  // of the client.
   327  // A session may have many active views at any given time.
   328  type Session interface {
   329  	// ID returns the unique identifier for this session on this server.
   330  	ID() string
   331  	// NewView creates a new View, returning it and its first snapshot. If a
   332  	// non-empty tempWorkspace directory is provided, the View will record a copy
   333  	// of its gopls workspace module in that directory, so that client tooling
   334  	// can execute in the same main module.
   335  	NewView(ctx context.Context, name string, folder span.URI, options *Options) (View, Snapshot, func(), error)
   336  
   337  	// Cache returns the cache that created this session, for debugging only.
   338  	Cache() interface{}
   339  
   340  	// View returns a view with a matching name, if the session has one.
   341  	View(name string) View
   342  
   343  	// ViewOf returns a view corresponding to the given URI.
   344  	ViewOf(uri span.URI) (View, error)
   345  
   346  	// Views returns the set of active views built by this session.
   347  	Views() []View
   348  
   349  	// Shutdown the session and all views it has created.
   350  	Shutdown(ctx context.Context)
   351  
   352  	// GetFile returns a handle for the specified file.
   353  	GetFile(ctx context.Context, uri span.URI) (FileHandle, error)
   354  
   355  	// DidModifyFile reports a file modification to the session. It returns
   356  	// the new snapshots after the modifications have been applied, paired with
   357  	// the affected file URIs for those snapshots.
   358  	DidModifyFiles(ctx context.Context, changes []FileModification) (map[Snapshot][]span.URI, []func(), error)
   359  
   360  	// ExpandModificationsToDirectories returns the set of changes with the
   361  	// directory changes removed and expanded to include all of the files in
   362  	// the directory.
   363  	ExpandModificationsToDirectories(ctx context.Context, changes []FileModification) []FileModification
   364  
   365  	// Overlays returns a slice of file overlays for the session.
   366  	Overlays() []Overlay
   367  
   368  	// Options returns a copy of the SessionOptions for this session.
   369  	Options() *Options
   370  
   371  	// SetOptions sets the options of this session to new values.
   372  	SetOptions(*Options)
   373  
   374  	// FileWatchingGlobPatterns returns glob patterns to watch every directory
   375  	// known by the view. For views within a module, this is the module root,
   376  	// any directory in the module root, and any replace targets.
   377  	FileWatchingGlobPatterns(ctx context.Context) map[string]struct{}
   378  
   379  	// SetProgressTracker sets the progress tracker for the session.
   380  	SetProgressTracker(tracker *progress.Tracker)
   381  }
   382  
   383  var ErrViewExists = errors.New("view already exists for session")
   384  
   385  // Overlay is the type for a file held in memory on a session.
   386  type Overlay interface {
   387  	Kind() FileKind
   388  	VersionedFileHandle
   389  }
   390  
   391  // FileModification represents a modification to a file.
   392  type FileModification struct {
   393  	URI    span.URI
   394  	Action FileAction
   395  
   396  	// OnDisk is true if a watched file is changed on disk.
   397  	// If true, Version will be -1 and Text will be nil.
   398  	OnDisk bool
   399  
   400  	// Version will be -1 and Text will be nil when they are not supplied,
   401  	// specifically on textDocument/didClose and for on-disk changes.
   402  	Version int32
   403  	Text    []byte
   404  
   405  	// LanguageID is only sent from the language client on textDocument/didOpen.
   406  	LanguageID string
   407  }
   408  
   409  type FileAction int
   410  
   411  const (
   412  	UnknownFileAction = FileAction(iota)
   413  	Open
   414  	Change
   415  	Close
   416  	Save
   417  	Create
   418  	Delete
   419  	InvalidateMetadata
   420  )
   421  
   422  func (a FileAction) String() string {
   423  	switch a {
   424  	case Open:
   425  		return "Open"
   426  	case Change:
   427  		return "Change"
   428  	case Close:
   429  		return "Close"
   430  	case Save:
   431  		return "Save"
   432  	case Create:
   433  		return "Create"
   434  	case Delete:
   435  		return "Delete"
   436  	case InvalidateMetadata:
   437  		return "InvalidateMetadata"
   438  	default:
   439  		return "Unknown"
   440  	}
   441  }
   442  
   443  var ErrTmpModfileUnsupported = errors.New("-modfile is unsupported for this Go version")
   444  var ErrNoModOnDisk = errors.New("go.mod file is not on disk")
   445  
   446  func IsNonFatalGoModError(err error) bool {
   447  	return err == ErrTmpModfileUnsupported || err == ErrNoModOnDisk
   448  }
   449  
   450  // ParseMode controls the content of the AST produced when parsing a source file.
   451  type ParseMode int
   452  
   453  const (
   454  	// ParseHeader specifies that the main package declaration and imports are needed.
   455  	// This is the mode used when attempting to examine the package graph structure.
   456  	ParseHeader ParseMode = iota
   457  
   458  	// ParseExported specifies that the package is used only as a dependency,
   459  	// and only its exported declarations are needed. More may be included if
   460  	// necessary to avoid type errors.
   461  	ParseExported
   462  
   463  	// ParseFull specifies the full AST is needed.
   464  	// This is used for files of direct interest where the entire contents must
   465  	// be considered.
   466  	ParseFull
   467  )
   468  
   469  // TypecheckMode controls what kind of parsing should be done (see ParseMode)
   470  // while type checking a package.
   471  type TypecheckMode int
   472  
   473  const (
   474  	// Invalid default value.
   475  	TypecheckUnknown TypecheckMode = iota
   476  	// TypecheckFull means to use ParseFull.
   477  	TypecheckFull
   478  	// TypecheckWorkspace means to use ParseFull for workspace packages, and
   479  	// ParseExported for others.
   480  	TypecheckWorkspace
   481  	// TypecheckAll means ParseFull for workspace packages, and both Full and
   482  	// Exported for others. Only valid for some functions.
   483  	TypecheckAll
   484  )
   485  
   486  type VersionedFileHandle interface {
   487  	FileHandle
   488  	Version() int32
   489  	Session() string
   490  
   491  	// LSPIdentity returns the version identity of a file.
   492  	VersionedFileIdentity() VersionedFileIdentity
   493  }
   494  
   495  type VersionedFileIdentity struct {
   496  	URI span.URI
   497  
   498  	// SessionID is the ID of the LSP session.
   499  	SessionID string
   500  
   501  	// Version is the version of the file, as specified by the client. It should
   502  	// only be set in combination with SessionID.
   503  	Version int32
   504  }
   505  
   506  // FileHandle represents a handle to a specific version of a single file.
   507  type FileHandle interface {
   508  	URI() span.URI
   509  
   510  	// FileIdentity returns a FileIdentity for the file, even if there was an
   511  	// error reading it.
   512  	FileIdentity() FileIdentity
   513  	// Read reads the contents of a file.
   514  	// If the file is not available, returns a nil slice and an error.
   515  	Read() ([]byte, error)
   516  	// Saved reports whether the file has the same content on disk.
   517  	Saved() bool
   518  }
   519  
   520  // FileIdentity uniquely identifies a file at a version from a FileSystem.
   521  type FileIdentity struct {
   522  	URI span.URI
   523  
   524  	// Identifier represents a unique identifier for the file's content.
   525  	Hash string
   526  }
   527  
   528  func (id FileIdentity) String() string {
   529  	return fmt.Sprintf("%s%s", id.URI, id.Hash)
   530  }
   531  
   532  // FileKind describes the kind of the file in question.
   533  // It can be one of Go,mod, Sum, or Tmpl.
   534  type FileKind int
   535  
   536  const (
   537  	// UnknownKind is a file type we don't know about.
   538  	UnknownKind = FileKind(iota)
   539  
   540  	// Go is a normal go source file.
   541  	Go
   542  	// Mod is a go.mod file.
   543  	Mod
   544  	// Sum is a go.sum file.
   545  	Sum
   546  	// Tmpl is a template file.
   547  	Tmpl
   548  	// Work is a go.work file.
   549  	Work
   550  )
   551  
   552  // Analyzer represents a go/analysis analyzer with some boolean properties
   553  // that let the user know how to use the analyzer.
   554  type Analyzer struct {
   555  	Analyzer *analysis.Analyzer
   556  
   557  	// Enabled reports whether the analyzer is enabled. This value can be
   558  	// configured per-analysis in user settings. For staticcheck analyzers,
   559  	// the value of the Staticcheck setting overrides this field.
   560  	Enabled bool
   561  
   562  	// Fix is the name of the suggested fix name used to invoke the suggested
   563  	// fixes for the analyzer. It is non-empty if we expect this analyzer to
   564  	// provide its fix separately from its diagnostics. That is, we should apply
   565  	// the analyzer's suggested fixes through a Command, not a TextEdit.
   566  	Fix string
   567  
   568  	// ActionKind is the kind of code action this analyzer produces. If
   569  	// unspecified the type defaults to quickfix.
   570  	ActionKind []protocol.CodeActionKind
   571  
   572  	// Severity is the severity set for diagnostics reported by this
   573  	// analyzer. If left unset it defaults to Warning.
   574  	Severity protocol.DiagnosticSeverity
   575  }
   576  
   577  func (a Analyzer) IsEnabled(view View) bool {
   578  	// Staticcheck analyzers can only be enabled when staticcheck is on.
   579  	if _, ok := view.Options().StaticcheckAnalyzers[a.Analyzer.Name]; ok {
   580  		if !view.Options().Staticcheck {
   581  			return false
   582  		}
   583  	}
   584  	if enabled, ok := view.Options().Analyses[a.Analyzer.Name]; ok {
   585  		return enabled
   586  	}
   587  	return a.Enabled
   588  }
   589  
   590  // Package represents a Go package that has been type-checked. It maintains
   591  // only the relevant fields of a *go/packages.Package.
   592  type Package interface {
   593  	ID() string
   594  	Name() string
   595  	PkgPath() string
   596  	CompiledGoFiles() []*ParsedGoFile
   597  	File(uri span.URI) (*ParsedGoFile, error)
   598  	GetSyntax() []*ast.File
   599  	GetTypes() *types.Package
   600  	GetTypesInfo() *types.Info
   601  	GetTypesSizes() types.Sizes
   602  	IsIllTyped() bool
   603  	ForTest() string
   604  	GetImport(pkgPath string) (Package, error)
   605  	MissingDependencies() []string
   606  	Imports() []Package
   607  	Version() *module.Version
   608  	HasListOrParseErrors() bool
   609  	HasTypeErrors() bool
   610  	ParseMode() ParseMode
   611  }
   612  
   613  type CriticalError struct {
   614  	// MainError is the primary error. Must be non-nil.
   615  	MainError error
   616  	// DiagList contains any supplemental (structured) diagnostics.
   617  	DiagList []*Diagnostic
   618  }
   619  
   620  // An Diagnostic corresponds to an LSP Diagnostic.
   621  // https://microsoft.github.io/language-server-protocol/specification#diagnostic
   622  type Diagnostic struct {
   623  	URI      span.URI
   624  	Range    protocol.Range
   625  	Severity protocol.DiagnosticSeverity
   626  	Code     string
   627  	CodeHref string
   628  
   629  	// Source is a human-readable description of the source of the error.
   630  	// Diagnostics generated by an analysis.Analyzer set it to Analyzer.Name.
   631  	Source DiagnosticSource
   632  
   633  	Message string
   634  
   635  	Tags    []protocol.DiagnosticTag
   636  	Related []RelatedInformation
   637  
   638  	// Fields below are used internally to generate quick fixes. They aren't
   639  	// part of the LSP spec and don't leave the server.
   640  	SuggestedFixes []SuggestedFix
   641  	Analyzer       *Analyzer
   642  }
   643  
   644  type DiagnosticSource string
   645  
   646  const (
   647  	UnknownError             DiagnosticSource = "<Unknown source>"
   648  	ListError                DiagnosticSource = "go list"
   649  	ParseError               DiagnosticSource = "syntax"
   650  	TypeError                DiagnosticSource = "compiler"
   651  	ModTidyError             DiagnosticSource = "go mod tidy"
   652  	OptimizationDetailsError DiagnosticSource = "optimizer details"
   653  	UpgradeNotification      DiagnosticSource = "upgrade available"
   654  	TemplateError            DiagnosticSource = "template"
   655  )
   656  
   657  func AnalyzerErrorKind(name string) DiagnosticSource {
   658  	return DiagnosticSource(name)
   659  }
   660  
   661  var (
   662  	PackagesLoadError = errors.New("packages.Load error")
   663  )
   664  
   665  // WorkspaceModuleVersion is the nonexistent pseudoversion suffix used in the
   666  // construction of the workspace module. It is exported so that we can make
   667  // sure not to show this version to end users in error messages, to avoid
   668  // confusion.
   669  // The major version is not included, as that depends on the module path.
   670  //
   671  // If workspace module A is dependent on workspace module B, we need our
   672  // nonexistant version to be greater than the version A mentions.
   673  // Otherwise, the go command will try to update to that version. Use a very
   674  // high minor version to make that more likely.
   675  const workspaceModuleVersion = ".9999999.0-goplsworkspace"
   676  
   677  func IsWorkspaceModuleVersion(version string) bool {
   678  	return strings.HasSuffix(version, workspaceModuleVersion)
   679  }
   680  
   681  func WorkspaceModuleVersion(majorVersion string) string {
   682  	// Use the highest compatible major version to avoid unwanted upgrades.
   683  	// See the comment on workspaceModuleVersion.
   684  	if majorVersion == "v0" {
   685  		majorVersion = "v1"
   686  	}
   687  	return majorVersion + workspaceModuleVersion
   688  }