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.
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"
61 defaultOptions *Options
64 //go:generate go run golang.org/x/tools/internal/lsp/source/genapijson -output api_json.go
66 // DefaultOptions is the options that are used for Gopls execution independent
67 // of any externally provided configuration (LSP initialization, command
69 func DefaultOptions() *Options {
70 optionsOnce.Do(func() {
72 for _, c := range Commands {
73 commands = append(commands, c.ID())
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,
85 ServerOptions: ServerOptions{
86 SupportedCodeActions: map[FileKind]map[protocol.CodeActionKind]bool{
88 protocol.SourceFixAll: true,
89 protocol.SourceOrganizeImports: true,
90 protocol.QuickFix: true,
91 protocol.RefactorRewrite: true,
92 protocol.RefactorExtract: true,
95 protocol.SourceOrganizeImports: true,
99 SupportedCommands: commands,
101 UserOptions: UserOptions{
102 HoverKind: FullDocumentation,
103 LinkTarget: "pkg.go.dev",
105 DebuggingOptions: DebuggingOptions{
106 CompletionBudget: 100 * time.Millisecond,
108 ExperimentalOptions: ExperimentalOptions{
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,
120 CompleteUnimported: true,
121 CompletionDocumentation: true,
122 DeepCompletion: true,
123 ImportShortcut: Both,
125 SymbolMatcher: SymbolFuzzy,
126 SymbolStyle: PackageQualifiedSymbols,
128 InternalOptions: InternalOptions{
129 LiteralCompletions: true,
132 ComputeEdits: myers.ComputeEdits,
133 URLRegexp: urlRegexp(),
134 DefaultAnalyzers: defaultAnalyzers(),
135 TypeErrorAnalyzers: typeErrorAnalyzers(),
136 ConvenienceAnalyzers: convenienceAnalyzers(),
137 StaticcheckAnalyzers: map[string]Analyzer{},
142 return defaultOptions
145 // Options holds various configuration that affects Gopls execution, organized
146 // by the nature or origin of the settings.
147 type Options struct {
157 // ClientOptions holds LSP-specific configuration that is provided by the
159 type ClientOptions struct {
160 InsertTextFormat protocol.InsertTextFormat
161 ConfigurationSupported bool
162 DynamicConfigurationSupported bool
163 DynamicWatchedFilesSupported bool
164 PreferredContentFormat protocol.MarkupKind
166 HierarchicalDocumentSymbolSupport bool
167 SemanticTypes []string
168 SemanticMods []string
171 // ServerOptions holds LSP-specific configuration that is provided by the
173 type ServerOptions struct {
174 SupportedCodeActions map[FileKind]map[protocol.CodeActionKind]bool
175 SupportedCommands []string
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`.
186 // Env adds environment variables to external commands run by `gopls`, most notably `go list`.
187 Env map[string]string
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.
193 // Placeholders enables placeholders for function parameters or struct fields in completion responses.
196 // LinkTarget controls where documentation links go.
197 // It might be one of:
202 // If company chooses to use its own `godoc.org`, its address can be used as well.
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.
209 // Gofumpt indicates if we should run gofumpt formatting.
213 // EnvSlice returns Env as a slice of k=v strings.
214 func (u *UserOptions) EnvSlice() []string {
216 for k, v := range u.Env {
217 result = append(result, fmt.Sprintf("%v=%v", k, v))
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)
230 u.Env[split[0]] = split[1]
234 // Hooks contains configuration that is provided to the Gopls command by the
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
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)
259 // "unreachable": false, // Disable the unreachable analyzer.
260 // "unusedparams": true // Enable the unusedparams analyzer.
264 Analyses map[string]bool
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.
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.
280 Codelens map[string]bool
282 // CompletionDocumentation enables documentation with completion results.
283 CompletionDocumentation bool
285 // CompleteUnimported enables completion for packages that you do not currently import.
286 CompleteUnimported bool
288 // DeepCompletion enables the ability to return completions from deep inside relevant entities, rather than just the locally accessible ones.
290 // Consider this example:
297 // type wrapString struct {
302 // x := wrapString{"hello world"}
307 // At the location of the `<>` in this program, deep completion would suggest the result `x.str`.
310 // Matcher sets the algorithm that is used when calculating completion candidates.
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
321 // Staticcheck enables additional analyses from staticcheck.io.
324 // SymbolMatcher sets the algorithm that is used when finding workspace symbols.
325 SymbolMatcher SymbolMatcher
327 // SymbolStyle controls how symbols are qualified in symbol responses.
333 // "symbolStyle": "dynamic",
337 SymbolStyle SymbolStyle
339 // LinksInHover toggles the presence of links to documentation in hover.
342 // TempModfile controls the use of the -modfile flag in Go 1.14.
345 // ImportShortcut specifies whether import statements should link to
346 // documentation or go to definitions.
347 ImportShortcut ImportShortcut
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
353 // SemanticTokens controls whether the LSP server will send
354 // semantic tokens to the client.
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
362 // ExperimentalWorkspaceModule opts a user into the experimental support
363 // for multi-module workspaces.
364 ExperimentalWorkspaceModule bool
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.
371 // This option must be set to a valid duration string, for example `"250ms"`.
372 ExperimentalDiagnosticsDelay time.Duration
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
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.
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
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
407 type ImportShortcut string
410 Both ImportShortcut = "Both"
411 Link ImportShortcut = "Link"
412 Definition ImportShortcut = "Definition"
415 func (s ImportShortcut) ShowLinks() bool {
416 return s == Both || s == Link
419 func (s ImportShortcut) ShowDefinition() bool {
420 return s == Both || s == Definition
426 Fuzzy Matcher = "Fuzzy"
427 CaseInsensitive Matcher = "CaseInsensitive"
428 CaseSensitive Matcher = "CaseSensitive"
431 type SymbolMatcher string
434 SymbolFuzzy SymbolMatcher = "Fuzzy"
435 SymbolCaseInsensitive SymbolMatcher = "CaseInsensitive"
436 SymbolCaseSensitive SymbolMatcher = "CaseSensitive"
439 type SymbolStyle string
442 // PackageQualifiedSymbols is package qualified symbols i.e.
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
452 DynamicSymbols SymbolStyle = "Dynamic"
455 type HoverKind string
458 SingleLine HoverKind = "SingleLine"
459 NoDocumentation HoverKind = "NoDocumentation"
460 SynopsisDocumentation HoverKind = "SynopsisDocumentation"
461 FullDocumentation HoverKind = "FullDocumentation"
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.
467 // This should only be used by clients that support this behavior.
468 Structured HoverKind = "Structured"
471 type OptionResults []OptionResult
473 type OptionResult struct {
485 OptionHandled = OptionState(iota)
490 type LinkTarget string
492 func SetOptions(options *Options, opts interface{}) OptionResults {
493 var results OptionResults
494 switch opts := opts.(type) {
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()
506 for name, value := range opts {
507 results = append(results, options.set(name, value))
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()
515 results = append(results, OptionResult{
517 Error: errors.Errorf("Invalid options type %T", opts),
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
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
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]
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
550 func (o *Options) Clone() *Options {
552 ClientOptions: o.ClientOptions,
553 DebuggingOptions: o.DebuggingOptions,
554 ExperimentalOptions: o.ExperimentalOptions,
555 InternalOptions: o.InternalOptions,
557 GoDiff: o.Hooks.GoDiff,
558 ComputeEdits: o.Hooks.ComputeEdits,
559 GofumptFormat: o.GofumptFormat,
560 URLRegexp: o.URLRegexp,
562 ServerOptions: o.ServerOptions,
563 UserOptions: o.UserOptions,
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 {
574 result.Analyses = copyStringMap(o.Analyses)
575 result.Annotations = copyStringMap(o.Annotations)
576 result.Codelens = copyStringMap(o.Codelens)
578 copySlice := func(src []string) []string {
579 dst := make([]string, len(src))
583 result.SetEnvSlice(o.EnvSlice())
584 result.BuildFlags = copySlice(o.BuildFlags)
586 copyAnalyzerMap := func(src map[string]Analyzer) map[string]Analyzer {
587 dst := make(map[string]Analyzer)
588 for k, v := range src {
593 result.DefaultAnalyzers = copyAnalyzerMap(o.DefaultAnalyzers)
594 result.TypeErrorAnalyzers = copyAnalyzerMap(o.TypeErrorAnalyzers)
595 result.ConvenienceAnalyzers = copyAnalyzerMap(o.ConvenienceAnalyzers)
596 result.StaticcheckAnalyzers = copyAnalyzerMap(o.StaticcheckAnalyzers)
600 func (o *Options) AddStaticcheckAnalyzer(a *analysis.Analyzer) {
601 o.StaticcheckAnalyzers[a.Name] = Analyzer{Analyzer: a, Enabled: true}
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
614 func (o *Options) enableAllExperimentMaps() {
615 if _, ok := o.Codelens[CommandToggleDetails.Name]; !ok {
616 o.Codelens[CommandToggleDetails.Name] = true
618 if _, ok := o.Analyses[unusedparams.Analyzer.Name]; !ok {
619 o.Analyses[unusedparams.Analyzer.Name] = true
623 func (o *Options) set(name string, value interface{}) OptionResult {
624 result := OptionResult{Name: name, Value: value}
627 menv, ok := value.(map[string]interface{})
629 result.errorf("invalid type %T, expect map", value)
632 for k, v := range menv {
633 o.Env[k] = fmt.Sprint(v)
637 iflags, ok := value.([]interface{})
639 result.errorf("invalid type %T, expect list", value)
642 flags := make([]string, 0, len(iflags))
643 for _, flag := range iflags {
644 flags = append(flags, fmt.Sprintf("%s", flag))
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)
659 if s, ok := result.asOneOf(
661 string(CaseSensitive),
662 string(CaseInsensitive),
664 o.Matcher = Matcher(s)
667 case "symbolMatcher":
668 if s, ok := result.asOneOf(
670 string(SymbolCaseInsensitive),
671 string(SymbolCaseSensitive),
673 o.SymbolMatcher = SymbolMatcher(s)
677 if s, ok := result.asOneOf(
678 string(FullyQualifiedSymbols),
679 string(PackageQualifiedSymbols),
680 string(DynamicSymbols),
682 o.SymbolStyle = SymbolStyle(s)
686 if s, ok := result.asOneOf(
687 string(NoDocumentation),
689 string(SynopsisDocumentation),
690 string(FullDocumentation),
693 o.HoverKind = HoverKind(s)
697 result.setString(&o.LinkTarget)
700 result.setBool(&o.LinksInHover)
702 case "importShortcut":
703 if s, ok := result.asOneOf(string(Both), string(Link), string(Definition)); ok {
704 o.ImportShortcut = ImportShortcut(s)
708 result.setBoolMap(&o.Analyses)
711 result.setBoolMap(&o.Annotations)
712 for k := range o.Annotations {
714 case "noEscape", "noNilcheck", "noInline", "noBounds":
717 result.Name += ":" + k // put mistake(s) in the message
718 result.State = OptionUnexpected
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)
729 for lens, enabled := range lensOverrides {
730 o.Codelens[lens] = enabled
735 result.setBool(&o.Staticcheck)
738 result.setString(&o.Local)
740 case "verboseOutput":
741 result.setBool(&o.VerboseOutput)
743 case "verboseWorkDoneProgress":
744 result.setBool(&o.VerboseWorkDoneProgress)
747 result.setBool(&o.TempModfile)
750 result.setBool(&o.Gofumpt)
752 case "semanticTokens":
753 result.setBool(&o.SemanticTokens)
755 case "expandWorkspaceToModule":
756 result.setBool(&o.ExpandWorkspaceToModule)
758 case "experimentalWorkspaceModule":
759 result.setBool(&o.ExperimentalWorkspaceModule)
761 case "experimentalDiagnosticsDelay":
762 result.setDuration(&o.ExperimentalDiagnosticsDelay)
764 case "experimentalPackageCacheKey":
765 result.setBool(&o.ExperimentalPackageCacheKey)
767 case "allExperiments":
768 // This setting should be handled before all of the other options are
769 // processed, so do nothing here.
771 // Replaced settings.
772 case "experimentalDisabledAnalyses":
773 result.State = OptionDeprecated
774 result.Replacement = "analyses"
776 case "disableDeepCompletion":
777 result.State = OptionDeprecated
778 result.Replacement = "deepCompletion"
780 case "disableFuzzyMatching":
781 result.State = OptionDeprecated
782 result.Replacement = "fuzzyMatching"
784 case "wantCompletionDocumentation":
785 result.State = OptionDeprecated
786 result.Replacement = "completionDocumentation"
788 case "wantUnimportedCompletions":
789 result.State = OptionDeprecated
790 result.Replacement = "completeUnimported"
792 case "fuzzyMatching":
793 result.State = OptionDeprecated
794 result.Replacement = "matcher"
796 case "caseSensitiveCompletion":
797 result.State = OptionDeprecated
798 result.Replacement = "matcher"
800 // Deprecated settings.
801 case "wantSuggestedFixes":
802 result.State = OptionDeprecated
804 case "noIncrementalSync":
805 result.State = OptionDeprecated
807 case "watchFileChanges":
808 result.State = OptionDeprecated
811 result.State = OptionDeprecated
814 result.State = OptionUnexpected
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...)
824 func (r *OptionResult) asBool() (bool, bool) {
825 b, ok := r.Value.(bool)
827 r.errorf("invalid type %T, expect bool", r.Value)
833 func (r *OptionResult) setBool(b *bool) {
834 if v, ok := r.asBool(); ok {
839 func (r *OptionResult) setDuration(d *time.Duration) {
840 if v, ok := r.asString(); ok {
841 parsed, err := time.ParseDuration(v)
843 r.errorf("failed to parse duration %q: %v", v, err)
850 func (r *OptionResult) setBoolMap(bm *map[string]bool) {
851 all, ok := r.Value.(map[string]interface{})
853 r.errorf("invalid type %T for map[string]bool option", r.Value)
856 m := make(map[string]bool)
857 for a, enabled := range all {
858 if enabled, ok := enabled.(bool); ok {
861 r.errorf("invalid type %T for map key %q", enabled, a)
868 func (r *OptionResult) asString() (string, bool) {
869 b, ok := r.Value.(string)
871 r.errorf("invalid type %T, expect string", r.Value)
877 func (r *OptionResult) asOneOf(options ...string) (string, bool) {
878 s, ok := r.asString()
882 lower := strings.ToLower(s)
883 for _, opt := range options {
884 if strings.ToLower(opt) == lower {
888 r.errorf("invalid option %q for enum", r.Value)
892 func (r *OptionResult) setString(s *string) {
893 if v, ok := r.asString(); ok {
898 // EnabledAnalyzers returns all of the analyzers enabled for the given
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)
906 for _, a := range snapshot.View().Options().TypeErrorAnalyzers {
907 if a.IsEnabled(snapshot.View()) {
908 analyzers = append(analyzers, a)
911 for _, a := range snapshot.View().Options().ConvenienceAnalyzers {
912 if a.IsEnabled(snapshot.View()) {
913 analyzers = append(analyzers, a)
916 for _, a := range snapshot.View().Options().StaticcheckAnalyzers {
917 if a.IsEnabled(snapshot.View()) {
918 analyzers = append(analyzers, a)
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,
932 nonewvars.Analyzer.Name: {
933 Analyzer: nonewvars.Analyzer,
934 FixesError: nonewvars.FixesError,
937 noresultvalues.Analyzer.Name: {
938 Analyzer: noresultvalues.Analyzer,
939 FixesError: noresultvalues.FixesError,
942 undeclaredname.Analyzer.Name: {
943 Analyzer: undeclaredname.Analyzer,
944 FixesError: undeclaredname.FixesError,
945 Command: CommandUndeclaredName,
951 func convenienceAnalyzers() map[string]Analyzer {
952 return map[string]Analyzer{
953 fillstruct.Analyzer.Name: {
954 Analyzer: fillstruct.Analyzer,
955 Command: CommandFillStruct,
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},
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},
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},
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`)
1010 type APIJSON struct {
1011 Options map[string][]*OptionJSON
1012 Commands []*CommandJSON
1016 type OptionJSON struct {
1020 EnumValues []EnumValue
1024 type EnumValue struct {
1029 type CommandJSON struct {
1035 type LensJSON struct {