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.
16 "golang.org/x/tools/go/analysis"
17 "golang.org/x/tools/go/analysis/passes/asmdecl"
18 "golang.org/x/tools/go/analysis/passes/assign"
19 "golang.org/x/tools/go/analysis/passes/atomic"
20 "golang.org/x/tools/go/analysis/passes/atomicalign"
21 "golang.org/x/tools/go/analysis/passes/bools"
22 "golang.org/x/tools/go/analysis/passes/buildtag"
23 "golang.org/x/tools/go/analysis/passes/cgocall"
24 "golang.org/x/tools/go/analysis/passes/composite"
25 "golang.org/x/tools/go/analysis/passes/copylock"
26 "golang.org/x/tools/go/analysis/passes/deepequalerrors"
27 "golang.org/x/tools/go/analysis/passes/errorsas"
28 "golang.org/x/tools/go/analysis/passes/fieldalignment"
29 "golang.org/x/tools/go/analysis/passes/httpresponse"
30 "golang.org/x/tools/go/analysis/passes/ifaceassert"
31 "golang.org/x/tools/go/analysis/passes/loopclosure"
32 "golang.org/x/tools/go/analysis/passes/lostcancel"
33 "golang.org/x/tools/go/analysis/passes/nilfunc"
34 "golang.org/x/tools/go/analysis/passes/printf"
35 "golang.org/x/tools/go/analysis/passes/shadow"
36 "golang.org/x/tools/go/analysis/passes/shift"
37 "golang.org/x/tools/go/analysis/passes/sortslice"
38 "golang.org/x/tools/go/analysis/passes/stdmethods"
39 "golang.org/x/tools/go/analysis/passes/stringintconv"
40 "golang.org/x/tools/go/analysis/passes/structtag"
41 "golang.org/x/tools/go/analysis/passes/testinggoroutine"
42 "golang.org/x/tools/go/analysis/passes/tests"
43 "golang.org/x/tools/go/analysis/passes/unmarshal"
44 "golang.org/x/tools/go/analysis/passes/unreachable"
45 "golang.org/x/tools/go/analysis/passes/unsafeptr"
46 "golang.org/x/tools/go/analysis/passes/unusedresult"
47 "golang.org/x/tools/internal/lsp/analysis/fillreturns"
48 "golang.org/x/tools/internal/lsp/analysis/fillstruct"
49 "golang.org/x/tools/internal/lsp/analysis/nonewvars"
50 "golang.org/x/tools/internal/lsp/analysis/noresultvalues"
51 "golang.org/x/tools/internal/lsp/analysis/simplifycompositelit"
52 "golang.org/x/tools/internal/lsp/analysis/simplifyrange"
53 "golang.org/x/tools/internal/lsp/analysis/simplifyslice"
54 "golang.org/x/tools/internal/lsp/analysis/undeclaredname"
55 "golang.org/x/tools/internal/lsp/analysis/unusedparams"
56 "golang.org/x/tools/internal/lsp/diff"
57 "golang.org/x/tools/internal/lsp/diff/myers"
58 "golang.org/x/tools/internal/lsp/protocol"
59 errors "golang.org/x/xerrors"
64 defaultOptions *Options
67 // DefaultOptions is the options that are used for Gopls execution independent
68 // of any externally provided configuration (LSP initialization, command
70 func DefaultOptions() *Options {
71 optionsOnce.Do(func() {
73 for _, c := range Commands {
74 commands = append(commands, c.ID())
76 defaultOptions = &Options{
77 ClientOptions: ClientOptions{
78 InsertTextFormat: protocol.PlainTextTextFormat,
79 PreferredContentFormat: protocol.Markdown,
80 ConfigurationSupported: true,
81 DynamicConfigurationSupported: true,
82 DynamicWatchedFilesSupported: true,
83 LineFoldingOnly: false,
84 HierarchicalDocumentSymbolSupport: true,
86 ServerOptions: ServerOptions{
87 SupportedCodeActions: map[FileKind]map[protocol.CodeActionKind]bool{
89 protocol.SourceFixAll: true,
90 protocol.SourceOrganizeImports: true,
91 protocol.QuickFix: true,
92 protocol.RefactorRewrite: true,
93 protocol.RefactorExtract: true,
96 protocol.SourceOrganizeImports: true,
100 SupportedCommands: commands,
102 UserOptions: UserOptions{
103 BuildOptions: BuildOptions{
104 ExpandWorkspaceToModule: true,
105 ExperimentalPackageCacheKey: true,
107 UIOptions: UIOptions{
108 DiagnosticOptions: DiagnosticOptions{
109 ExperimentalDiagnosticsDelay: 250 * time.Millisecond,
110 Annotations: map[Annotation]bool{
117 DocumentationOptions: DocumentationOptions{
118 HoverKind: FullDocumentation,
119 LinkTarget: "pkg.go.dev",
122 NavigationOptions: NavigationOptions{
123 ImportShortcut: Both,
124 SymbolMatcher: SymbolFuzzy,
125 SymbolStyle: DynamicSymbols,
127 CompletionOptions: CompletionOptions{
129 CompletionBudget: 100 * time.Millisecond,
131 Codelenses: map[string]bool{
132 CommandGenerate.Name: true,
133 CommandRegenerateCgo.Name: true,
134 CommandTidy.Name: true,
135 CommandToggleDetails.Name: false,
136 CommandUpgradeDependency.Name: true,
137 CommandVendor.Name: true,
141 InternalOptions: InternalOptions{
142 LiteralCompletions: true,
144 CompleteUnimported: true,
145 CompletionDocumentation: true,
146 DeepCompletion: true,
149 ComputeEdits: myers.ComputeEdits,
150 URLRegexp: urlRegexp(),
151 DefaultAnalyzers: defaultAnalyzers(),
152 TypeErrorAnalyzers: typeErrorAnalyzers(),
153 ConvenienceAnalyzers: convenienceAnalyzers(),
154 StaticcheckAnalyzers: map[string]Analyzer{},
159 return defaultOptions
162 // Options holds various configuration that affects Gopls execution, organized
163 // by the nature or origin of the settings.
164 type Options struct {
172 // ClientOptions holds LSP-specific configuration that is provided by the
174 type ClientOptions struct {
175 InsertTextFormat protocol.InsertTextFormat
176 ConfigurationSupported bool
177 DynamicConfigurationSupported bool
178 DynamicWatchedFilesSupported bool
179 PreferredContentFormat protocol.MarkupKind
181 HierarchicalDocumentSymbolSupport bool
182 SemanticTypes []string
183 SemanticMods []string
186 // ServerOptions holds LSP-specific configuration that is provided by the
188 type ServerOptions struct {
189 SupportedCodeActions map[FileKind]map[protocol.CodeActionKind]bool
190 SupportedCommands []string
193 type BuildOptions struct {
194 // BuildFlags is the set of flags passed on to the build system when invoked.
195 // It is applied to queries like `go list`, which is used when discovering files.
196 // The most common use is to set `-tags`.
199 // Env adds environment variables to external commands run by `gopls`, most notably `go list`.
200 Env map[string]string
202 // DirectoryFilters can be used to exclude unwanted directories from the
203 // workspace. By default, all directories are included. Filters are an
204 // operator, `+` to include and `-` to exclude, followed by a path prefix
205 // relative to the workspace folder. They are evaluated in order, and
206 // the last filter that applies to a path controls whether it is included.
207 // The path prefix can be empty, so an initial `-` excludes everything.
210 // Exclude node_modules: `-node_modules`
211 // Include only project_a: `-` (exclude everything), `+project_a`
212 // Include only project_a, but not node_modules inside it: `-`, `+project_a`, `-project_a/node_modules`
213 DirectoryFilters []string
215 // ExpandWorkspaceToModule instructs `gopls` to adjust the scope of the
216 // workspace to find the best available module root. `gopls` first looks for
217 // a go.mod file in any parent directory of the workspace folder, expanding
218 // the scope to that directory if it exists. If no viable parent directory is
219 // found, gopls will check if there is exactly one child directory containing
220 // a go.mod file, narrowing the scope to that directory if it exists.
221 ExpandWorkspaceToModule bool `status:"experimental"`
223 // ExperimentalWorkspaceModule opts a user into the experimental support
224 // for multi-module workspaces.
225 ExperimentalWorkspaceModule bool `status:"experimental"`
227 // ExperimentalPackageCacheKey controls whether to use a coarser cache key
228 // for package type information to increase cache hits. This setting removes
229 // the user's environment, build flags, and working directory from the cache
230 // key, which should be a safe change as all relevant inputs into the type
231 // checking pass are already hashed into the key. This is temporarily guarded
232 // by an experiment because caching behavior is subtle and difficult to
233 // comprehensively test.
234 ExperimentalPackageCacheKey bool `status:"experimental"`
236 // AllowModfileModifications disables -mod=readonly, allowing imports from
237 // out-of-scope modules. This option will eventually be removed.
238 AllowModfileModifications bool `status:"experimental"`
240 // AllowImplicitNetworkAccess disables GOPROXY=off, allowing implicit module
241 // downloads rather than requiring user action. This option will eventually
243 AllowImplicitNetworkAccess bool `status:"experimental"`
246 type UIOptions struct {
252 // Codelenses overrides the enabled/disabled state of code lenses. See the
253 // "Code Lenses" section of the
254 // [Settings page](https://github.com/golang/tools/blob/master/gopls/doc/settings.md)
255 // for the list of supported lenses.
263 // "generate": false, // Don't show the `go generate` lens.
264 // "gc_details": true // Show a code lens toggling the display of gc's choices.
269 Codelenses map[string]bool
271 // SemanticTokens controls whether the LSP server will send
272 // semantic tokens to the client.
273 SemanticTokens bool `status:"experimental"`
276 type CompletionOptions struct {
277 // Placeholders enables placeholders for function parameters or struct
278 // fields in completion responses.
281 // CompletionBudget is the soft latency goal for completion requests. Most
282 // requests finish in a couple milliseconds, but in some cases deep
283 // completions can take much longer. As we use up our budget we
284 // dynamically reduce the search scope to ensure we return timely
285 // results. Zero means unlimited.
286 CompletionBudget time.Duration `status:"debug"`
288 // Matcher sets the algorithm that is used when calculating completion
290 Matcher Matcher `status:"advanced"`
293 type DocumentationOptions struct {
294 // HoverKind controls the information that appears in the hover text.
295 // SingleLine and Structured are intended for use only by authors of editor plugins.
298 // LinkTarget controls where documentation links go.
299 // It might be one of:
304 // If company chooses to use its own `godoc.org`, its address can be used as well.
307 // LinksInHover toggles the presence of links to documentation in hover.
311 type FormattingOptions struct {
312 // Local is the equivalent of the `goimports -local` flag, which puts
313 // imports beginning with this string after third-party packages. It should
314 // be the prefix of the import path whose imports should be grouped
318 // Gofumpt indicates if we should run gofumpt formatting.
322 type DiagnosticOptions struct {
323 // Analyses specify analyses that the user would like to enable or disable.
324 // A map of the names of analysis passes that should be enabled/disabled.
325 // A full list of analyzers that gopls uses can be found
326 // [here](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md).
333 // "unreachable": false, // Disable the unreachable analyzer.
334 // "unusedparams": true // Enable the unusedparams analyzer.
338 Analyses map[string]bool
340 // Staticcheck enables additional analyses from staticcheck.io.
341 Staticcheck bool `status:"experimental"`
343 // Annotations specifies the various kinds of optimization diagnostics
344 // that should be reported by the gc_details command.
345 Annotations map[Annotation]bool `status:"experimental"`
347 // ExperimentalDiagnosticsDelay controls the amount of time that gopls waits
348 // after the most recent file modification before computing deep diagnostics.
349 // Simple diagnostics (parsing and type-checking) are always run immediately
350 // on recently modified packages.
352 // This option must be set to a valid duration string, for example `"250ms"`.
353 ExperimentalDiagnosticsDelay time.Duration `status:"experimental"`
356 type NavigationOptions struct {
357 // ImportShortcut specifies whether import statements should link to
358 // documentation or go to definitions.
359 ImportShortcut ImportShortcut
361 // SymbolMatcher sets the algorithm that is used when finding workspace symbols.
362 SymbolMatcher SymbolMatcher `status:"advanced"`
364 // SymbolStyle controls how symbols are qualified in symbol responses.
371 // "symbolStyle": "dynamic",
375 SymbolStyle SymbolStyle `status:"advanced"`
378 // UserOptions holds custom Gopls configuration (not part of the LSP) that is
379 // modified by the client.
380 type UserOptions struct {
385 // VerboseOutput enables additional debug logging.
386 VerboseOutput bool `status:"debug"`
389 // EnvSlice returns Env as a slice of k=v strings.
390 func (u *UserOptions) EnvSlice() []string {
392 for k, v := range u.Env {
393 result = append(result, fmt.Sprintf("%v=%v", k, v))
398 // SetEnvSlice sets Env from a slice of k=v strings.
399 func (u *UserOptions) SetEnvSlice(env []string) {
400 u.Env = map[string]string{}
401 for _, kv := range env {
402 split := strings.SplitN(kv, "=", 2)
406 u.Env[split[0]] = split[1]
410 // Hooks contains configuration that is provided to the Gopls command by the
415 ComputeEdits diff.ComputeEdits
416 URLRegexp *regexp.Regexp
417 GofumptFormat func(ctx context.Context, src []byte) ([]byte, error)
418 DefaultAnalyzers map[string]Analyzer
419 TypeErrorAnalyzers map[string]Analyzer
420 ConvenienceAnalyzers map[string]Analyzer
421 StaticcheckAnalyzers map[string]Analyzer
424 // InternalOptions contains settings that are not intended for use by the
425 // average user. These may be settings used by tests or outdated settings that
426 // will soon be deprecated. Some of these settings may not even be configurable
428 type InternalOptions struct {
429 // LiteralCompletions controls whether literal candidates such as
430 // "&someStruct{}" are offered. Tests disable this flag to simplify
431 // their expected values.
432 LiteralCompletions bool
434 // VerboseWorkDoneProgress controls whether the LSP server should send
435 // progress reports for all work done outside the scope of an RPC.
436 // Used by the regression tests.
437 VerboseWorkDoneProgress bool
439 // The following options were previously available to users, but they
440 // really shouldn't be configured by anyone other than "power users".
442 // CompletionDocumentation enables documentation with completion results.
443 CompletionDocumentation bool
445 // CompleteUnimported enables completion for packages that you do not
447 CompleteUnimported bool
449 // DeepCompletion enables the ability to return completions from deep
450 // inside relevant entities, rather than just the locally accessible ones.
452 // Consider this example:
459 // type wrapString struct {
464 // x := wrapString{"hello world"}
469 // At the location of the `<>` in this program, deep completion would suggest the result `x.str`.
472 // TempModfile controls the use of the -modfile flag in Go 1.14.
476 type ImportShortcut string
479 Both ImportShortcut = "Both"
480 Link ImportShortcut = "Link"
481 Definition ImportShortcut = "Definition"
484 func (s ImportShortcut) ShowLinks() bool {
485 return s == Both || s == Link
488 func (s ImportShortcut) ShowDefinition() bool {
489 return s == Both || s == Definition
495 Fuzzy Matcher = "Fuzzy"
496 CaseInsensitive Matcher = "CaseInsensitive"
497 CaseSensitive Matcher = "CaseSensitive"
500 type SymbolMatcher string
503 SymbolFuzzy SymbolMatcher = "Fuzzy"
504 SymbolCaseInsensitive SymbolMatcher = "CaseInsensitive"
505 SymbolCaseSensitive SymbolMatcher = "CaseSensitive"
508 type SymbolStyle string
511 // PackageQualifiedSymbols is package qualified symbols i.e.
513 PackageQualifiedSymbols SymbolStyle = "Package"
514 // FullyQualifiedSymbols is fully qualified symbols, i.e.
515 // "path/to/pkg.Foo.Field".
516 FullyQualifiedSymbols SymbolStyle = "Full"
517 // DynamicSymbols uses whichever qualifier results in the highest scoring
518 // match for the given symbol query. Here a "qualifier" is any "/" or "."
519 // delimited suffix of the fully qualified symbol. i.e. "to/pkg.Foo.Field" or
521 DynamicSymbols SymbolStyle = "Dynamic"
524 type HoverKind string
527 SingleLine HoverKind = "SingleLine"
528 NoDocumentation HoverKind = "NoDocumentation"
529 SynopsisDocumentation HoverKind = "SynopsisDocumentation"
530 FullDocumentation HoverKind = "FullDocumentation"
532 // Structured is an experimental setting that returns a structured hover format.
533 // This format separates the signature from the documentation, so that the client
534 // can do more manipulation of these fields.
536 // This should only be used by clients that support this behavior.
537 Structured HoverKind = "Structured"
540 type OptionResults []OptionResult
542 type OptionResult struct {
554 OptionHandled = OptionState(iota)
559 type LinkTarget string
561 func SetOptions(options *Options, opts interface{}) OptionResults {
562 var results OptionResults
563 switch opts := opts.(type) {
565 case map[string]interface{}:
566 // If the user's settings contains "allExperiments", set that first,
567 // and then let them override individual settings independently.
568 var enableExperiments bool
569 for name, value := range opts {
570 if b, ok := value.(bool); name == "allExperiments" && ok && b {
571 enableExperiments = true
572 options.enableAllExperiments()
575 seen := map[string]struct{}{}
576 for name, value := range opts {
577 results = append(results, options.set(name, value, seen))
579 // Finally, enable any experimental features that are specified in
580 // maps, which allows users to individually toggle them on or off.
581 if enableExperiments {
582 options.enableAllExperimentMaps()
585 results = append(results, OptionResult{
587 Error: errors.Errorf("Invalid options type %T", opts),
593 func (o *Options) ForClientCapabilities(caps protocol.ClientCapabilities) {
594 // Check if the client supports snippets in completion items.
595 if c := caps.TextDocument.Completion; c.CompletionItem.SnippetSupport {
596 o.InsertTextFormat = protocol.SnippetTextFormat
598 // Check if the client supports configuration messages.
599 o.ConfigurationSupported = caps.Workspace.Configuration
600 o.DynamicConfigurationSupported = caps.Workspace.DidChangeConfiguration.DynamicRegistration
601 o.DynamicWatchedFilesSupported = caps.Workspace.DidChangeWatchedFiles.DynamicRegistration
603 // Check which types of content format are supported by this client.
604 if hover := caps.TextDocument.Hover; len(hover.ContentFormat) > 0 {
605 o.PreferredContentFormat = hover.ContentFormat[0]
607 // Check if the client supports only line folding.
608 fr := caps.TextDocument.FoldingRange
609 o.LineFoldingOnly = fr.LineFoldingOnly
610 // Check if the client supports hierarchical document symbols.
611 o.HierarchicalDocumentSymbolSupport = caps.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport
612 // Check if the client supports semantic tokens
613 o.SemanticTypes = caps.TextDocument.SemanticTokens.TokenTypes
614 o.SemanticMods = caps.TextDocument.SemanticTokens.TokenModifiers
615 // we don't need Requests, as we support full functionality
616 // we don't need Formats, as there is only one, for now
619 func (o *Options) Clone() *Options {
621 ClientOptions: o.ClientOptions,
622 InternalOptions: o.InternalOptions,
624 GoDiff: o.Hooks.GoDiff,
625 ComputeEdits: o.Hooks.ComputeEdits,
626 GofumptFormat: o.GofumptFormat,
627 URLRegexp: o.URLRegexp,
629 ServerOptions: o.ServerOptions,
630 UserOptions: o.UserOptions,
632 // Fully clone any slice or map fields. Only Hooks, ExperimentalOptions,
633 // and UserOptions can be modified.
634 copyStringMap := func(src map[string]bool) map[string]bool {
635 dst := make(map[string]bool)
636 for k, v := range src {
641 result.Analyses = copyStringMap(o.Analyses)
642 result.Codelenses = copyStringMap(o.Codelenses)
644 copySlice := func(src []string) []string {
645 dst := make([]string, len(src))
649 result.SetEnvSlice(o.EnvSlice())
650 result.BuildFlags = copySlice(o.BuildFlags)
651 result.DirectoryFilters = copySlice(o.DirectoryFilters)
653 copyAnalyzerMap := func(src map[string]Analyzer) map[string]Analyzer {
654 dst := make(map[string]Analyzer)
655 for k, v := range src {
660 result.DefaultAnalyzers = copyAnalyzerMap(o.DefaultAnalyzers)
661 result.TypeErrorAnalyzers = copyAnalyzerMap(o.TypeErrorAnalyzers)
662 result.ConvenienceAnalyzers = copyAnalyzerMap(o.ConvenienceAnalyzers)
663 result.StaticcheckAnalyzers = copyAnalyzerMap(o.StaticcheckAnalyzers)
667 func (o *Options) AddStaticcheckAnalyzer(a *analysis.Analyzer) {
668 o.StaticcheckAnalyzers[a.Name] = Analyzer{Analyzer: a, Enabled: true}
671 // enableAllExperiments turns on all of the experimental "off-by-default"
672 // features offered by gopls. Any experimental features specified in maps
673 // should be enabled in enableAllExperimentMaps.
674 func (o *Options) enableAllExperiments() {
675 // There are currently no experimental features in development.
678 func (o *Options) enableAllExperimentMaps() {
679 if _, ok := o.Codelenses[CommandToggleDetails.Name]; !ok {
680 o.Codelenses[CommandToggleDetails.Name] = true
682 if _, ok := o.Analyses[unusedparams.Analyzer.Name]; !ok {
683 o.Analyses[unusedparams.Analyzer.Name] = true
687 func (o *Options) set(name string, value interface{}, seen map[string]struct{}) OptionResult {
688 // Flatten the name in case we get options with a hierarchy.
689 split := strings.Split(name, ".")
690 name = split[len(split)-1]
692 result := OptionResult{Name: name, Value: value}
693 if _, ok := seen[name]; ok {
694 result.errorf("duplicate configuration for %s", name)
696 seen[name] = struct{}{}
700 menv, ok := value.(map[string]interface{})
702 result.errorf("invalid type %T, expect map", value)
706 o.Env = make(map[string]string)
708 for k, v := range menv {
709 o.Env[k] = fmt.Sprint(v)
713 iflags, ok := value.([]interface{})
715 result.errorf("invalid type %T, expect list", value)
718 flags := make([]string, 0, len(iflags))
719 for _, flag := range iflags {
720 flags = append(flags, fmt.Sprintf("%s", flag))
723 case "directoryFilters":
724 ifilters, ok := value.([]interface{})
726 result.errorf("invalid type %T, expect list", value)
730 for _, ifilter := range ifilters {
731 filter := fmt.Sprint(ifilter)
732 if filter[0] != '+' && filter[0] != '-' {
733 result.errorf("invalid filter %q, must start with + or -", filter)
736 filters = append(filters, filepath.FromSlash(filter))
738 o.DirectoryFilters = filters
739 case "completionDocumentation":
740 result.setBool(&o.CompletionDocumentation)
741 case "usePlaceholders":
742 result.setBool(&o.UsePlaceholders)
743 case "deepCompletion":
744 result.setBool(&o.DeepCompletion)
745 case "completeUnimported":
746 result.setBool(&o.CompleteUnimported)
747 case "completionBudget":
748 result.setDuration(&o.CompletionBudget)
750 if s, ok := result.asOneOf(
752 string(CaseSensitive),
753 string(CaseInsensitive),
755 o.Matcher = Matcher(s)
758 case "symbolMatcher":
759 if s, ok := result.asOneOf(
761 string(SymbolCaseInsensitive),
762 string(SymbolCaseSensitive),
764 o.SymbolMatcher = SymbolMatcher(s)
768 if s, ok := result.asOneOf(
769 string(FullyQualifiedSymbols),
770 string(PackageQualifiedSymbols),
771 string(DynamicSymbols),
773 o.SymbolStyle = SymbolStyle(s)
777 if s, ok := result.asOneOf(
778 string(NoDocumentation),
780 string(SynopsisDocumentation),
781 string(FullDocumentation),
784 o.HoverKind = HoverKind(s)
788 result.setString(&o.LinkTarget)
791 result.setBool(&o.LinksInHover)
793 case "importShortcut":
794 if s, ok := result.asOneOf(string(Both), string(Link), string(Definition)); ok {
795 o.ImportShortcut = ImportShortcut(s)
799 result.setBoolMap(&o.Analyses)
802 result.setAnnotationMap(&o.Annotations)
804 case "codelenses", "codelens":
805 var lensOverrides map[string]bool
806 result.setBoolMap(&lensOverrides)
807 if result.Error == nil {
808 if o.Codelenses == nil {
809 o.Codelenses = make(map[string]bool)
811 for lens, enabled := range lensOverrides {
812 o.Codelenses[lens] = enabled
816 // codelens is deprecated, but still works for now.
817 // TODO(rstambler): Remove this for the gopls/v0.7.0 release.
818 if name == "codelens" {
819 result.State = OptionDeprecated
820 result.Replacement = "codelenses"
824 result.setBool(&o.Staticcheck)
827 result.setString(&o.Local)
829 case "verboseOutput":
830 result.setBool(&o.VerboseOutput)
832 case "verboseWorkDoneProgress":
833 result.setBool(&o.VerboseWorkDoneProgress)
836 result.setBool(&o.TempModfile)
839 result.setBool(&o.Gofumpt)
841 case "semanticTokens":
842 result.setBool(&o.SemanticTokens)
844 case "expandWorkspaceToModule":
845 result.setBool(&o.ExpandWorkspaceToModule)
847 case "experimentalWorkspaceModule":
848 result.setBool(&o.ExperimentalWorkspaceModule)
850 case "experimentalDiagnosticsDelay":
851 result.setDuration(&o.ExperimentalDiagnosticsDelay)
853 case "experimentalPackageCacheKey":
854 result.setBool(&o.ExperimentalPackageCacheKey)
856 case "allowModfileModifications":
857 result.setBool(&o.AllowModfileModifications)
859 case "allowImplicitNetworkAccess":
860 result.setBool(&o.AllowImplicitNetworkAccess)
862 case "allExperiments":
863 // This setting should be handled before all of the other options are
864 // processed, so do nothing here.
866 // Replaced settings.
867 case "experimentalDisabledAnalyses":
868 result.State = OptionDeprecated
869 result.Replacement = "analyses"
871 case "disableDeepCompletion":
872 result.State = OptionDeprecated
873 result.Replacement = "deepCompletion"
875 case "disableFuzzyMatching":
876 result.State = OptionDeprecated
877 result.Replacement = "fuzzyMatching"
879 case "wantCompletionDocumentation":
880 result.State = OptionDeprecated
881 result.Replacement = "completionDocumentation"
883 case "wantUnimportedCompletions":
884 result.State = OptionDeprecated
885 result.Replacement = "completeUnimported"
887 case "fuzzyMatching":
888 result.State = OptionDeprecated
889 result.Replacement = "matcher"
891 case "caseSensitiveCompletion":
892 result.State = OptionDeprecated
893 result.Replacement = "matcher"
895 // Deprecated settings.
896 case "wantSuggestedFixes":
897 result.State = OptionDeprecated
899 case "noIncrementalSync":
900 result.State = OptionDeprecated
902 case "watchFileChanges":
903 result.State = OptionDeprecated
906 result.State = OptionDeprecated
909 result.State = OptionUnexpected
914 func (r *OptionResult) errorf(msg string, values ...interface{}) {
915 prefix := fmt.Sprintf("parsing setting %q: ", r.Name)
916 r.Error = errors.Errorf(prefix+msg, values...)
919 func (r *OptionResult) asBool() (bool, bool) {
920 b, ok := r.Value.(bool)
922 r.errorf("invalid type %T, expect bool", r.Value)
928 func (r *OptionResult) setBool(b *bool) {
929 if v, ok := r.asBool(); ok {
934 func (r *OptionResult) setDuration(d *time.Duration) {
935 if v, ok := r.asString(); ok {
936 parsed, err := time.ParseDuration(v)
938 r.errorf("failed to parse duration %q: %v", v, err)
945 func (r *OptionResult) setBoolMap(bm *map[string]bool) {
950 func (r *OptionResult) setAnnotationMap(bm *map[Annotation]bool) {
955 // Default to everything enabled by default.
956 m := make(map[Annotation]bool)
957 for k, enabled := range all {
966 // In case of an error, process any legacy values.
970 r.errorf(`"noEscape" is deprecated, set "Escape: false" instead`)
973 r.errorf(`"noNilcheck" is deprecated, set "Nil: false" instead`)
976 r.errorf(`"noInline" is deprecated, set "Inline: false" instead`)
979 r.errorf(`"noBounds" is deprecated, set "Bounds: false" instead`)
981 r.errorf(err.Error())
985 m[Annotation(a)] = enabled
990 func (r *OptionResult) asBoolMap() map[string]bool {
991 all, ok := r.Value.(map[string]interface{})
993 r.errorf("invalid type %T for map[string]bool option", r.Value)
996 m := make(map[string]bool)
997 for a, enabled := range all {
998 if enabled, ok := enabled.(bool); ok {
1001 r.errorf("invalid type %T for map key %q", enabled, a)
1008 func (r *OptionResult) asString() (string, bool) {
1009 b, ok := r.Value.(string)
1011 r.errorf("invalid type %T, expect string", r.Value)
1017 func (r *OptionResult) asOneOf(options ...string) (string, bool) {
1018 s, ok := r.asString()
1022 s, err := asOneOf(s, options...)
1024 r.errorf(err.Error())
1026 return s, err == nil
1029 func asOneOf(str string, options ...string) (string, error) {
1030 lower := strings.ToLower(str)
1031 for _, opt := range options {
1032 if strings.ToLower(opt) == lower {
1036 return "", fmt.Errorf("invalid option %q for enum", str)
1039 func (r *OptionResult) setString(s *string) {
1040 if v, ok := r.asString(); ok {
1045 // EnabledAnalyzers returns all of the analyzers enabled for the given
1047 func EnabledAnalyzers(snapshot Snapshot) (analyzers []Analyzer) {
1048 for _, a := range snapshot.View().Options().DefaultAnalyzers {
1049 if a.IsEnabled(snapshot.View()) {
1050 analyzers = append(analyzers, a)
1053 for _, a := range snapshot.View().Options().TypeErrorAnalyzers {
1054 if a.IsEnabled(snapshot.View()) {
1055 analyzers = append(analyzers, a)
1058 for _, a := range snapshot.View().Options().ConvenienceAnalyzers {
1059 if a.IsEnabled(snapshot.View()) {
1060 analyzers = append(analyzers, a)
1063 for _, a := range snapshot.View().Options().StaticcheckAnalyzers {
1064 if a.IsEnabled(snapshot.View()) {
1065 analyzers = append(analyzers, a)
1071 func typeErrorAnalyzers() map[string]Analyzer {
1072 return map[string]Analyzer{
1073 fillreturns.Analyzer.Name: {
1074 Analyzer: fillreturns.Analyzer,
1075 FixesError: fillreturns.FixesError,
1076 HighConfidence: true,
1079 nonewvars.Analyzer.Name: {
1080 Analyzer: nonewvars.Analyzer,
1081 FixesError: nonewvars.FixesError,
1084 noresultvalues.Analyzer.Name: {
1085 Analyzer: noresultvalues.Analyzer,
1086 FixesError: noresultvalues.FixesError,
1089 undeclaredname.Analyzer.Name: {
1090 Analyzer: undeclaredname.Analyzer,
1091 FixesError: undeclaredname.FixesError,
1092 Command: CommandUndeclaredName,
1098 func convenienceAnalyzers() map[string]Analyzer {
1099 return map[string]Analyzer{
1100 fillstruct.Analyzer.Name: {
1101 Analyzer: fillstruct.Analyzer,
1102 Command: CommandFillStruct,
1108 func defaultAnalyzers() map[string]Analyzer {
1109 return map[string]Analyzer{
1110 // The traditional vet suite:
1111 asmdecl.Analyzer.Name: {Analyzer: asmdecl.Analyzer, Enabled: true},
1112 assign.Analyzer.Name: {Analyzer: assign.Analyzer, Enabled: true},
1113 atomic.Analyzer.Name: {Analyzer: atomic.Analyzer, Enabled: true},
1114 bools.Analyzer.Name: {Analyzer: bools.Analyzer, Enabled: true},
1115 buildtag.Analyzer.Name: {Analyzer: buildtag.Analyzer, Enabled: true},
1116 cgocall.Analyzer.Name: {Analyzer: cgocall.Analyzer, Enabled: true},
1117 composite.Analyzer.Name: {Analyzer: composite.Analyzer, Enabled: true},
1118 copylock.Analyzer.Name: {Analyzer: copylock.Analyzer, Enabled: true},
1119 errorsas.Analyzer.Name: {Analyzer: errorsas.Analyzer, Enabled: true},
1120 httpresponse.Analyzer.Name: {Analyzer: httpresponse.Analyzer, Enabled: true},
1121 ifaceassert.Analyzer.Name: {Analyzer: ifaceassert.Analyzer, Enabled: true},
1122 loopclosure.Analyzer.Name: {Analyzer: loopclosure.Analyzer, Enabled: true},
1123 lostcancel.Analyzer.Name: {Analyzer: lostcancel.Analyzer, Enabled: true},
1124 nilfunc.Analyzer.Name: {Analyzer: nilfunc.Analyzer, Enabled: true},
1125 printf.Analyzer.Name: {Analyzer: printf.Analyzer, Enabled: true},
1126 shift.Analyzer.Name: {Analyzer: shift.Analyzer, Enabled: true},
1127 stdmethods.Analyzer.Name: {Analyzer: stdmethods.Analyzer, Enabled: true},
1128 stringintconv.Analyzer.Name: {Analyzer: stringintconv.Analyzer, Enabled: true},
1129 structtag.Analyzer.Name: {Analyzer: structtag.Analyzer, Enabled: true},
1130 tests.Analyzer.Name: {Analyzer: tests.Analyzer, Enabled: true},
1131 unmarshal.Analyzer.Name: {Analyzer: unmarshal.Analyzer, Enabled: true},
1132 unreachable.Analyzer.Name: {Analyzer: unreachable.Analyzer, Enabled: true},
1133 unsafeptr.Analyzer.Name: {Analyzer: unsafeptr.Analyzer, Enabled: true},
1134 unusedresult.Analyzer.Name: {Analyzer: unusedresult.Analyzer, Enabled: true},
1136 // Non-vet analyzers:
1137 atomicalign.Analyzer.Name: {Analyzer: atomicalign.Analyzer, Enabled: true},
1138 deepequalerrors.Analyzer.Name: {Analyzer: deepequalerrors.Analyzer, Enabled: true},
1139 fieldalignment.Analyzer.Name: {Analyzer: fieldalignment.Analyzer, Enabled: false},
1140 shadow.Analyzer.Name: {Analyzer: shadow.Analyzer, Enabled: false},
1141 sortslice.Analyzer.Name: {Analyzer: sortslice.Analyzer, Enabled: true},
1142 testinggoroutine.Analyzer.Name: {Analyzer: testinggoroutine.Analyzer, Enabled: true},
1143 unusedparams.Analyzer.Name: {Analyzer: unusedparams.Analyzer, Enabled: false},
1146 simplifycompositelit.Analyzer.Name: {Analyzer: simplifycompositelit.Analyzer, Enabled: true, HighConfidence: true},
1147 simplifyrange.Analyzer.Name: {Analyzer: simplifyrange.Analyzer, Enabled: true, HighConfidence: true},
1148 simplifyslice.Analyzer.Name: {Analyzer: simplifyslice.Analyzer, Enabled: true, HighConfidence: true},
1152 func urlRegexp() *regexp.Regexp {
1153 // Ensure links are matched as full words, not anywhere.
1154 re := regexp.MustCompile(`\b(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?\b`)
1159 type APIJSON struct {
1160 Options map[string][]*OptionJSON
1161 Commands []*CommandJSON
1163 Analyzers []*AnalyzerJSON
1166 type OptionJSON struct {
1171 EnumValues []EnumValue
1177 type EnumKeys struct {
1182 type EnumKey struct {
1188 type EnumValue struct {
1193 type CommandJSON struct {
1199 type LensJSON struct {
1205 type AnalyzerJSON struct {