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.
18 "golang.org/x/mod/modfile"
19 "golang.org/x/mod/module"
20 "golang.org/x/tools/go/analysis"
21 "golang.org/x/tools/internal/gocommand"
22 "golang.org/x/tools/internal/imports"
23 "golang.org/x/tools/internal/lsp/protocol"
24 "golang.org/x/tools/internal/span"
25 errors "golang.org/x/xerrors"
28 // Snapshot represents the current state for the given view.
29 type Snapshot interface {
32 // View returns the View associated with this snapshot.
35 // BackgroundContext returns a context used for all background processing
36 // on behalf of this snapshot.
37 BackgroundContext() context.Context
39 // Fileset returns the Fileset used to parse all the Go files in this snapshot.
40 FileSet() *token.FileSet
42 // ValidBuildConfiguration returns true if there is some error in the
43 // user's workspace. In particular, if they are both outside of a module
45 ValidBuildConfiguration() bool
47 // WriteEnv writes the view-specific environment to the io.Writer.
48 WriteEnv(ctx context.Context, w io.Writer) error
50 // FindFile returns the FileHandle for the given URI, if it is already
51 // in the given snapshot.
52 FindFile(uri span.URI) VersionedFileHandle
54 // GetVersionedFile returns the VersionedFileHandle for a given URI,
55 // initializing it if it is not already part of the snapshot.
56 GetVersionedFile(ctx context.Context, uri span.URI) (VersionedFileHandle, error)
58 // GetFile returns the FileHandle for a given URI, initializing it if it is
59 // not already part of the snapshot.
60 GetFile(ctx context.Context, uri span.URI) (FileHandle, error)
62 // AwaitInitialized waits until the snapshot's view is initialized.
63 AwaitInitialized(ctx context.Context)
65 // IsOpen returns whether the editor currently has a file open.
66 IsOpen(uri span.URI) bool
68 // IgnoredFile reports if a file would be ignored by a `go list` of the whole
70 IgnoredFile(uri span.URI) bool
72 // ParseGo returns the parsed AST for the file.
73 // If the file is not available, returns nil and an error.
74 ParseGo(ctx context.Context, fh FileHandle, mode ParseMode) (*ParsedGoFile, error)
76 // PosToField is a cache of *ast.Fields by token.Pos. This allows us
77 // to quickly find corresponding *ast.Field node given a *types.Var.
78 // We must refer to the AST to render type aliases properly when
79 // formatting signatures and other types.
80 PosToField(ctx context.Context, pgf *ParsedGoFile) (map[token.Pos]*ast.Field, error)
82 // PosToDecl maps certain objects' positions to their surrounding
83 // ast.Decl. This mapping is used when building the documentation
84 // string for the objects.
85 PosToDecl(ctx context.Context, pgf *ParsedGoFile) (map[token.Pos]ast.Decl, error)
87 // DiagnosePackage returns basic diagnostics, including list, parse, and type errors
88 // for pkg, grouped by file.
89 DiagnosePackage(ctx context.Context, pkg Package) (map[span.URI][]*Diagnostic, error)
91 // Analyze runs the analyses for the given package at this snapshot.
92 Analyze(ctx context.Context, pkgID string, analyzers []*Analyzer) ([]*Diagnostic, error)
94 // RunGoCommandPiped runs the given `go` command, writing its output
95 // to stdout and stderr. Verb, Args, and WorkingDir must be specified.
96 RunGoCommandPiped(ctx context.Context, mode InvocationFlags, inv *gocommand.Invocation, stdout, stderr io.Writer) error
98 // RunGoCommandDirect runs the given `go` command. Verb, Args, and
99 // WorkingDir must be specified.
100 RunGoCommandDirect(ctx context.Context, mode InvocationFlags, inv *gocommand.Invocation) (*bytes.Buffer, error)
102 // RunGoCommands runs a series of `go` commands that updates the go.mod
103 // and go.sum file for wd, and returns their updated contents.
104 RunGoCommands(ctx context.Context, allowNetwork bool, wd string, run func(invoke func(...string) (*bytes.Buffer, error)) error) (bool, []byte, []byte, error)
106 // RunProcessEnvFunc runs fn with the process env for this snapshot's view.
107 // Note: the process env contains cached module and filesystem state.
108 RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error
110 // ModFiles are the go.mod files enclosed in the snapshot's view and known
112 ModFiles() []span.URI
114 // ParseMod is used to parse go.mod files.
115 ParseMod(ctx context.Context, fh FileHandle) (*ParsedModule, error)
117 // ModWhy returns the results of `go mod why` for the module specified by
118 // the given go.mod file.
119 ModWhy(ctx context.Context, fh FileHandle) (map[string]string, error)
121 // ModTidy returns the results of `go mod tidy` for the module specified by
122 // the given go.mod file.
123 ModTidy(ctx context.Context, pm *ParsedModule) (*TidiedModule, error)
125 // GoModForFile returns the URI of the go.mod file for the given URI.
126 GoModForFile(uri span.URI) span.URI
128 // BuiltinPackage returns information about the special builtin package.
129 BuiltinPackage(ctx context.Context) (*BuiltinPackage, error)
131 // PackagesForFile returns the packages that this file belongs to, checked
133 PackagesForFile(ctx context.Context, uri span.URI, mode TypecheckMode) ([]Package, error)
135 // PackageForFile returns a single package that this file belongs to,
136 // checked in mode and filtered by the package policy.
137 PackageForFile(ctx context.Context, uri span.URI, mode TypecheckMode, selectPackage PackageFilter) (Package, error)
139 // GetActiveReverseDeps returns the active files belonging to the reverse
140 // dependencies of this file's package, checked in TypecheckWorkspace mode.
141 GetReverseDependencies(ctx context.Context, id string) ([]Package, error)
143 // CachedImportPaths returns all the imported packages loaded in this
144 // snapshot, indexed by their import path and checked in TypecheckWorkspace
146 CachedImportPaths(ctx context.Context) (map[string]Package, error)
148 // KnownPackages returns all the packages loaded in this snapshot, checked
149 // in TypecheckWorkspace mode.
150 KnownPackages(ctx context.Context) ([]Package, error)
152 // WorkspacePackages returns the snapshot's top-level packages.
153 WorkspacePackages(ctx context.Context) ([]Package, error)
155 // GetCriticalError returns any critical errors in the workspace.
156 GetCriticalError(ctx context.Context) *CriticalError
159 // PackageFilter sets how a package is filtered out from a set of packages
160 // containing a given file.
161 type PackageFilter int
164 // NarrowestPackage picks the "narrowest" package for a given file.
165 // By "narrowest" package, we mean the package with the fewest number of
166 // files that includes the given file. This solves the problem of test
167 // variants, as the test will have more files than the non-test package.
168 NarrowestPackage PackageFilter = iota
170 // WidestPackage returns the Package containing the most files.
171 // This is useful for something like diagnostics, where we'd prefer to
172 // offer diagnostics for as many files as possible.
176 // InvocationFlags represents the settings of a particular go command invocation.
177 // It is a mode, plus a set of flag bits.
178 type InvocationFlags int
181 // Normal is appropriate for commands that might be run by a user and don't
182 // deliberately modify go.mod files, e.g. `go test`.
183 Normal InvocationFlags = iota
184 // UpdateUserModFile is for commands that intend to update the user's real
185 // go.mod file, e.g. `go mod tidy` in response to a user's request to tidy.
187 // WriteTemporaryModFile is for commands that need information from a
188 // modified version of the user's go.mod file, e.g. `go mod tidy` used to
189 // generate diagnostics.
190 WriteTemporaryModFile
191 // LoadWorkspace is for packages.Load, and other operations that should
192 // consider the whole workspace at once.
195 // AllowNetwork is a flag bit that indicates the invocation should be
196 // allowed to access the network.
197 AllowNetwork InvocationFlags = 1 << 10
200 func (m InvocationFlags) Mode() InvocationFlags {
201 return m & (AllowNetwork - 1)
204 func (m InvocationFlags) AllowNetwork() bool {
205 return m&AllowNetwork != 0
208 // View represents a single workspace.
209 // This is the level at which we maintain configuration like working directory
211 type View interface {
212 // Name returns the name this view was constructed with.
215 // Folder returns the folder with which this view was created.
218 // Shutdown closes this view, and detaches it from its session.
219 Shutdown(ctx context.Context)
221 // Options returns a copy of the Options for this view.
224 // SetOptions sets the options of this view to new values.
225 // Calling this may cause the view to be invalidated and a replacement view
226 // added to the session. If so the new view will be returned, otherwise the
227 // original one will be.
228 SetOptions(context.Context, *Options) (View, error)
230 // Snapshot returns the current snapshot for the view.
231 Snapshot(ctx context.Context) (Snapshot, func())
233 // Rebuild rebuilds the current view, replacing the original view in its session.
234 Rebuild(ctx context.Context) (Snapshot, func(), error)
236 // IsGoPrivatePath reports whether target is a private import path, as identified
237 // by the GOPRIVATE environment variable.
238 IsGoPrivatePath(path string) bool
240 // ModuleUpgrades returns known module upgrades.
241 ModuleUpgrades() map[string]string
243 // RegisterModuleUpgrades registers that upgrades exist for the given modules.
244 RegisterModuleUpgrades(upgrades map[string]string)
247 // A FileSource maps uris to FileHandles. This abstraction exists both for
248 // testability, and so that algorithms can be run equally on session and
250 type FileSource interface {
251 // GetFile returns the FileHandle for a given URI.
252 GetFile(ctx context.Context, uri span.URI) (FileHandle, error)
255 type BuiltinPackage struct {
257 ParsedFile *ParsedGoFile
260 // A ParsedGoFile contains the results of parsing a Go file.
261 type ParsedGoFile struct {
266 // Source code used to build the AST. It may be different from the
267 // actual content of the file if we have fixed the AST.
269 Mapper *protocol.ColumnMapper
270 ParseErr scanner.ErrorList
273 // A ParsedModule contains the results of parsing a go.mod file.
274 type ParsedModule struct {
277 Mapper *protocol.ColumnMapper
278 ParseErrors []*Diagnostic
281 // A TidiedModule contains the results of running `go mod tidy` on a module.
282 type TidiedModule struct {
283 // Diagnostics representing changes made by `go mod tidy`.
284 Diagnostics []*Diagnostic
285 // The bytes of the go.mod file after it was tidied.
289 // Session represents a single connection from a client.
290 // This is the level at which things like open files are maintained on behalf
292 // A session may have many active views at any given time.
293 type Session interface {
294 // NewView creates a new View, returning it and its first snapshot.
295 NewView(ctx context.Context, name string, folder, tempWorkspaceDir span.URI, options *Options) (View, Snapshot, func(), error)
297 // Cache returns the cache that created this session, for debugging only.
300 // View returns a view with a matching name, if the session has one.
301 View(name string) View
303 // ViewOf returns a view corresponding to the given URI.
304 ViewOf(uri span.URI) (View, error)
306 // Views returns the set of active views built by this session.
309 // Shutdown the session and all views it has created.
310 Shutdown(ctx context.Context)
312 // GetFile returns a handle for the specified file.
313 GetFile(ctx context.Context, uri span.URI) (FileHandle, error)
315 // DidModifyFile reports a file modification to the session. It returns
316 // the new snapshots after the modifications have been applied, paired with
317 // the affected file URIs for those snapshots.
318 DidModifyFiles(ctx context.Context, changes []FileModification) (map[Snapshot][]span.URI, []func(), error)
320 // ExpandModificationsToDirectories returns the set of changes with the
321 // directory changes removed and expanded to include all of the files in
323 ExpandModificationsToDirectories(ctx context.Context, changes []FileModification) []FileModification
325 // Overlays returns a slice of file overlays for the session.
328 // Options returns a copy of the SessionOptions for this session.
331 // SetOptions sets the options of this session to new values.
334 // FileWatchingGlobPatterns returns glob patterns to watch every directory
335 // known by the view. For views within a module, this is the module root,
336 // any directory in the module root, and any replace targets.
337 FileWatchingGlobPatterns(ctx context.Context) map[string]struct{}
340 // Overlay is the type for a file held in memory on a session.
341 type Overlay interface {
345 // FileModification represents a modification to a file.
346 type FileModification struct {
350 // OnDisk is true if a watched file is changed on disk.
351 // If true, Version will be -1 and Text will be nil.
354 // Version will be -1 and Text will be nil when they are not supplied,
355 // specifically on textDocument/didClose and for on-disk changes.
359 // LanguageID is only sent from the language client on textDocument/didOpen.
366 UnknownFileAction = FileAction(iota)
376 func (a FileAction) String() string {
390 case InvalidateMetadata:
391 return "InvalidateMetadata"
397 var ErrTmpModfileUnsupported = errors.New("-modfile is unsupported for this Go version")
398 var ErrNoModOnDisk = errors.New("go.mod file is not on disk")
400 func IsNonFatalGoModError(err error) bool {
401 return err == ErrTmpModfileUnsupported || err == ErrNoModOnDisk
404 // ParseMode controls the content of the AST produced when parsing a source file.
408 // ParseHeader specifies that the main package declaration and imports are needed.
409 // This is the mode used when attempting to examine the package graph structure.
410 ParseHeader ParseMode = iota
412 // ParseExported specifies that the public symbols are needed, but things like
413 // private symbols and function bodies are not.
414 // This mode is used for things where a package is being consumed only as a
418 // ParseFull specifies the full AST is needed.
419 // This is used for files of direct interest where the entire contents must
424 // TypecheckMode controls what kind of parsing should be done (see ParseMode)
425 // while type checking a package.
426 type TypecheckMode int
429 // Invalid default value.
430 TypecheckUnknown TypecheckMode = iota
431 // TypecheckFull means to use ParseFull.
433 // TypecheckWorkspace means to use ParseFull for workspace packages, and
434 // ParseExported for others.
436 // TypecheckAll means ParseFull for workspace packages, and both Full and
437 // Exported for others. Only valid for some functions.
441 type VersionedFileHandle interface {
446 // LSPIdentity returns the version identity of a file.
447 VersionedFileIdentity() VersionedFileIdentity
450 type VersionedFileIdentity struct {
453 // SessionID is the ID of the LSP session.
456 // Version is the version of the file, as specified by the client. It should
457 // only be set in combination with SessionID.
461 // FileHandle represents a handle to a specific version of a single file.
462 type FileHandle interface {
466 // FileIdentity returns a FileIdentity for the file, even if there was an
468 FileIdentity() FileIdentity
469 // Read reads the contents of a file.
470 // If the file is not available, returns a nil slice and an error.
471 Read() ([]byte, error)
472 // Saved reports whether the file has the same content on disk.
476 // FileIdentity uniquely identifies a file at a version from a FileSystem.
477 type FileIdentity struct {
480 // Identifier represents a unique identifier for the file's content.
483 // Kind is the file's kind.
487 func (id FileIdentity) String() string {
488 return fmt.Sprintf("%s%s%s", id.URI, id.Hash, id.Kind)
491 // FileKind describes the kind of the file in question.
492 // It can be one of Go, mod, or sum.
496 // UnknownKind is a file type we don't know about.
497 UnknownKind = FileKind(iota)
499 // Go is a normal go source file.
501 // Mod is a go.mod file.
503 // Sum is a go.sum file.
507 // Analyzer represents a go/analysis analyzer with some boolean properties
508 // that let the user know how to use the analyzer.
509 type Analyzer struct {
510 Analyzer *analysis.Analyzer
512 // Enabled reports whether the analyzer is enabled. This value can be
513 // configured per-analysis in user settings. For staticcheck analyzers,
514 // the value of the Staticcheck setting overrides this field.
517 // Fix is the name of the suggested fix name used to invoke the suggested
518 // fixes for the analyzer. It is non-empty if we expect this analyzer to
519 // provide its fix separately from its diagnostics. That is, we should apply
520 // the analyzer's suggested fixes through a Command, not a TextEdit.
523 // ActionKind is the kind of code action this analyzer produces. If
524 // unspecified the type defaults to quickfix.
525 ActionKind protocol.CodeActionKind
528 func (a Analyzer) IsEnabled(view View) bool {
529 // Staticcheck analyzers can only be enabled when staticcheck is on.
530 if _, ok := view.Options().StaticcheckAnalyzers[a.Analyzer.Name]; ok {
531 if !view.Options().Staticcheck {
535 if enabled, ok := view.Options().Analyses[a.Analyzer.Name]; ok {
541 // Package represents a Go package that has been type-checked. It maintains
542 // only the relevant fields of a *go/packages.Package.
543 type Package interface {
547 CompiledGoFiles() []*ParsedGoFile
548 File(uri span.URI) (*ParsedGoFile, error)
549 GetSyntax() []*ast.File
550 GetTypes() *types.Package
551 GetTypesInfo() *types.Info
552 GetTypesSizes() types.Sizes
555 GetImport(pkgPath string) (Package, error)
556 MissingDependencies() []string
558 Version() *module.Version
559 HasListOrParseErrors() bool
563 type CriticalError struct {
564 // MainError is the primary error. Must be non-nil.
566 // DiagList contains any supplemental (structured) diagnostics.
567 DiagList []*Diagnostic
570 // An Diagnostic corresponds to an LSP Diagnostic.
571 // https://microsoft.github.io/language-server-protocol/specification#diagnostic
572 type Diagnostic struct {
575 Severity protocol.DiagnosticSeverity
579 // Source is a human-readable description of the source of the error.
580 // Diagnostics generated by an analysis.Analyzer set it to Analyzer.Name.
581 Source DiagnosticSource
585 Tags []protocol.DiagnosticTag
586 Related []RelatedInformation
588 // Fields below are used internally to generate quick fixes. They aren't
589 // part of the LSP spec and don't leave the server.
590 SuggestedFixes []SuggestedFix
594 type DiagnosticSource string
597 UnknownError DiagnosticSource = "<Unknown source>"
598 ListError DiagnosticSource = "go list"
599 ParseError DiagnosticSource = "syntax"
600 TypeError DiagnosticSource = "compiler"
601 ModTidyError DiagnosticSource = "go mod tidy"
602 OptimizationDetailsError DiagnosticSource = "optimizer details"
603 UpgradeNotification DiagnosticSource = "upgrade available"
606 func AnalyzerErrorKind(name string) DiagnosticSource {
607 return DiagnosticSource(name)
611 PackagesLoadError = errors.New("packages.Load error")
614 // WorkspaceModuleVersion is the nonexistent pseudoversion suffix used in the
615 // construction of the workspace module. It is exported so that we can make
616 // sure not to show this version to end users in error messages, to avoid
618 // The major version is not included, as that depends on the module path.
620 // If workspace module A is dependent on workspace module B, we need our
621 // nonexistant version to be greater than the version A mentions.
622 // Otherwise, the go command will try to update to that version. Use a very
623 // high minor version to make that more likely.
624 const workspaceModuleVersion = ".9999999.0-goplsworkspace"
626 func IsWorkspaceModuleVersion(version string) bool {
627 return strings.HasSuffix(version, workspaceModuleVersion)
630 func WorkspaceModuleVersion(majorVersion string) string {
631 // Use the highest compatible major version to avoid unwanted upgrades.
632 // See the comment on workspaceModuleVersion.
633 if majorVersion == "v0" {
636 return majorVersion + workspaceModuleVersion