diff --git a/internal/lsp/diagnostics.go b/internal/lsp/diagnostics.go index ffc7c82babf..ba926f41b49 100644 --- a/internal/lsp/diagnostics.go +++ b/internal/lsp/diagnostics.go @@ -28,7 +28,7 @@ func (s *Server) Diagnostics(ctx context.Context, v source.View, uri span.URI) { if !ok { return } - reports, err := source.Diagnostics(ctx, v, gof) + reports, err := source.Diagnostics(ctx, v, gof, s.disabledAnalyses) if err != nil { s.session.Logger().Errorf(ctx, "failed to compute diagnostics for %s: %v", gof.URI(), err) return diff --git a/internal/lsp/general.go b/internal/lsp/general.go index 92e28a53017..c8b6b6b25ce 100644 --- a/internal/lsp/general.go +++ b/internal/lsp/general.go @@ -188,6 +188,15 @@ func (s *Server) processConfig(view source.View, config interface{}) error { if noDocsOnHover, ok := c["noDocsOnHover"].(bool); ok { s.noDocsOnHover = noDocsOnHover } + // Check if the user has explicitly disabled any analyses. + if disabledAnalyses, ok := c["experimentalDisabledAnalyses"].([]interface{}); ok { + s.disabledAnalyses = make(map[string]struct{}) + for _, a := range disabledAnalyses { + if a, ok := a.(string); ok { + s.disabledAnalyses[a] = struct{}{} + } + } + } return nil } diff --git a/internal/lsp/lsp_test.go b/internal/lsp/lsp_test.go index a7d12b0f95d..6867bfb6484 100644 --- a/internal/lsp/lsp_test.go +++ b/internal/lsp/lsp_test.go @@ -68,7 +68,7 @@ func (r *runner) Diagnostics(t *testing.T, data tests.Diagnostics) { if !ok { t.Fatalf("%s is not a Go file: %v", uri, err) } - results, err := source.Diagnostics(context.Background(), v, gof) + results, err := source.Diagnostics(context.Background(), v, gof, nil) if err != nil { t.Fatal(err) } diff --git a/internal/lsp/server.go b/internal/lsp/server.go index 121cc13e837..2903951e965 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -79,6 +79,7 @@ type Server struct { configurationSupported bool dynamicConfigurationSupported bool preferredContentFormat protocol.MarkupKind + disabledAnalyses map[string]struct{} textDocumentSyncKind protocol.TextDocumentSyncKind diff --git a/internal/lsp/source/diagnostics.go b/internal/lsp/source/diagnostics.go index 6ae073a0f29..b7b74b7a2a1 100644 --- a/internal/lsp/source/diagnostics.go +++ b/internal/lsp/source/diagnostics.go @@ -51,7 +51,7 @@ const ( SeverityError ) -func Diagnostics(ctx context.Context, v View, f GoFile) (map[span.URI][]Diagnostic, error) { +func Diagnostics(ctx context.Context, v View, f GoFile, disabledAnalyses map[string]struct{}) (map[span.URI][]Diagnostic, error) { pkg := f.GetPackage(ctx) if pkg == nil { return singleDiagnostic(f.URI(), "%s is not part of a package", f.URI()), nil @@ -70,7 +70,7 @@ func Diagnostics(ctx context.Context, v View, f GoFile) (map[span.URI][]Diagnost // Run diagnostics for the package that this URI belongs to. if !diagnostics(ctx, v, pkg, reports) { // If we don't have any list, parse, or type errors, run analyses. - if err := analyses(ctx, v, pkg, reports); err != nil { + if err := analyses(ctx, v, pkg, disabledAnalyses, reports); err != nil { v.Session().Logger().Errorf(ctx, "failed to run analyses for %s: %v", f.URI(), err) } } @@ -126,9 +126,9 @@ func diagnostics(ctx context.Context, v View, pkg Package, reports map[span.URI] return len(diags) != 0 } -func analyses(ctx context.Context, v View, pkg Package, reports map[span.URI][]Diagnostic) error { +func analyses(ctx context.Context, v View, pkg Package, disabledAnalyses map[string]struct{}, reports map[span.URI][]Diagnostic) error { // Type checking and parsing succeeded. Run analyses. - if err := runAnalyses(ctx, v, pkg, func(a *analysis.Analyzer, diag analysis.Diagnostic) error { + if err := runAnalyses(ctx, v, pkg, disabledAnalyses, func(a *analysis.Analyzer, diag analysis.Diagnostic) error { r := span.NewRange(v.Session().Cache().FileSet(), diag.Pos, diag.End) s, err := r.Span() if err != nil { @@ -234,9 +234,10 @@ func singleDiagnostic(uri span.URI, format string, a ...interface{}) map[span.UR } } -func runAnalyses(ctx context.Context, v View, pkg Package, report func(a *analysis.Analyzer, diag analysis.Diagnostic) error) error { +func runAnalyses(ctx context.Context, v View, pkg Package, disabledAnalyses map[string]struct{}, report func(a *analysis.Analyzer, diag analysis.Diagnostic) error) error { // The traditional vet suite: - analyzers := []*analysis.Analyzer{ + var analyzers []*analysis.Analyzer + for _, a := range []*analysis.Analyzer{ asmdecl.Analyzer, assign.Analyzer, atomic.Analyzer, @@ -259,6 +260,11 @@ func runAnalyses(ctx context.Context, v View, pkg Package, report func(a *analys unreachable.Analyzer, unsafeptr.Analyzer, unusedresult.Analyzer, + } { + if _, ok := disabledAnalyses[a.Name]; ok { + continue + } + analyzers = append(analyzers, a) } roots, err := analyze(ctx, v, []Package{pkg}, analyzers) diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go index be9c0f6ca64..5d957b6f6a7 100644 --- a/internal/lsp/source/source_test.go +++ b/internal/lsp/source/source_test.go @@ -55,7 +55,7 @@ func (r *runner) Diagnostics(t *testing.T, data tests.Diagnostics) { if err != nil { t.Fatal(err) } - results, err := source.Diagnostics(context.Background(), r.view, f.(source.GoFile)) + results, err := source.Diagnostics(context.Background(), r.view, f.(source.GoFile), nil) if err != nil { t.Fatal(err) }