Skip to content

Commit

Permalink
internal/lsp/source: make matchers selectable in WorkspaceSymbols
Browse files Browse the repository at this point in the history
This change allows to use fuzzy or case-sensitive matchers in addition
to case-insensitive when searching for symbols.
Matcher is specified by UserOptions.Matcher just like Completion.

Updates golang/go#33844

Change-Id: I4000fb7984c75f0f41c38d740dbe164398032312
Reviewed-on: https://go-review.googlesource.com/c/tools/+/218737
Reviewed-by: Rebecca Stambler <[email protected]>
Run-TryBot: Rebecca Stambler <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
  • Loading branch information
daisuzu authored and stamblerre committed Feb 13, 2020
1 parent 695c81b commit 885dec1
Show file tree
Hide file tree
Showing 15 changed files with 307 additions and 86 deletions.
8 changes: 8 additions & 0 deletions internal/lsp/cmd/test/cmdtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ func (r *runner) WorkspaceSymbols(*testing.T, string, []protocol.SymbolInformati
//TODO: add command line workspace symbol tests when it works
}

func (r *runner) FuzzyWorkspaceSymbols(*testing.T, string, []protocol.SymbolInformation, map[string]struct{}) {
//TODO: add command line workspace symbol tests when it works
}

func (r *runner) CaseSensitiveWorkspaceSymbols(*testing.T, string, []protocol.SymbolInformation, map[string]struct{}) {
//TODO: add command line workspace symbol tests when it works
}

func (r *runner) runGoplsCmd(t testing.TB, args ...string) (string, string) {
rStdout, wStdout, err := os.Pipe()
if err != nil {
Expand Down
62 changes: 56 additions & 6 deletions internal/lsp/lsp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -785,14 +785,24 @@ func (r *runner) Symbols(t *testing.T, uri span.URI, expectedSymbols []protocol.
}

func (r *runner) WorkspaceSymbols(t *testing.T, query string, expectedSymbols []protocol.SymbolInformation, dirs map[string]struct{}) {
params := &protocol.WorkspaceSymbolParams{
Query: query,
got := r.callWorkspaceSymbols(t, query, func(opts *source.Options) {
opts.Matcher = source.CaseInsensitive
})
got = tests.FilterWorkspaceSymbols(got, dirs)
if len(got) != len(expectedSymbols) {
t.Errorf("want %d symbols, got %d", len(expectedSymbols), len(got))
return
}
symbols, err := r.server.Symbol(r.ctx, params)
if err != nil {
t.Fatal(err)
if diff := tests.DiffWorkspaceSymbols(expectedSymbols, got); diff != "" {
t.Error(diff)
}
got := tests.FilterWorkspaceSymbols(symbols, dirs)
}

func (r *runner) FuzzyWorkspaceSymbols(t *testing.T, query string, expectedSymbols []protocol.SymbolInformation, dirs map[string]struct{}) {
got := r.callWorkspaceSymbols(t, query, func(opts *source.Options) {
opts.Matcher = source.Fuzzy
})
got = tests.FilterWorkspaceSymbols(got, dirs)
if len(got) != len(expectedSymbols) {
t.Errorf("want %d symbols, got %d", len(expectedSymbols), len(got))
return
Expand All @@ -802,6 +812,46 @@ func (r *runner) WorkspaceSymbols(t *testing.T, query string, expectedSymbols []
}
}

func (r *runner) CaseSensitiveWorkspaceSymbols(t *testing.T, query string, expectedSymbols []protocol.SymbolInformation, dirs map[string]struct{}) {
got := r.callWorkspaceSymbols(t, query, func(opts *source.Options) {
opts.Matcher = source.CaseSensitive
})
got = tests.FilterWorkspaceSymbols(got, dirs)
if len(got) != len(expectedSymbols) {
t.Errorf("want %d symbols, got %d", len(expectedSymbols), len(got))
return
}
if diff := tests.DiffWorkspaceSymbols(expectedSymbols, got); diff != "" {
t.Error(diff)
}
}

func (r *runner) callWorkspaceSymbols(t *testing.T, query string, options func(*source.Options)) []protocol.SymbolInformation {
t.Helper()

for _, view := range r.server.session.Views() {
original := view.Options()
modified := original
options(&modified)
var err error
view, err = view.SetOptions(r.ctx, modified)
if err != nil {
t.Error(err)
return nil
}
defer view.SetOptions(r.ctx, original)
}

params := &protocol.WorkspaceSymbolParams{
Query: query,
}
symbols, err := r.server.Symbol(r.ctx, params)
if err != nil {
t.Fatal(err)
}
return symbols
}

func (r *runner) SignatureHelp(t *testing.T, spn span.Span, want *protocol.SignatureHelp) {
m, err := r.data.Mapper(spn.URI())
if err != nil {
Expand Down
54 changes: 50 additions & 4 deletions internal/lsp/source/source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -798,11 +798,38 @@ func (r *runner) Symbols(t *testing.T, uri span.URI, expectedSymbols []protocol.
}

func (r *runner) WorkspaceSymbols(t *testing.T, query string, expectedSymbols []protocol.SymbolInformation, dirs map[string]struct{}) {
symbols, err := source.WorkspaceSymbols(r.ctx, []source.View{r.view}, query)
if err != nil {
t.Errorf("symbols failed: %v", err)
got := r.callWorkspaceSymbols(t, query, func(opts *source.Options) {
opts.Matcher = source.CaseInsensitive
})
got = tests.FilterWorkspaceSymbols(got, dirs)
if len(got) != len(expectedSymbols) {
t.Errorf("want %d symbols, got %d", len(expectedSymbols), len(got))
return
}
if diff := tests.DiffWorkspaceSymbols(expectedSymbols, got); diff != "" {
t.Error(diff)
}
}

func (r *runner) FuzzyWorkspaceSymbols(t *testing.T, query string, expectedSymbols []protocol.SymbolInformation, dirs map[string]struct{}) {
got := r.callWorkspaceSymbols(t, query, func(opts *source.Options) {
opts.Matcher = source.Fuzzy
})
got = tests.FilterWorkspaceSymbols(got, dirs)
if len(got) != len(expectedSymbols) {
t.Errorf("want %d symbols, got %d", len(expectedSymbols), len(got))
return
}
if diff := tests.DiffWorkspaceSymbols(expectedSymbols, got); diff != "" {
t.Error(diff)
}
got := tests.FilterWorkspaceSymbols(symbols, dirs)
}

func (r *runner) CaseSensitiveWorkspaceSymbols(t *testing.T, query string, expectedSymbols []protocol.SymbolInformation, dirs map[string]struct{}) {
got := r.callWorkspaceSymbols(t, query, func(opts *source.Options) {
opts.Matcher = source.CaseSensitive
})
got = tests.FilterWorkspaceSymbols(got, dirs)
if len(got) != len(expectedSymbols) {
t.Errorf("want %d symbols, got %d", len(expectedSymbols), len(got))
return
Expand All @@ -812,6 +839,25 @@ func (r *runner) WorkspaceSymbols(t *testing.T, query string, expectedSymbols []
}
}

func (r *runner) callWorkspaceSymbols(t *testing.T, query string, options func(*source.Options)) []protocol.SymbolInformation {
t.Helper()

original := r.view.Options()
modified := original
options(&modified)
view, err := r.view.SetOptions(r.ctx, modified)
if err != nil {
t.Fatal(err)
}
defer r.view.SetOptions(r.ctx, original)

got, err := source.WorkspaceSymbols(r.ctx, []source.View{view}, query)
if err != nil {
t.Fatal(err)
}
return got
}

func (r *runner) SignatureHelp(t *testing.T, spn span.Span, want *protocol.SignatureHelp) {
_, rng, err := spanToRange(r.data, spn)
if err != nil {
Expand Down
26 changes: 21 additions & 5 deletions internal/lsp/source/workspace_symbol.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"go/types"
"strings"

"golang.org/x/tools/internal/lsp/fuzzy"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/telemetry/log"
"golang.org/x/tools/internal/telemetry/trace"
Expand All @@ -20,18 +21,14 @@ func WorkspaceSymbols(ctx context.Context, views []View, query string) ([]protoc
ctx, done := trace.StartSpan(ctx, "source.WorkspaceSymbols")
defer done()

q := strings.ToLower(query)
matcher := func(s string) bool {
return strings.Contains(strings.ToLower(s), q)
}

seen := make(map[string]struct{})
var symbols []protocol.SymbolInformation
for _, view := range views {
knownPkgs, err := view.Snapshot().KnownPackages(ctx)
if err != nil {
return nil, err
}
matcher := makeMatcher(view.Options().Matcher, query)
for _, ph := range knownPkgs {
pkg, err := ph.Check(ctx)
if err != nil {
Expand Down Expand Up @@ -75,6 +72,25 @@ type symbolInformation struct {

type matcherFunc func(string) bool

func makeMatcher(m Matcher, query string) matcherFunc {
switch m {
case Fuzzy:
fm := fuzzy.NewMatcher(query)
return func(s string) bool {
return fm.Score(s) > 0
}
case CaseSensitive:
return func(s string) bool {
return strings.Contains(s, query)
}
default:
q := strings.ToLower(query)
return func(s string) bool {
return strings.Contains(strings.ToLower(s), q)
}
}
}

func findSymbol(decls []ast.Decl, info *types.Info, matcher matcherFunc) []symbolInformation {
var result []symbolInformation
for _, decl := range decls {
Expand Down
2 changes: 2 additions & 0 deletions internal/lsp/testdata/indirect/summary.txt.golden
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ RenamesCount = 0
PrepareRenamesCount = 0
SymbolsCount = 0
WorkspaceSymbolsCount = 0
FuzzyWorkspaceSymbolsCount = 0
CaseSensitiveWorkspaceSymbolsCount = 0
SignaturesCount = 0
LinksCount = 0
ImplementationsCount = 0
Expand Down
4 changes: 4 additions & 0 deletions internal/lsp/testdata/lsp/primarymod/workspacesymbol/a/a.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ package a
var WorkspaceSymbolVariableA = "a" //@symbol("WorkspaceSymbolVariableA", "WorkspaceSymbolVariableA", "Variable", "")

const WorkspaceSymbolConstantA = "a" //@symbol("WorkspaceSymbolConstantA", "WorkspaceSymbolConstantA", "Constant", "")

const (
workspacesymbolinvariable = iota //@symbol("workspacesymbolinvariable", "workspacesymbolinvariable", "Constant", "")
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
-- symbols --
WorkspaceSymbolVariableA Variable 3:5-3:29
WorkspaceSymbolConstantA Constant 5:7-5:31
workspacesymbolinvariable Constant 8:2-8:27

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package casesensitive

/*@
workspacesymbolcasesensitive("baz", baz)
workspacesymbolcasesensitive("Baz", Baz)
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package fuzzy

/*@
workspacesymbolfuzzy("wsym",
WorkspaceSymbolVariableA,
WorkspaceSymbolConstantA,
workspacesymbolinvariable,
WorkspaceSymbolVariableB,
WorkspaceSymbolStructB,
)
workspacesymbolfuzzy("symbola",
WorkspaceSymbolVariableA,
WorkspaceSymbolConstantA,
workspacesymbolinvariable,
WorkspaceSymbolVariableB,
)
workspacesymbolfuzzy("symbolb",
WorkspaceSymbolVariableA,
workspacesymbolinvariable,
WorkspaceSymbolVariableB,
WorkspaceSymbolStructB,
)
*/
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ workspacesymbol("",
ioWriter,
WorkspaceSymbolVariableA,
WorkspaceSymbolConstantA,
workspacesymbolinvariable,
WorkspaceSymbolVariableB,
WorkspaceSymbolStructB,
bBar,
Expand Down
2 changes: 2 additions & 0 deletions internal/lsp/testdata/lsp/summary.txt.golden
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ RenamesCount = 23
PrepareRenamesCount = 7
SymbolsCount = 3
WorkspaceSymbolsCount = 2
FuzzyWorkspaceSymbolsCount = 3
CaseSensitiveWorkspaceSymbolsCount = 2
SignaturesCount = 23
LinksCount = 8
ImplementationsCount = 5
Expand Down
2 changes: 2 additions & 0 deletions internal/lsp/testdata/missingdep/summary.txt.golden
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ RenamesCount = 0
PrepareRenamesCount = 0
SymbolsCount = 0
WorkspaceSymbolsCount = 0
FuzzyWorkspaceSymbolsCount = 0
CaseSensitiveWorkspaceSymbolsCount = 0
SignaturesCount = 0
LinksCount = 0
ImplementationsCount = 0
Expand Down
2 changes: 2 additions & 0 deletions internal/lsp/testdata/missingtwodep/summary.txt.golden
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ RenamesCount = 0
PrepareRenamesCount = 0
SymbolsCount = 0
WorkspaceSymbolsCount = 0
FuzzyWorkspaceSymbolsCount = 0
CaseSensitiveWorkspaceSymbolsCount = 0
SignaturesCount = 0
LinksCount = 0
ImplementationsCount = 0
Expand Down
2 changes: 2 additions & 0 deletions internal/lsp/testdata/unused/summary.txt.golden
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ RenamesCount = 0
PrepareRenamesCount = 0
SymbolsCount = 0
WorkspaceSymbolsCount = 0
FuzzyWorkspaceSymbolsCount = 0
CaseSensitiveWorkspaceSymbolsCount = 0
SignaturesCount = 0
LinksCount = 0
ImplementationsCount = 0
Expand Down
Loading

0 comments on commit 885dec1

Please sign in to comment.