diff --git a/internal/lsp/fake/editor.go b/internal/lsp/fake/editor.go index a5dd4791ee..e97c49b95f 100644 --- a/internal/lsp/fake/editor.go +++ b/internal/lsp/fake/editor.go @@ -67,7 +67,7 @@ type EditorConfig struct { // SymbolMatcher is the config associated with the "symbolMatcher" gopls // config option. - SymbolMatcher *string + SymbolMatcher, SymbolStyle *string // LimitWorkspaceScope is true if the user does not want to expand their // workspace scope to the entire module. @@ -185,6 +185,10 @@ func (e *Editor) configuration() map[string]interface{} { config["symbolMatcher"] = *e.Config.SymbolMatcher } + if e.Config.SymbolStyle != nil { + config["symbolStyle"] = *e.Config.SymbolStyle + } + return config } diff --git a/internal/lsp/regtest/bench_test.go b/internal/lsp/regtest/bench_test.go new file mode 100644 index 0000000000..d91c4240b6 --- /dev/null +++ b/internal/lsp/regtest/bench_test.go @@ -0,0 +1,71 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package regtest + +import ( + "flag" + "fmt" + "testing" + + "golang.org/x/tools/internal/lsp/fake" + "golang.org/x/tools/internal/lsp/protocol" +) + +var symbolBench = struct { + workdir, query, matcher, style string + printResults bool +}{} + +func init() { + flag.StringVar(&symbolBench.workdir, "symbol_workdir", "", "if set, run symbol benchmark in this directory") + flag.StringVar(&symbolBench.query, "symbol_query", "test", "symbol query to use in benchmark") + flag.StringVar(&symbolBench.matcher, "symbol_matcher", "", "symbol matcher to use in benchmark") + flag.StringVar(&symbolBench.style, "symbol_style", "", "symbol style to use in benchmark") + flag.BoolVar(&symbolBench.printResults, "symbol_print_results", false, "symbol style to use in benchmark") +} + +func TestBenchmarkSymbols(t *testing.T) { + if symbolBench.workdir == "" { + t.Skip("-symbol_workdir not configured") + } + opts := stressTestOptions(symbolBench.workdir) + conf := fake.EditorConfig{} + if symbolBench.matcher != "" { + conf.SymbolMatcher = &symbolBench.matcher + } + if symbolBench.style != "" { + conf.SymbolStyle = &symbolBench.style + } + opts = append(opts, WithEditorConfig(conf)) + withOptions(opts...).run(t, "", func(t *testing.T, env *Env) { + // We can't Await in this test, since we have disabled hooks. Instead, run + // one symbol request to completion to ensure all necessary cache entries + // are populated. + results, err := env.Editor.Server.Symbol(env.Ctx, &protocol.WorkspaceSymbolParams{ + Query: symbolBench.query, + }) + if err != nil { + t.Fatal(err) + } + if symbolBench.printResults { + fmt.Println("Results:") + for i := 0; i < len(results); i++ { + fmt.Printf("\t%d. %s\n", i, results[i].Name) + } + } + b := testing.Benchmark(func(b *testing.B) { + for i := 0; i < b.N; i++ { + if _, err := env.Editor.Server.Symbol(env.Ctx, &protocol.WorkspaceSymbolParams{ + Query: symbolBench.query, + }); err != nil { + t.Fatal(err) + } + } + }) + fmt.Println("Benchmark stats:") + fmt.Println(b.String()) + fmt.Println(b.MemString()) + }) +} diff --git a/internal/lsp/source/options.go b/internal/lsp/source/options.go index c6c397398d..06d4ea0b77 100644 --- a/internal/lsp/source/options.go +++ b/internal/lsp/source/options.go @@ -47,7 +47,6 @@ import ( "golang.org/x/tools/internal/lsp/analysis/simplifyslice" "golang.org/x/tools/internal/lsp/analysis/undeclaredname" "golang.org/x/tools/internal/lsp/analysis/unusedparams" - "golang.org/x/tools/internal/lsp/debug/tag" "golang.org/x/tools/internal/lsp/diff" "golang.org/x/tools/internal/lsp/diff/myers" "golang.org/x/tools/internal/lsp/protocol" @@ -494,8 +493,10 @@ func (o *Options) set(name string, value interface{}) OptionResult { o.SymbolStyle = FullyQualifiedSymbols case "dynamic": o.SymbolStyle = DynamicSymbols - default: + case "package": o.SymbolStyle = PackageQualifiedSymbols + default: + result.errorf("Unsupported symbol style %q", style) } case "hoverKind": @@ -515,7 +516,7 @@ func (o *Options) set(name string, value interface{}) OptionResult { case "Structured": o.HoverKind = Structured default: - result.errorf("Unsupported hover kind", tag.HoverKind.Of(hoverKind)) + result.errorf("Unsupported hover kind %q", hoverKind) } case "linkTarget":