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