Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / internal / lsp / source / options.go
1 // Copyright 2019 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         "context"
9         "fmt"
10         "regexp"
11         "strings"
12         "sync"
13         "time"
14
15         "golang.org/x/tools/go/analysis"
16         "golang.org/x/tools/go/analysis/passes/asmdecl"
17         "golang.org/x/tools/go/analysis/passes/assign"
18         "golang.org/x/tools/go/analysis/passes/atomic"
19         "golang.org/x/tools/go/analysis/passes/atomicalign"
20         "golang.org/x/tools/go/analysis/passes/bools"
21         "golang.org/x/tools/go/analysis/passes/buildtag"
22         "golang.org/x/tools/go/analysis/passes/cgocall"
23         "golang.org/x/tools/go/analysis/passes/composite"
24         "golang.org/x/tools/go/analysis/passes/copylock"
25         "golang.org/x/tools/go/analysis/passes/deepequalerrors"
26         "golang.org/x/tools/go/analysis/passes/errorsas"
27         "golang.org/x/tools/go/analysis/passes/httpresponse"
28         "golang.org/x/tools/go/analysis/passes/ifaceassert"
29         "golang.org/x/tools/go/analysis/passes/loopclosure"
30         "golang.org/x/tools/go/analysis/passes/lostcancel"
31         "golang.org/x/tools/go/analysis/passes/nilfunc"
32         "golang.org/x/tools/go/analysis/passes/printf"
33         "golang.org/x/tools/go/analysis/passes/shift"
34         "golang.org/x/tools/go/analysis/passes/sortslice"
35         "golang.org/x/tools/go/analysis/passes/stdmethods"
36         "golang.org/x/tools/go/analysis/passes/stringintconv"
37         "golang.org/x/tools/go/analysis/passes/structtag"
38         "golang.org/x/tools/go/analysis/passes/testinggoroutine"
39         "golang.org/x/tools/go/analysis/passes/tests"
40         "golang.org/x/tools/go/analysis/passes/unmarshal"
41         "golang.org/x/tools/go/analysis/passes/unreachable"
42         "golang.org/x/tools/go/analysis/passes/unsafeptr"
43         "golang.org/x/tools/go/analysis/passes/unusedresult"
44         "golang.org/x/tools/internal/lsp/analysis/fillreturns"
45         "golang.org/x/tools/internal/lsp/analysis/fillstruct"
46         "golang.org/x/tools/internal/lsp/analysis/nonewvars"
47         "golang.org/x/tools/internal/lsp/analysis/noresultvalues"
48         "golang.org/x/tools/internal/lsp/analysis/simplifycompositelit"
49         "golang.org/x/tools/internal/lsp/analysis/simplifyrange"
50         "golang.org/x/tools/internal/lsp/analysis/simplifyslice"
51         "golang.org/x/tools/internal/lsp/analysis/undeclaredname"
52         "golang.org/x/tools/internal/lsp/analysis/unusedparams"
53         "golang.org/x/tools/internal/lsp/diff"
54         "golang.org/x/tools/internal/lsp/diff/myers"
55         "golang.org/x/tools/internal/lsp/protocol"
56         errors "golang.org/x/xerrors"
57 )
58
59 var (
60         optionsOnce    sync.Once
61         defaultOptions *Options
62 )
63
64 //go:generate go run golang.org/x/tools/internal/lsp/source/genapijson -output api_json.go
65
66 // DefaultOptions is the options that are used for Gopls execution independent
67 // of any externally provided configuration (LSP initialization, command
68 // invokation, etc.).
69 func DefaultOptions() *Options {
70         optionsOnce.Do(func() {
71                 var commands []string
72                 for _, c := range Commands {
73                         commands = append(commands, c.ID())
74                 }
75                 defaultOptions = &Options{
76                         ClientOptions: ClientOptions{
77                                 InsertTextFormat:                  protocol.PlainTextTextFormat,
78                                 PreferredContentFormat:            protocol.Markdown,
79                                 ConfigurationSupported:            true,
80                                 DynamicConfigurationSupported:     true,
81                                 DynamicWatchedFilesSupported:      true,
82                                 LineFoldingOnly:                   false,
83                                 HierarchicalDocumentSymbolSupport: true,
84                         },
85                         ServerOptions: ServerOptions{
86                                 SupportedCodeActions: map[FileKind]map[protocol.CodeActionKind]bool{
87                                         Go: {
88                                                 protocol.SourceFixAll:          true,
89                                                 protocol.SourceOrganizeImports: true,
90                                                 protocol.QuickFix:              true,
91                                                 protocol.RefactorRewrite:       true,
92                                                 protocol.RefactorExtract:       true,
93                                         },
94                                         Mod: {
95                                                 protocol.SourceOrganizeImports: true,
96                                         },
97                                         Sum: {},
98                                 },
99                                 SupportedCommands: commands,
100                         },
101                         UserOptions: UserOptions{
102                                 HoverKind:  FullDocumentation,
103                                 LinkTarget: "pkg.go.dev",
104                         },
105                         DebuggingOptions: DebuggingOptions{
106                                 CompletionBudget: 100 * time.Millisecond,
107                         },
108                         ExperimentalOptions: ExperimentalOptions{
109                                 TempModfile:             true,
110                                 ExpandWorkspaceToModule: true,
111                                 Codelens: map[string]bool{
112                                         CommandGenerate.Name:          true,
113                                         CommandRegenerateCgo.Name:     true,
114                                         CommandTidy.Name:              true,
115                                         CommandToggleDetails.Name:     false,
116                                         CommandUpgradeDependency.Name: true,
117                                         CommandVendor.Name:            true,
118                                 },
119                                 LinksInHover:            true,
120                                 CompleteUnimported:      true,
121                                 CompletionDocumentation: true,
122                                 DeepCompletion:          true,
123                                 ImportShortcut:          Both,
124                                 Matcher:                 Fuzzy,
125                                 SymbolMatcher:           SymbolFuzzy,
126                                 SymbolStyle:             PackageQualifiedSymbols,
127                         },
128                         InternalOptions: InternalOptions{
129                                 LiteralCompletions: true,
130                         },
131                         Hooks: Hooks{
132                                 ComputeEdits:         myers.ComputeEdits,
133                                 URLRegexp:            urlRegexp(),
134                                 DefaultAnalyzers:     defaultAnalyzers(),
135                                 TypeErrorAnalyzers:   typeErrorAnalyzers(),
136                                 ConvenienceAnalyzers: convenienceAnalyzers(),
137                                 StaticcheckAnalyzers: map[string]Analyzer{},
138                                 GoDiff:               true,
139                         },
140                 }
141         })
142         return defaultOptions
143 }
144
145 // Options holds various configuration that affects Gopls execution, organized
146 // by the nature or origin of the settings.
147 type Options struct {
148         ClientOptions
149         ServerOptions
150         UserOptions
151         DebuggingOptions
152         ExperimentalOptions
153         InternalOptions
154         Hooks
155 }
156
157 // ClientOptions holds LSP-specific configuration that is provided by the
158 // client.
159 type ClientOptions struct {
160         InsertTextFormat                  protocol.InsertTextFormat
161         ConfigurationSupported            bool
162         DynamicConfigurationSupported     bool
163         DynamicWatchedFilesSupported      bool
164         PreferredContentFormat            protocol.MarkupKind
165         LineFoldingOnly                   bool
166         HierarchicalDocumentSymbolSupport bool
167         SemanticTypes                     []string
168         SemanticMods                      []string
169 }
170
171 // ServerOptions holds LSP-specific configuration that is provided by the
172 // server.
173 type ServerOptions struct {
174         SupportedCodeActions map[FileKind]map[protocol.CodeActionKind]bool
175         SupportedCommands    []string
176 }
177
178 // UserOptions holds custom Gopls configuration (not part of the LSP) that is
179 // modified by the client.
180 type UserOptions struct {
181         // BuildFlags is the set of flags passed on to the build system when invoked.
182         // It is applied to queries like `go list`, which is used when discovering files.
183         // The most common use is to set `-tags`.
184         BuildFlags []string
185
186         // Env adds environment variables to external commands run by `gopls`, most notably `go list`.
187         Env map[string]string
188
189         // HoverKind controls the information that appears in the hover text.
190         // SingleLine and Structured are intended for use only by authors of editor plugins.
191         HoverKind HoverKind
192
193         // Placeholders enables placeholders for function parameters or struct fields in completion responses.
194         UsePlaceholders bool
195
196         // LinkTarget controls where documentation links go.
197         // It might be one of:
198         //
199         // * `"godoc.org"`
200         // * `"pkg.go.dev"`
201         //
202         // If company chooses to use its own `godoc.org`, its address can be used as well.
203         LinkTarget string
204
205         // Local is the equivalent of the `goimports -local` flag, which puts imports beginning with this string after 3rd-party packages.
206         // It should be the prefix of the import path whose imports should be grouped separately.
207         Local string
208
209         // Gofumpt indicates if we should run gofumpt formatting.
210         Gofumpt bool
211 }
212
213 // EnvSlice returns Env as a slice of k=v strings.
214 func (u *UserOptions) EnvSlice() []string {
215         var result []string
216         for k, v := range u.Env {
217                 result = append(result, fmt.Sprintf("%v=%v", k, v))
218         }
219         return result
220 }
221
222 // SetEnvSlice sets Env from a slice of k=v strings.
223 func (u *UserOptions) SetEnvSlice(env []string) {
224         u.Env = map[string]string{}
225         for _, kv := range env {
226                 split := strings.SplitN(kv, "=", 2)
227                 if len(split) != 2 {
228                         continue
229                 }
230                 u.Env[split[0]] = split[1]
231         }
232 }
233
234 // Hooks contains configuration that is provided to the Gopls command by the
235 // main package.
236 type Hooks struct {
237         GoDiff               bool
238         ComputeEdits         diff.ComputeEdits
239         URLRegexp            *regexp.Regexp
240         GofumptFormat        func(ctx context.Context, src []byte) ([]byte, error)
241         DefaultAnalyzers     map[string]Analyzer
242         TypeErrorAnalyzers   map[string]Analyzer
243         ConvenienceAnalyzers map[string]Analyzer
244         StaticcheckAnalyzers map[string]Analyzer
245 }
246
247 // ExperimentalOptions defines configuration for features under active
248 // development. WARNING: This configuration will be changed in the future. It
249 // only exists while these features are under development.
250 type ExperimentalOptions struct {
251         // Analyses specify analyses that the user would like to enable or disable.
252         // A map of the names of analysis passes that should be enabled/disabled.
253         // A full list of analyzers that gopls uses can be found [here](analyzers.md)
254         //
255         // Example Usage:
256         // ```json5
257         // ...
258         // "analyses": {
259         //   "unreachable": false, // Disable the unreachable analyzer.
260         //   "unusedparams": true  // Enable the unusedparams analyzer.
261         // }
262         // ...
263         // ```
264         Analyses map[string]bool
265
266         // Codelens overrides the enabled/disabled state of code lenses. See the "Code Lenses"
267         // section of settings.md for the list of supported lenses.
268         //
269         // Example Usage:
270         // ```json5
271         // "gopls": {
272         // ...
273         //   "codelens": {
274         //     "generate": false,  // Don't show the `go generate` lens.
275         //     "gc_details": true  // Show a code lens toggling the display of gc's choices.
276         //   }
277         // ...
278         // }
279         // ```
280         Codelens map[string]bool
281
282         // CompletionDocumentation enables documentation with completion results.
283         CompletionDocumentation bool
284
285         // CompleteUnimported enables completion for packages that you do not currently import.
286         CompleteUnimported bool
287
288         // DeepCompletion enables the ability to return completions from deep inside relevant entities, rather than just the locally accessible ones.
289         //
290         // Consider this example:
291         //
292         // ```go
293         // package main
294         //
295         // import "fmt"
296         //
297         // type wrapString struct {
298         //     str string
299         // }
300         //
301         // func main() {
302         //     x := wrapString{"hello world"}
303         //     fmt.Printf(<>)
304         // }
305         // ```
306         //
307         // At the location of the `<>` in this program, deep completion would suggest the result `x.str`.
308         DeepCompletion bool
309
310         // Matcher sets the algorithm that is used when calculating completion candidates.
311         Matcher Matcher
312
313         // Annotations suppress various kinds of optimization diagnostics
314         // that would be reported by the gc_details command.
315         //  * noNilcheck suppresses display of nilchecks.
316         //  * noEscape suppresses escape choices.
317         //  * noInline suppresses inlining choices.
318         //  * noBounds suppresses bounds checking diagnostics.
319         Annotations map[string]bool
320
321         // Staticcheck enables additional analyses from staticcheck.io.
322         Staticcheck bool
323
324         // SymbolMatcher sets the algorithm that is used when finding workspace symbols.
325         SymbolMatcher SymbolMatcher
326
327         // SymbolStyle controls how symbols are qualified in symbol responses.
328         //
329         // Example Usage:
330         // ```json5
331         // "gopls": {
332         // ...
333         //   "symbolStyle": "dynamic",
334         // ...
335         // }
336         // ```
337         SymbolStyle SymbolStyle
338
339         // LinksInHover toggles the presence of links to documentation in hover.
340         LinksInHover bool
341
342         // TempModfile controls the use of the -modfile flag in Go 1.14.
343         TempModfile bool
344
345         // ImportShortcut specifies whether import statements should link to
346         // documentation or go to definitions.
347         ImportShortcut ImportShortcut
348
349         // VerboseWorkDoneProgress controls whether the LSP server should send
350         // progress reports for all work done outside the scope of an RPC.
351         VerboseWorkDoneProgress bool
352
353         // SemanticTokens controls whether the LSP server will send
354         // semantic tokens to the client.
355         SemanticTokens bool
356
357         // ExpandWorkspaceToModule instructs `gopls` to expand the scope of the workspace to include the
358         // modules containing the workspace folders. Set this to false to avoid loading
359         // your entire module. This is particularly useful for those working in a monorepo.
360         ExpandWorkspaceToModule bool
361
362         // ExperimentalWorkspaceModule opts a user into the experimental support
363         // for multi-module workspaces.
364         ExperimentalWorkspaceModule bool
365
366         // ExperimentalDiagnosticsDelay controls the amount of time that gopls waits
367         // after the most recent file modification before computing deep diagnostics.
368         // Simple diagnostics (parsing and type-checking) are always run immediately
369         // on recently modified packages.
370         //
371         // This option must be set to a valid duration string, for example `"250ms"`.
372         ExperimentalDiagnosticsDelay time.Duration
373
374         // ExperimentalPackageCacheKey controls whether to use a coarser cache key
375         // for package type information to increase cache hits. This setting removes
376         // the user's environment, build flags, and working directory from the cache
377         // key, which should be a safe change as all relevant inputs into the type
378         // checking pass are already hashed into the key. This is temporarily guarded
379         // by an experiment because caching behavior is subtle and difficult to
380         // comprehensively test.
381         ExperimentalPackageCacheKey bool
382 }
383
384 // DebuggingOptions should not affect the logical execution of Gopls, but may
385 // be altered for debugging purposes.
386 type DebuggingOptions struct {
387         // VerboseOutput enables additional debug logging.
388         VerboseOutput bool
389
390         // CompletionBudget is the soft latency goal for completion requests. Most
391         // requests finish in a couple milliseconds, but in some cases deep
392         // completions can take much longer. As we use up our budget we
393         // dynamically reduce the search scope to ensure we return timely
394         // results. Zero means unlimited.
395         CompletionBudget time.Duration
396 }
397
398 // InternalOptions contains settings that are not exposed to the user for various
399 // reasons, e.g. settings used by tests.
400 type InternalOptions struct {
401         // LiteralCompletions controls whether literal candidates such as
402         // "&someStruct{}" are offered. Tests disable this flag to simplify
403         // their expected values.
404         LiteralCompletions bool
405 }
406
407 type ImportShortcut string
408
409 const (
410         Both       ImportShortcut = "Both"
411         Link       ImportShortcut = "Link"
412         Definition ImportShortcut = "Definition"
413 )
414
415 func (s ImportShortcut) ShowLinks() bool {
416         return s == Both || s == Link
417 }
418
419 func (s ImportShortcut) ShowDefinition() bool {
420         return s == Both || s == Definition
421 }
422
423 type Matcher string
424
425 const (
426         Fuzzy           Matcher = "Fuzzy"
427         CaseInsensitive Matcher = "CaseInsensitive"
428         CaseSensitive   Matcher = "CaseSensitive"
429 )
430
431 type SymbolMatcher string
432
433 const (
434         SymbolFuzzy           SymbolMatcher = "Fuzzy"
435         SymbolCaseInsensitive SymbolMatcher = "CaseInsensitive"
436         SymbolCaseSensitive   SymbolMatcher = "CaseSensitive"
437 )
438
439 type SymbolStyle string
440
441 const (
442         // PackageQualifiedSymbols is package qualified symbols i.e.
443         // "pkg.Foo.Field".
444         PackageQualifiedSymbols SymbolStyle = "Package"
445         // FullyQualifiedSymbols is fully qualified symbols, i.e.
446         // "path/to/pkg.Foo.Field".
447         FullyQualifiedSymbols SymbolStyle = "Full"
448         // DynamicSymbols uses whichever qualifier results in the highest scoring
449         // match for the given symbol query. Here a "qualifier" is any "/" or "."
450         // delimited suffix of the fully qualified symbol. i.e. "to/pkg.Foo.Field" or
451         // just "Foo.Field".
452         DynamicSymbols SymbolStyle = "Dynamic"
453 )
454
455 type HoverKind string
456
457 const (
458         SingleLine            HoverKind = "SingleLine"
459         NoDocumentation       HoverKind = "NoDocumentation"
460         SynopsisDocumentation HoverKind = "SynopsisDocumentation"
461         FullDocumentation     HoverKind = "FullDocumentation"
462
463         // Structured is an experimental setting that returns a structured hover format.
464         // This format separates the signature from the documentation, so that the client
465         // can do more manipulation of these fields.
466         //
467         // This should only be used by clients that support this behavior.
468         Structured HoverKind = "Structured"
469 )
470
471 type OptionResults []OptionResult
472
473 type OptionResult struct {
474         Name  string
475         Value interface{}
476         Error error
477
478         State       OptionState
479         Replacement string
480 }
481
482 type OptionState int
483
484 const (
485         OptionHandled = OptionState(iota)
486         OptionDeprecated
487         OptionUnexpected
488 )
489
490 type LinkTarget string
491
492 func SetOptions(options *Options, opts interface{}) OptionResults {
493         var results OptionResults
494         switch opts := opts.(type) {
495         case nil:
496         case map[string]interface{}:
497                 // If the user's settings contains "allExperiments", set that first,
498                 // and then let them override individual settings independently.
499                 var enableExperiments bool
500                 for name, value := range opts {
501                         if b, ok := value.(bool); name == "allExperiments" && ok && b {
502                                 enableExperiments = true
503                                 options.enableAllExperiments()
504                         }
505                 }
506                 for name, value := range opts {
507                         results = append(results, options.set(name, value))
508                 }
509                 // Finally, enable any experimental features that are specified in
510                 // maps, which allows users to individually toggle them on or off.
511                 if enableExperiments {
512                         options.enableAllExperimentMaps()
513                 }
514         default:
515                 results = append(results, OptionResult{
516                         Value: opts,
517                         Error: errors.Errorf("Invalid options type %T", opts),
518                 })
519         }
520         return results
521 }
522
523 func (o *Options) ForClientCapabilities(caps protocol.ClientCapabilities) {
524         // Check if the client supports snippets in completion items.
525         if c := caps.TextDocument.Completion; c.CompletionItem.SnippetSupport {
526                 o.InsertTextFormat = protocol.SnippetTextFormat
527         }
528         // Check if the client supports configuration messages.
529         o.ConfigurationSupported = caps.Workspace.Configuration
530         o.DynamicConfigurationSupported = caps.Workspace.DidChangeConfiguration.DynamicRegistration
531         o.DynamicWatchedFilesSupported = caps.Workspace.DidChangeWatchedFiles.DynamicRegistration
532
533         // Check which types of content format are supported by this client.
534         if hover := caps.TextDocument.Hover; len(hover.ContentFormat) > 0 {
535                 o.PreferredContentFormat = hover.ContentFormat[0]
536         }
537         // Check if the client supports only line folding.
538         fr := caps.TextDocument.FoldingRange
539         o.LineFoldingOnly = fr.LineFoldingOnly
540         // Check if the client supports hierarchical document symbols.
541         o.HierarchicalDocumentSymbolSupport = caps.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport
542         // Check if the client supports semantic tokens
543         o.SemanticTypes = caps.TextDocument.SemanticTokens.TokenTypes
544         o.SemanticMods = caps.TextDocument.SemanticTokens.TokenModifiers
545         // we don't need Requests, as we support full functionality
546         // we don't need Formats, as there is only one, for now
547
548 }
549
550 func (o *Options) Clone() *Options {
551         result := &Options{
552                 ClientOptions:       o.ClientOptions,
553                 DebuggingOptions:    o.DebuggingOptions,
554                 ExperimentalOptions: o.ExperimentalOptions,
555                 InternalOptions:     o.InternalOptions,
556                 Hooks: Hooks{
557                         GoDiff:        o.Hooks.GoDiff,
558                         ComputeEdits:  o.Hooks.ComputeEdits,
559                         GofumptFormat: o.GofumptFormat,
560                         URLRegexp:     o.URLRegexp,
561                 },
562                 ServerOptions: o.ServerOptions,
563                 UserOptions:   o.UserOptions,
564         }
565         // Fully clone any slice or map fields. Only Hooks, ExperimentalOptions,
566         // and UserOptions can be modified.
567         copyStringMap := func(src map[string]bool) map[string]bool {
568                 dst := make(map[string]bool)
569                 for k, v := range src {
570                         dst[k] = v
571                 }
572                 return dst
573         }
574         result.Analyses = copyStringMap(o.Analyses)
575         result.Annotations = copyStringMap(o.Annotations)
576         result.Codelens = copyStringMap(o.Codelens)
577
578         copySlice := func(src []string) []string {
579                 dst := make([]string, len(src))
580                 copy(dst, src)
581                 return dst
582         }
583         result.SetEnvSlice(o.EnvSlice())
584         result.BuildFlags = copySlice(o.BuildFlags)
585
586         copyAnalyzerMap := func(src map[string]Analyzer) map[string]Analyzer {
587                 dst := make(map[string]Analyzer)
588                 for k, v := range src {
589                         dst[k] = v
590                 }
591                 return dst
592         }
593         result.DefaultAnalyzers = copyAnalyzerMap(o.DefaultAnalyzers)
594         result.TypeErrorAnalyzers = copyAnalyzerMap(o.TypeErrorAnalyzers)
595         result.ConvenienceAnalyzers = copyAnalyzerMap(o.ConvenienceAnalyzers)
596         result.StaticcheckAnalyzers = copyAnalyzerMap(o.StaticcheckAnalyzers)
597         return result
598 }
599
600 func (o *Options) AddStaticcheckAnalyzer(a *analysis.Analyzer) {
601         o.StaticcheckAnalyzers[a.Name] = Analyzer{Analyzer: a, Enabled: true}
602 }
603
604 // enableAllExperiments turns on all of the experimental "off-by-default"
605 // features offered by gopls.
606 // Any experimental features specified in maps should be enabled in
607 // enableAllExperimentMaps.
608 func (o *Options) enableAllExperiments() {
609         o.ExperimentalDiagnosticsDelay = 200 * time.Millisecond
610         o.ExperimentalPackageCacheKey = true
611         o.SymbolStyle = DynamicSymbols
612 }
613
614 func (o *Options) enableAllExperimentMaps() {
615         if _, ok := o.Codelens[CommandToggleDetails.Name]; !ok {
616                 o.Codelens[CommandToggleDetails.Name] = true
617         }
618         if _, ok := o.Analyses[unusedparams.Analyzer.Name]; !ok {
619                 o.Analyses[unusedparams.Analyzer.Name] = true
620         }
621 }
622
623 func (o *Options) set(name string, value interface{}) OptionResult {
624         result := OptionResult{Name: name, Value: value}
625         switch name {
626         case "env":
627                 menv, ok := value.(map[string]interface{})
628                 if !ok {
629                         result.errorf("invalid type %T, expect map", value)
630                         break
631                 }
632                 for k, v := range menv {
633                         o.Env[k] = fmt.Sprint(v)
634                 }
635
636         case "buildFlags":
637                 iflags, ok := value.([]interface{})
638                 if !ok {
639                         result.errorf("invalid type %T, expect list", value)
640                         break
641                 }
642                 flags := make([]string, 0, len(iflags))
643                 for _, flag := range iflags {
644                         flags = append(flags, fmt.Sprintf("%s", flag))
645                 }
646                 o.BuildFlags = flags
647
648         case "completionDocumentation":
649                 result.setBool(&o.CompletionDocumentation)
650         case "usePlaceholders":
651                 result.setBool(&o.UsePlaceholders)
652         case "deepCompletion":
653                 result.setBool(&o.DeepCompletion)
654         case "completeUnimported":
655                 result.setBool(&o.CompleteUnimported)
656         case "completionBudget":
657                 result.setDuration(&o.CompletionBudget)
658         case "matcher":
659                 if s, ok := result.asOneOf(
660                         string(Fuzzy),
661                         string(CaseSensitive),
662                         string(CaseInsensitive),
663                 ); ok {
664                         o.Matcher = Matcher(s)
665                 }
666
667         case "symbolMatcher":
668                 if s, ok := result.asOneOf(
669                         string(SymbolFuzzy),
670                         string(SymbolCaseInsensitive),
671                         string(SymbolCaseSensitive),
672                 ); ok {
673                         o.SymbolMatcher = SymbolMatcher(s)
674                 }
675
676         case "symbolStyle":
677                 if s, ok := result.asOneOf(
678                         string(FullyQualifiedSymbols),
679                         string(PackageQualifiedSymbols),
680                         string(DynamicSymbols),
681                 ); ok {
682                         o.SymbolStyle = SymbolStyle(s)
683                 }
684
685         case "hoverKind":
686                 if s, ok := result.asOneOf(
687                         string(NoDocumentation),
688                         string(SingleLine),
689                         string(SynopsisDocumentation),
690                         string(FullDocumentation),
691                         string(Structured),
692                 ); ok {
693                         o.HoverKind = HoverKind(s)
694                 }
695
696         case "linkTarget":
697                 result.setString(&o.LinkTarget)
698
699         case "linksInHover":
700                 result.setBool(&o.LinksInHover)
701
702         case "importShortcut":
703                 if s, ok := result.asOneOf(string(Both), string(Link), string(Definition)); ok {
704                         o.ImportShortcut = ImportShortcut(s)
705                 }
706
707         case "analyses":
708                 result.setBoolMap(&o.Analyses)
709
710         case "annotations":
711                 result.setBoolMap(&o.Annotations)
712                 for k := range o.Annotations {
713                         switch k {
714                         case "noEscape", "noNilcheck", "noInline", "noBounds":
715                                 continue
716                         default:
717                                 result.Name += ":" + k // put mistake(s) in the message
718                                 result.State = OptionUnexpected
719                         }
720                 }
721
722         case "codelens":
723                 var lensOverrides map[string]bool
724                 result.setBoolMap(&lensOverrides)
725                 if result.Error == nil {
726                         if o.Codelens == nil {
727                                 o.Codelens = make(map[string]bool)
728                         }
729                         for lens, enabled := range lensOverrides {
730                                 o.Codelens[lens] = enabled
731                         }
732                 }
733
734         case "staticcheck":
735                 result.setBool(&o.Staticcheck)
736
737         case "local":
738                 result.setString(&o.Local)
739
740         case "verboseOutput":
741                 result.setBool(&o.VerboseOutput)
742
743         case "verboseWorkDoneProgress":
744                 result.setBool(&o.VerboseWorkDoneProgress)
745
746         case "tempModfile":
747                 result.setBool(&o.TempModfile)
748
749         case "gofumpt":
750                 result.setBool(&o.Gofumpt)
751
752         case "semanticTokens":
753                 result.setBool(&o.SemanticTokens)
754
755         case "expandWorkspaceToModule":
756                 result.setBool(&o.ExpandWorkspaceToModule)
757
758         case "experimentalWorkspaceModule":
759                 result.setBool(&o.ExperimentalWorkspaceModule)
760
761         case "experimentalDiagnosticsDelay":
762                 result.setDuration(&o.ExperimentalDiagnosticsDelay)
763
764         case "experimentalPackageCacheKey":
765                 result.setBool(&o.ExperimentalPackageCacheKey)
766
767         case "allExperiments":
768                 // This setting should be handled before all of the other options are
769                 // processed, so do nothing here.
770
771         // Replaced settings.
772         case "experimentalDisabledAnalyses":
773                 result.State = OptionDeprecated
774                 result.Replacement = "analyses"
775
776         case "disableDeepCompletion":
777                 result.State = OptionDeprecated
778                 result.Replacement = "deepCompletion"
779
780         case "disableFuzzyMatching":
781                 result.State = OptionDeprecated
782                 result.Replacement = "fuzzyMatching"
783
784         case "wantCompletionDocumentation":
785                 result.State = OptionDeprecated
786                 result.Replacement = "completionDocumentation"
787
788         case "wantUnimportedCompletions":
789                 result.State = OptionDeprecated
790                 result.Replacement = "completeUnimported"
791
792         case "fuzzyMatching":
793                 result.State = OptionDeprecated
794                 result.Replacement = "matcher"
795
796         case "caseSensitiveCompletion":
797                 result.State = OptionDeprecated
798                 result.Replacement = "matcher"
799
800         // Deprecated settings.
801         case "wantSuggestedFixes":
802                 result.State = OptionDeprecated
803
804         case "noIncrementalSync":
805                 result.State = OptionDeprecated
806
807         case "watchFileChanges":
808                 result.State = OptionDeprecated
809
810         case "go-diff":
811                 result.State = OptionDeprecated
812
813         default:
814                 result.State = OptionUnexpected
815         }
816         return result
817 }
818
819 func (r *OptionResult) errorf(msg string, values ...interface{}) {
820         prefix := fmt.Sprintf("parsing setting %q: ", r.Name)
821         r.Error = errors.Errorf(prefix+msg, values...)
822 }
823
824 func (r *OptionResult) asBool() (bool, bool) {
825         b, ok := r.Value.(bool)
826         if !ok {
827                 r.errorf("invalid type %T, expect bool", r.Value)
828                 return false, false
829         }
830         return b, true
831 }
832
833 func (r *OptionResult) setBool(b *bool) {
834         if v, ok := r.asBool(); ok {
835                 *b = v
836         }
837 }
838
839 func (r *OptionResult) setDuration(d *time.Duration) {
840         if v, ok := r.asString(); ok {
841                 parsed, err := time.ParseDuration(v)
842                 if err != nil {
843                         r.errorf("failed to parse duration %q: %v", v, err)
844                         return
845                 }
846                 *d = parsed
847         }
848 }
849
850 func (r *OptionResult) setBoolMap(bm *map[string]bool) {
851         all, ok := r.Value.(map[string]interface{})
852         if !ok {
853                 r.errorf("invalid type %T for map[string]bool option", r.Value)
854                 return
855         }
856         m := make(map[string]bool)
857         for a, enabled := range all {
858                 if enabled, ok := enabled.(bool); ok {
859                         m[a] = enabled
860                 } else {
861                         r.errorf("invalid type %T for map key %q", enabled, a)
862                         return
863                 }
864         }
865         *bm = m
866 }
867
868 func (r *OptionResult) asString() (string, bool) {
869         b, ok := r.Value.(string)
870         if !ok {
871                 r.errorf("invalid type %T, expect string", r.Value)
872                 return "", false
873         }
874         return b, true
875 }
876
877 func (r *OptionResult) asOneOf(options ...string) (string, bool) {
878         s, ok := r.asString()
879         if !ok {
880                 return "", false
881         }
882         lower := strings.ToLower(s)
883         for _, opt := range options {
884                 if strings.ToLower(opt) == lower {
885                         return opt, true
886                 }
887         }
888         r.errorf("invalid option %q for enum", r.Value)
889         return "", false
890 }
891
892 func (r *OptionResult) setString(s *string) {
893         if v, ok := r.asString(); ok {
894                 *s = v
895         }
896 }
897
898 // EnabledAnalyzers returns all of the analyzers enabled for the given
899 // snapshot.
900 func EnabledAnalyzers(snapshot Snapshot) (analyzers []Analyzer) {
901         for _, a := range snapshot.View().Options().DefaultAnalyzers {
902                 if a.IsEnabled(snapshot.View()) {
903                         analyzers = append(analyzers, a)
904                 }
905         }
906         for _, a := range snapshot.View().Options().TypeErrorAnalyzers {
907                 if a.IsEnabled(snapshot.View()) {
908                         analyzers = append(analyzers, a)
909                 }
910         }
911         for _, a := range snapshot.View().Options().ConvenienceAnalyzers {
912                 if a.IsEnabled(snapshot.View()) {
913                         analyzers = append(analyzers, a)
914                 }
915         }
916         for _, a := range snapshot.View().Options().StaticcheckAnalyzers {
917                 if a.IsEnabled(snapshot.View()) {
918                         analyzers = append(analyzers, a)
919                 }
920         }
921         return analyzers
922 }
923
924 func typeErrorAnalyzers() map[string]Analyzer {
925         return map[string]Analyzer{
926                 fillreturns.Analyzer.Name: {
927                         Analyzer:       fillreturns.Analyzer,
928                         FixesError:     fillreturns.FixesError,
929                         HighConfidence: true,
930                         Enabled:        true,
931                 },
932                 nonewvars.Analyzer.Name: {
933                         Analyzer:   nonewvars.Analyzer,
934                         FixesError: nonewvars.FixesError,
935                         Enabled:    true,
936                 },
937                 noresultvalues.Analyzer.Name: {
938                         Analyzer:   noresultvalues.Analyzer,
939                         FixesError: noresultvalues.FixesError,
940                         Enabled:    true,
941                 },
942                 undeclaredname.Analyzer.Name: {
943                         Analyzer:   undeclaredname.Analyzer,
944                         FixesError: undeclaredname.FixesError,
945                         Command:    CommandUndeclaredName,
946                         Enabled:    true,
947                 },
948         }
949 }
950
951 func convenienceAnalyzers() map[string]Analyzer {
952         return map[string]Analyzer{
953                 fillstruct.Analyzer.Name: {
954                         Analyzer: fillstruct.Analyzer,
955                         Command:  CommandFillStruct,
956                         Enabled:  true,
957                 },
958         }
959 }
960
961 func defaultAnalyzers() map[string]Analyzer {
962         return map[string]Analyzer{
963                 // The traditional vet suite:
964                 asmdecl.Analyzer.Name:       {Analyzer: asmdecl.Analyzer, Enabled: true},
965                 assign.Analyzer.Name:        {Analyzer: assign.Analyzer, Enabled: true},
966                 atomic.Analyzer.Name:        {Analyzer: atomic.Analyzer, Enabled: true},
967                 bools.Analyzer.Name:         {Analyzer: bools.Analyzer, Enabled: true},
968                 buildtag.Analyzer.Name:      {Analyzer: buildtag.Analyzer, Enabled: true},
969                 cgocall.Analyzer.Name:       {Analyzer: cgocall.Analyzer, Enabled: true},
970                 composite.Analyzer.Name:     {Analyzer: composite.Analyzer, Enabled: true},
971                 copylock.Analyzer.Name:      {Analyzer: copylock.Analyzer, Enabled: true},
972                 errorsas.Analyzer.Name:      {Analyzer: errorsas.Analyzer, Enabled: true},
973                 httpresponse.Analyzer.Name:  {Analyzer: httpresponse.Analyzer, Enabled: true},
974                 ifaceassert.Analyzer.Name:   {Analyzer: ifaceassert.Analyzer, Enabled: true},
975                 loopclosure.Analyzer.Name:   {Analyzer: loopclosure.Analyzer, Enabled: true},
976                 lostcancel.Analyzer.Name:    {Analyzer: lostcancel.Analyzer, Enabled: true},
977                 nilfunc.Analyzer.Name:       {Analyzer: nilfunc.Analyzer, Enabled: true},
978                 printf.Analyzer.Name:        {Analyzer: printf.Analyzer, Enabled: true},
979                 shift.Analyzer.Name:         {Analyzer: shift.Analyzer, Enabled: true},
980                 stdmethods.Analyzer.Name:    {Analyzer: stdmethods.Analyzer, Enabled: true},
981                 stringintconv.Analyzer.Name: {Analyzer: stringintconv.Analyzer, Enabled: true},
982                 structtag.Analyzer.Name:     {Analyzer: structtag.Analyzer, Enabled: true},
983                 tests.Analyzer.Name:         {Analyzer: tests.Analyzer, Enabled: true},
984                 unmarshal.Analyzer.Name:     {Analyzer: unmarshal.Analyzer, Enabled: true},
985                 unreachable.Analyzer.Name:   {Analyzer: unreachable.Analyzer, Enabled: true},
986                 unsafeptr.Analyzer.Name:     {Analyzer: unsafeptr.Analyzer, Enabled: true},
987                 unusedresult.Analyzer.Name:  {Analyzer: unusedresult.Analyzer, Enabled: true},
988
989                 // Non-vet analyzers:
990                 atomicalign.Analyzer.Name:      {Analyzer: atomicalign.Analyzer, Enabled: true},
991                 deepequalerrors.Analyzer.Name:  {Analyzer: deepequalerrors.Analyzer, Enabled: true},
992                 sortslice.Analyzer.Name:        {Analyzer: sortslice.Analyzer, Enabled: true},
993                 testinggoroutine.Analyzer.Name: {Analyzer: testinggoroutine.Analyzer, Enabled: true},
994                 unusedparams.Analyzer.Name:     {Analyzer: unusedparams.Analyzer, Enabled: false},
995
996                 // gofmt -s suite:
997                 simplifycompositelit.Analyzer.Name: {Analyzer: simplifycompositelit.Analyzer, Enabled: true, HighConfidence: true},
998                 simplifyrange.Analyzer.Name:        {Analyzer: simplifyrange.Analyzer, Enabled: true, HighConfidence: true},
999                 simplifyslice.Analyzer.Name:        {Analyzer: simplifyslice.Analyzer, Enabled: true, HighConfidence: true},
1000         }
1001 }
1002
1003 func urlRegexp() *regexp.Regexp {
1004         // Ensure links are matched as full words, not anywhere.
1005         re := regexp.MustCompile(`\b(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?\b`)
1006         re.Longest()
1007         return re
1008 }
1009
1010 type APIJSON struct {
1011         Options  map[string][]*OptionJSON
1012         Commands []*CommandJSON
1013         Lenses   []*LensJSON
1014 }
1015
1016 type OptionJSON struct {
1017         Name       string
1018         Type       string
1019         Doc        string
1020         EnumValues []EnumValue
1021         Default    string
1022 }
1023
1024 type EnumValue struct {
1025         Value string
1026         Doc   string
1027 }
1028
1029 type CommandJSON struct {
1030         Command string
1031         Title   string
1032         Doc     string
1033 }
1034
1035 type LensJSON struct {
1036         Lens  string
1037         Title string
1038         Doc   string
1039 }