internal/lsp/source: add a new symbolStyle configuration option

Add a symbolStyle configuration option, and use it to parameterize the
following behavior when computing workspace symbols:

 + package (default): include package name in the workspace symbol.
 + full: fully qualify the symbol by import path
 + dynamic: use as the symbol the shortest suffix of the full path that
   contains the match.

To implement this, expose package name in the source.Package interface.
To be consistent with other handling in the cache package, define a new
cache.packageName named string type, to avoid confusion with packageID
or packagePath (if confusing those two identifiers was a problem, surely
it is a potential problem for package name as well).

Change-Id: Ic8ed6ba5473b0523b97e677878e5e6bddfff10a7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/236842
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
diff --git a/internal/lsp/cache/check.go b/internal/lsp/cache/check.go
index 3ab5b3f..a71106c 100644
--- a/internal/lsp/cache/check.go
+++ b/internal/lsp/cache/check.go
@@ -276,6 +276,7 @@
 
 	pkg := &pkg{
 		id:              m.id,
+		name:            m.name,
 		pkgPath:         m.pkgPath,
 		mode:            mode,
 		goFiles:         goFiles,
@@ -352,7 +353,7 @@
 	} else if len(files) == 0 { // not the unsafe package, no parsed files
 		return nil, errors.Errorf("no parsed files for package %s, expected: %s, errors: %v, list errors: %v", pkg.pkgPath, pkg.compiledGoFiles, actualErrors, rawErrors)
 	} else {
-		pkg.types = types.NewPackage(string(m.pkgPath), m.name)
+		pkg.types = types.NewPackage(string(m.pkgPath), string(m.name))
 	}
 
 	cfg := &types.Config{
diff --git a/internal/lsp/cache/load.go b/internal/lsp/cache/load.go
index 6b4d847..1ce17fc 100644
--- a/internal/lsp/cache/load.go
+++ b/internal/lsp/cache/load.go
@@ -23,7 +23,7 @@
 type metadata struct {
 	id              packageID
 	pkgPath         packagePath
-	name            string
+	name            packageName
 	goFiles         []span.URI
 	compiledGoFiles []span.URI
 	forTest         packagePath
@@ -171,7 +171,7 @@
 	m := &metadata{
 		id:         id,
 		pkgPath:    pkgPath,
-		name:       pkg.Name,
+		name:       packageName(pkg.Name),
 		forTest:    packagePath(packagesinternal.GetForTest(pkg)),
 		typesSizes: pkg.TypesSizes,
 		errors:     pkg.Errors,
diff --git a/internal/lsp/cache/pkg.go b/internal/lsp/cache/pkg.go
index bbfa04a1..aaded22 100644
--- a/internal/lsp/cache/pkg.go
+++ b/internal/lsp/cache/pkg.go
@@ -18,6 +18,7 @@
 type pkg struct {
 	// ID and package path have their own types to avoid being used interchangeably.
 	id              packageID
+	name            packageName
 	pkgPath         packagePath
 	mode            source.ParseMode
 	forTest         packagePath
@@ -32,11 +33,15 @@
 	typesSizes      types.Sizes
 }
 
-// Declare explicit types for package paths and IDs to ensure that we never use
-// an ID where a path belongs, and vice versa. If we confused the two, it would
-// result in confusing errors because package IDs often look like package paths.
-type packageID string
-type packagePath string
+// Declare explicit types for package paths, names, and IDs to ensure that we
+// never use an ID where a path belongs, and vice versa. If we confused these,
+// it would result in confusing errors because package IDs often look like
+// package paths.
+type (
+	packageID   string
+	packagePath string
+	packageName string
+)
 
 // Declare explicit types for files and directories to distinguish between the two.
 type fileURI span.URI
@@ -47,6 +52,10 @@
 	return string(p.id)
 }
 
+func (p *pkg) Name() string {
+	return string(p.name)
+}
+
 func (p *pkg) PkgPath() string {
 	return string(p.pkgPath)
 }
diff --git a/internal/lsp/regtest/symbol_test.go b/internal/lsp/regtest/symbol_test.go
index 32db7ef..68f3de4 100644
--- a/internal/lsp/regtest/symbol_test.go
+++ b/internal/lsp/regtest/symbol_test.go
@@ -44,14 +44,14 @@
 	DoSomeCoolStuff() string // interface method
 }
 -- p/p.go --
-package main
+package p
 
 const Message = "Hello World." // constant
 `
 
 var caseSensitiveSymbolChecks = map[string]*expSymbolInformation{
 	"main": {
-		Name: pString("mod.com.main"),
+		Name: pString("main.main"),
 		Kind: pKind(protocol.Function),
 		Location: &expLocation{
 			Path: pString("main.go"),
@@ -64,7 +64,7 @@
 		},
 	},
 	"Message": {
-		Name: pString("mod.com/p.Message"),
+		Name: pString("p.Message"),
 		Kind: pKind(protocol.Constant),
 		Location: &expLocation{
 			Path: pString("p/p.go"),
@@ -77,7 +77,7 @@
 		},
 	},
 	"myvar": {
-		Name: pString("mod.com.myvar"),
+		Name: pString("main.myvar"),
 		Kind: pKind(protocol.Variable),
 		Location: &expLocation{
 			Path: pString("main.go"),
@@ -90,7 +90,7 @@
 		},
 	},
 	"myType": {
-		Name: pString("mod.com.myType"),
+		Name: pString("main.myType"),
 		Kind: pKind(protocol.String),
 		Location: &expLocation{
 			Path: pString("main.go"),
@@ -103,7 +103,7 @@
 		},
 	},
 	"Blahblah": {
-		Name: pString("mod.com.myType.Blahblah"),
+		Name: pString("main.myType.Blahblah"),
 		Kind: pKind(protocol.Method),
 		Location: &expLocation{
 			Path: pString("main.go"),
@@ -116,11 +116,11 @@
 		},
 	},
 	"NewEncoder": {
-		Name: pString("encoding/json.NewEncoder"),
+		Name: pString("json.NewEncoder"),
 		Kind: pKind(protocol.Function),
 	},
 	"myStruct": {
-		Name: pString("mod.com.myStruct"),
+		Name: pString("main.myStruct"),
 		Kind: pKind(protocol.Struct),
 		Location: &expLocation{
 			Path: pString("main.go"),
@@ -134,7 +134,7 @@
 	},
 	// TODO: not sure we should be returning struct fields
 	"myStructField": {
-		Name: pString("mod.com.myStruct.myStructField"),
+		Name: pString("main.myStruct.myStructField"),
 		Kind: pKind(protocol.Field),
 		Location: &expLocation{
 			Path: pString("main.go"),
@@ -147,7 +147,7 @@
 		},
 	},
 	"myInterface": {
-		Name: pString("mod.com.myInterface"),
+		Name: pString("main.myInterface"),
 		Kind: pKind(protocol.Interface),
 		Location: &expLocation{
 			Path: pString("main.go"),
@@ -161,7 +161,7 @@
 	},
 	// TODO: not sure we should be returning interface methods
 	"DoSomeCoolStuff": {
-		Name: pString("mod.com.myInterface.DoSomeCoolStuff"),
+		Name: pString("main.myInterface.DoSomeCoolStuff"),
 		Kind: pKind(protocol.Method),
 		Location: &expLocation{
 			Path: pString("main.go"),
@@ -180,7 +180,7 @@
 }
 
 var fuzzySymbolChecks = map[string]*expSymbolInformation{
-	"mod.Mn": caseSensitiveSymbolChecks["main"],
+	"Mn": caseSensitiveSymbolChecks["main"],
 }
 
 // TestSymbolPos tests that, at a basic level, we get the correct position
@@ -202,7 +202,7 @@
 				t.Run(query, func(t *testing.T) {
 					res := env.Symbol(query)
 					if !exp.matchAgainst(res) {
-						t.Fatalf("failed to find a match against query %q for %v", query, exp)
+						t.Fatalf("failed to find a match against query %q for %v,\ngot: %v", query, exp, res)
 					}
 				})
 			}
diff --git a/internal/lsp/source/options.go b/internal/lsp/source/options.go
index 92c09e8..6e785e1 100644
--- a/internal/lsp/source/options.go
+++ b/internal/lsp/source/options.go
@@ -215,6 +215,10 @@
 	// SymbolMatcher specifies the type of matcher to use for symbol requests.
 	SymbolMatcher SymbolMatcher
 
+	// SymbolStyle specifies what style of symbols to return in symbol requests
+	// (package qualified, fully qualified, etc).
+	SymbolStyle SymbolStyle
+
 	// DeepCompletion allows completion to perform nested searches through
 	// possible candidates.
 	DeepCompletion bool
@@ -303,6 +307,14 @@
 	SymbolCaseSensitive
 )
 
+type SymbolStyle int
+
+const (
+	PackageQualifiedSymbols = SymbolStyle(iota)
+	FullyQualifiedSymbols
+	DynamicSymbols
+)
+
 type HoverKind int
 
 const (
@@ -449,6 +461,20 @@
 			o.SymbolMatcher = SymbolCaseInsensitive
 		}
 
+	case "symbolStyle":
+		style, ok := result.asString()
+		if !ok {
+			break
+		}
+		switch style {
+		case "full":
+			o.SymbolStyle = FullyQualifiedSymbols
+		case "dynamic":
+			o.SymbolStyle = DynamicSymbols
+		default:
+			o.SymbolStyle = PackageQualifiedSymbols
+		}
+
 	case "hoverKind":
 		hoverKind, ok := result.asString()
 		if !ok {
diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go
index e08260e..1ec2430 100644
--- a/internal/lsp/source/source_test.go
+++ b/internal/lsp/source/source_test.go
@@ -817,7 +817,7 @@
 
 func (r *runner) callWorkspaceSymbols(t *testing.T, query string, matcher source.SymbolMatcher, dirs map[string]struct{}, expectedSymbols []protocol.SymbolInformation) {
 	t.Helper()
-	got, err := source.WorkspaceSymbols(r.ctx, matcher, []source.View{r.view}, query)
+	got, err := source.WorkspaceSymbols(r.ctx, matcher, source.PackageQualifiedSymbols, []source.View{r.view}, query)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/internal/lsp/source/view.go b/internal/lsp/source/view.go
index 89bed4b..92230e4 100644
--- a/internal/lsp/source/view.go
+++ b/internal/lsp/source/view.go
@@ -440,6 +440,7 @@
 // only the relevant fields of a *go/packages.Package.
 type Package interface {
 	ID() string
+	Name() string
 	PkgPath() string
 	CompiledGoFiles() []ParseGoHandle
 	File(uri span.URI) (ParseGoHandle, error)
diff --git a/internal/lsp/source/workspace_symbol.go b/internal/lsp/source/workspace_symbol.go
index 17b7496..8d470fb 100644
--- a/internal/lsp/source/workspace_symbol.go
+++ b/internal/lsp/source/workspace_symbol.go
@@ -35,14 +35,14 @@
 // with a different configured SymbolMatcher per View. Therefore we assume that
 // Session level configuration will define the SymbolMatcher to be used for the
 // WorkspaceSymbols method.
-func WorkspaceSymbols(ctx context.Context, matcherType SymbolMatcher, views []View, query string) ([]protocol.SymbolInformation, error) {
+func WorkspaceSymbols(ctx context.Context, matcherType SymbolMatcher, style SymbolStyle, views []View, query string) ([]protocol.SymbolInformation, error) {
 	ctx, done := event.Start(ctx, "source.WorkspaceSymbols")
 	defer done()
 	if query == "" {
 		return nil, nil
 	}
 
-	matcher := makeMatcher(matcherType, query)
+	queryMatcher := makeQueryMatcher(matcherType, query)
 	seen := make(map[string]struct{})
 	var symbols []protocol.SymbolInformation
 outer:
@@ -53,6 +53,7 @@
 		}
 		for _, ph := range knownPkgs {
 			pkg, err := ph.Check(ctx)
+			symbolMatcher := makePackageSymbolMatcher(style, pkg, queryMatcher)
 			if err != nil {
 				return nil, err
 			}
@@ -65,7 +66,7 @@
 				if err != nil {
 					return nil, err
 				}
-				for _, si := range findSymbol(file.Decls, pkg.GetTypesInfo(), matcher, pkg.PkgPath()) {
+				for _, si := range findSymbol(file.Decls, pkg.GetTypesInfo(), symbolMatcher) {
 					mrng, err := posToMappedRange(view, pkg, si.node.Pos(), si.node.End())
 					if err != nil {
 						event.Error(ctx, "Error getting mapped range for node", err)
@@ -83,6 +84,7 @@
 							URI:   protocol.URIFromSpanURI(mrng.URI()),
 							Range: rng,
 						},
+						ContainerName: pkg.PkgPath(),
 					})
 					if len(symbols) > maxSymbols {
 						break outer
@@ -102,7 +104,7 @@
 
 type matcherFunc func(string) bool
 
-func makeMatcher(m SymbolMatcher, query string) matcherFunc {
+func makeQueryMatcher(m SymbolMatcher, query string) matcherFunc {
 	switch m {
 	case SymbolFuzzy:
 		fm := fuzzy.NewMatcher(query)
@@ -121,7 +123,91 @@
 	}
 }
 
-func findSymbol(decls []ast.Decl, info *types.Info, matcher matcherFunc, prefix string) []symbolInformation {
+// packageSymbolMatcher matches (possibly partially) qualified symbols within a
+// package scope.
+//
+// The given symbolizer controls how symbol names are extracted from the
+// package scope.
+type packageSymbolMatcher struct {
+	queryMatcher matcherFunc
+	pkg          Package
+	symbolize    symbolizer
+}
+
+// symbolMatch returns the package symbol for name that matches the underlying
+// query, or the empty string if no match is found.
+func (s packageSymbolMatcher) symbolMatch(name string) string {
+	return s.symbolize(name, s.pkg, s.queryMatcher)
+}
+
+func makePackageSymbolMatcher(style SymbolStyle, pkg Package, matcher matcherFunc) func(string) string {
+	var s symbolizer
+	switch style {
+	case DynamicSymbols:
+		s = dynamicSymbolMatch
+	case FullyQualifiedSymbols:
+		s = fullyQualifiedSymbolMatch
+	default:
+		s = packageSymbolMatch
+	}
+	return packageSymbolMatcher{queryMatcher: matcher, pkg: pkg, symbolize: s}.symbolMatch
+}
+
+// A symbolizer returns a qualified symbol match for the unqualified name
+// within pkg, if one exists, or the empty string if no match is found.
+type symbolizer func(name string, pkg Package, m matcherFunc) string
+
+func fullyQualifiedSymbolMatch(name string, pkg Package, matcher matcherFunc) string {
+	// TODO: this should probably include pkg.Name() as well.
+	fullyQualified := pkg.PkgPath() + "." + name
+	if matcher(fullyQualified) {
+		return fullyQualified
+	}
+	return ""
+}
+
+func dynamicSymbolMatch(name string, pkg Package, matcher matcherFunc) string {
+	pkgQualified := pkg.Name() + "." + name
+	if match := shortestMatch(pkgQualified, matcher); match != "" {
+		return match
+	}
+	fullyQualified := pkg.PkgPath() + "." + name
+	if match := shortestMatch(fullyQualified, matcher); match != "" {
+		return match
+	}
+	return ""
+}
+
+func packageSymbolMatch(name string, pkg Package, matcher matcherFunc) string {
+	qualified := pkg.Name() + "." + name
+	if matcher(qualified) {
+		return qualified
+	}
+	return ""
+}
+
+func shortestMatch(fullPath string, matcher func(string) bool) string {
+	pathParts := strings.Split(fullPath, "/")
+	dottedParts := strings.Split(pathParts[len(pathParts)-1], ".")
+	// First match the smallest package identifier.
+	if m := matchRight(dottedParts, ".", matcher); m != "" {
+		return m
+	}
+	// Then match the shortest subpath.
+	return matchRight(pathParts, "/", matcher)
+}
+
+func matchRight(parts []string, sep string, matcher func(string) bool) string {
+	for i := 0; i < len(parts); i++ {
+		path := strings.Join(parts[len(parts)-1-i:], sep)
+		if matcher(path) {
+			return path
+		}
+	}
+	return ""
+}
+
+func findSymbol(decls []ast.Decl, info *types.Info, symbolMatch func(string) string) []symbolInformation {
 	var result []symbolInformation
 	for _, decl := range decls {
 		switch decl := decl.(type) {
@@ -137,10 +223,9 @@
 					fn = typ.Name + "." + fn
 				}
 			}
-			target := prefix + "." + fn
-			if matcher(target) {
+			if m := symbolMatch(fn); m != "" {
 				result = append(result, symbolInformation{
-					name: target,
+					name: m,
 					kind: kind,
 					node: decl.Name,
 				})
@@ -149,10 +234,10 @@
 			for _, spec := range decl.Specs {
 				switch spec := spec.(type) {
 				case *ast.TypeSpec:
-					target := prefix + "." + spec.Name.Name
-					if matcher(target) {
+					target := spec.Name.Name
+					if m := symbolMatch(target); m != "" {
 						result = append(result, symbolInformation{
-							name: target,
+							name: m,
 							kind: typeToKind(info.TypeOf(spec.Type)),
 							node: spec.Name,
 						})
@@ -160,7 +245,7 @@
 					switch st := spec.Type.(type) {
 					case *ast.StructType:
 						for _, field := range st.Fields.List {
-							result = append(result, findFieldSymbol(field, protocol.Field, matcher, target)...)
+							result = append(result, findFieldSymbol(field, protocol.Field, symbolMatch, target)...)
 						}
 					case *ast.InterfaceType:
 						for _, field := range st.Methods.List {
@@ -168,19 +253,18 @@
 							if len(field.Names) == 0 {
 								kind = protocol.Interface
 							}
-							result = append(result, findFieldSymbol(field, kind, matcher, target)...)
+							result = append(result, findFieldSymbol(field, kind, symbolMatch, target)...)
 						}
 					}
 				case *ast.ValueSpec:
 					for _, name := range spec.Names {
-						target := prefix + "." + name.Name
-						if matcher(target) {
+						if m := symbolMatch(name.Name); m != "" {
 							kind := protocol.Variable
 							if decl.Tok == token.CONST {
 								kind = protocol.Constant
 							}
 							result = append(result, symbolInformation{
-								name: target,
+								name: m,
 								kind: kind,
 								node: name,
 							})
@@ -220,15 +304,15 @@
 	return protocol.Variable
 }
 
-func findFieldSymbol(field *ast.Field, kind protocol.SymbolKind, matcher matcherFunc, prefix string) []symbolInformation {
+func findFieldSymbol(field *ast.Field, kind protocol.SymbolKind, symbolMatch func(string) string, prefix string) []symbolInformation {
 	var result []symbolInformation
 
 	if len(field.Names) == 0 {
 		name := types.ExprString(field.Type)
 		target := prefix + "." + name
-		if matcher(target) {
+		if m := symbolMatch(target); m != "" {
 			result = append(result, symbolInformation{
-				name: target,
+				name: m,
 				kind: kind,
 				node: field,
 			})
@@ -238,9 +322,9 @@
 
 	for _, name := range field.Names {
 		target := prefix + "." + name.Name
-		if matcher(target) {
+		if m := symbolMatch(target); m != "" {
 			result = append(result, symbolInformation{
-				name: target,
+				name: m,
 				kind: kind,
 				node: name,
 			})
diff --git a/internal/lsp/testdata/lsp/primarymod/symbols/main.go b/internal/lsp/testdata/lsp/primarymod/symbols/main.go
index 794b62a..3da7139 100644
--- a/internal/lsp/testdata/lsp/primarymod/symbols/main.go
+++ b/internal/lsp/testdata/lsp/primarymod/symbols/main.go
@@ -4,57 +4,57 @@
 	"io"
 )
 
-var x = 42 //@mark(symbolsx, "x"), symbol("x", "x", "Variable", "", "golang.org/x/tools/internal/lsp/symbols.x")
+var x = 42 //@mark(symbolsx, "x"), symbol("x", "x", "Variable", "", "main.x")
 
-const y = 43 //@symbol("y", "y", "Constant", "", "golang.org/x/tools/internal/lsp/symbols.y")
+const y = 43 //@symbol("y", "y", "Constant", "", "main.y")
 
-type Number int //@symbol("Number", "Number", "Number", "", "golang.org/x/tools/internal/lsp/symbols.Number")
+type Number int //@symbol("Number", "Number", "Number", "", "main.Number")
 
-type Alias = string //@symbol("Alias", "Alias", "String", "", "golang.org/x/tools/internal/lsp/symbols.Alias")
+type Alias = string //@symbol("Alias", "Alias", "String", "", "main.Alias")
 
-type NumberAlias = Number //@symbol("NumberAlias", "NumberAlias", "Number", "", "golang.org/x/tools/internal/lsp/symbols.NumberAlias")
+type NumberAlias = Number //@symbol("NumberAlias", "NumberAlias", "Number", "", "main.NumberAlias")
 
 type (
-	Boolean   bool   //@symbol("Boolean", "Boolean", "Boolean", "", "golang.org/x/tools/internal/lsp/symbols.Boolean")
-	BoolAlias = bool //@symbol("BoolAlias", "BoolAlias", "Boolean", "", "golang.org/x/tools/internal/lsp/symbols.BoolAlias")
+	Boolean   bool   //@symbol("Boolean", "Boolean", "Boolean", "", "main.Boolean")
+	BoolAlias = bool //@symbol("BoolAlias", "BoolAlias", "Boolean", "", "main.BoolAlias")
 )
 
-type Foo struct { //@mark(symbolsFoo, "Foo"), symbol("Foo", "Foo", "Struct", "", "golang.org/x/tools/internal/lsp/symbols.Foo")
-	Quux           //@mark(fQuux, "Quux"), symbol("Quux", "Quux", "Field", "Foo", "golang.org/x/tools/internal/lsp/symbols.Foo.Quux")
-	W    io.Writer //@symbol("W" , "W", "Field", "Foo", "golang.org/x/tools/internal/lsp/symbols.Foo.W")
-	Bar  int       //@mark(fBar, "Bar"), symbol("Bar", "Bar", "Field", "Foo", "golang.org/x/tools/internal/lsp/symbols.Foo.Bar")
-	baz  string    //@symbol("baz", "baz", "Field", "Foo", "golang.org/x/tools/internal/lsp/symbols.Foo.baz")
+type Foo struct { //@mark(symbolsFoo, "Foo"), symbol("Foo", "Foo", "Struct", "", "main.Foo")
+	Quux           //@mark(fQuux, "Quux"), symbol("Quux", "Quux", "Field", "Foo", "main.Foo.Quux")
+	W    io.Writer //@symbol("W" , "W", "Field", "Foo", "main.Foo.W")
+	Bar  int       //@mark(fBar, "Bar"), symbol("Bar", "Bar", "Field", "Foo", "main.Foo.Bar")
+	baz  string    //@symbol("baz", "baz", "Field", "Foo", "main.Foo.baz")
 }
 
-type Quux struct { //@symbol("Quux", "Quux", "Struct", "", "golang.org/x/tools/internal/lsp/symbols.Quux")
-	X, Y float64 //@mark(qX, "X"), symbol("X", "X", "Field", "Quux", "golang.org/x/tools/internal/lsp/symbols.X"), symbol("Y", "Y", "Field", "Quux", "golang.org/x/tools/internal/lsp/symbols.Y")
+type Quux struct { //@symbol("Quux", "Quux", "Struct", "", "main.Quux")
+	X, Y float64 //@mark(qX, "X"), symbol("X", "X", "Field", "Quux", "main.X"), symbol("Y", "Y", "Field", "Quux", "main.Y")
 }
 
-func (f Foo) Baz() string { //@symbol("(Foo).Baz", "Baz", "Method", "", "golang.org/x/tools/internal/lsp/symbols.Foo.Baz")
+func (f Foo) Baz() string { //@symbol("(Foo).Baz", "Baz", "Method", "", "main.Foo.Baz")
 	return f.baz
 }
 
-func (q *Quux) Do() {} //@mark(qDo, "Do"), symbol("(*Quux).Do", "Do", "Method", "", "golang.org/x/tools/internal/lsp/symbols.Quux.Do")
+func (q *Quux) Do() {} //@mark(qDo, "Do"), symbol("(*Quux).Do", "Do", "Method", "", "main.Quux.Do")
 
-func main() { //@symbol("main", "main", "Function", "", "golang.org/x/tools/internal/lsp/symbols.main")
+func main() { //@symbol("main", "main", "Function", "", "main.main")
 
 }
 
-type Stringer interface { //@symbol("Stringer", "Stringer", "Interface", "", "golang.org/x/tools/internal/lsp/symbols.Stringer")
-	String() string //@symbol("String", "String", "Method", "Stringer", "golang.org/x/tools/internal/lsp/symbols.Stringer.String")
+type Stringer interface { //@symbol("Stringer", "Stringer", "Interface", "", "main.Stringer")
+	String() string //@symbol("String", "String", "Method", "Stringer", "main.Stringer.String")
 }
 
-type ABer interface { //@mark(ABerInterface, "ABer"), symbol("ABer", "ABer", "Interface", "", "golang.org/x/tools/internal/lsp/symbols.ABer")
-	B()        //@symbol("B", "B", "Method", "ABer", "golang.org/x/tools/internal/lsp/symbols.ABer.B")
-	A() string //@mark(ABerA, "A"), symbol("A", "A", "Method", "ABer", "golang.org/x/tools/internal/lsp/symbols.ABer.A")
+type ABer interface { //@mark(ABerInterface, "ABer"), symbol("ABer", "ABer", "Interface", "", "main.ABer")
+	B()        //@symbol("B", "B", "Method", "ABer", "main.ABer.B")
+	A() string //@mark(ABerA, "A"), symbol("A", "A", "Method", "ABer", "main.ABer.A")
 }
 
-type WithEmbeddeds interface { //@symbol("WithEmbeddeds", "WithEmbeddeds", "Interface", "", "golang.org/x/tools/internal/lsp/symbols.WithEmbeddeds")
-	Do()      //@symbol("Do", "Do", "Method", "WithEmbeddeds", "golang.org/x/tools/internal/lsp/symbols.WithEmbeddeds.Do")
-	ABer      //@symbol("ABer", "ABer", "Interface", "WithEmbeddeds", "golang.org/x/tools/internal/lsp/symbols.WithEmbeddeds.ABer")
-	io.Writer //@mark(ioWriter, "io.Writer"), symbol("io.Writer", "io.Writer", "Interface", "WithEmbeddeds", "golang.org/x/tools/internal/lsp/symbols.WithEmbeddeds.Writer")
+type WithEmbeddeds interface { //@symbol("WithEmbeddeds", "WithEmbeddeds", "Interface", "", "main.WithEmbeddeds")
+	Do()      //@symbol("Do", "Do", "Method", "WithEmbeddeds", "main.WithEmbeddeds.Do")
+	ABer      //@symbol("ABer", "ABer", "Interface", "WithEmbeddeds", "main.WithEmbeddeds.ABer")
+	io.Writer //@mark(ioWriter, "io.Writer"), symbol("io.Writer", "io.Writer", "Interface", "WithEmbeddeds", "main.WithEmbeddeds.Writer")
 }
 
-func Dunk() int { return 0 } //@symbol("Dunk", "Dunk", "Function", "", "golang.org/x/tools/internal/lsp/symbols.Dunk")
+func Dunk() int { return 0 } //@symbol("Dunk", "Dunk", "Function", "", "main.Dunk")
 
-func dunk() {} //@symbol("dunk", "dunk", "Function", "", "golang.org/x/tools/internal/lsp/symbols.dunk")
+func dunk() {} //@symbol("dunk", "dunk", "Function", "", "main.dunk")
diff --git a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/a/a.go b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/a/a.go
index 93bfee3..6e5a68b 100644
--- a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/a/a.go
+++ b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/a/a.go
@@ -1,9 +1,9 @@
 package a
 
-var RandomGopherVariableA = "a" //@symbol("RandomGopherVariableA", "RandomGopherVariableA", "Variable", "", "golang.org/x/tools/internal/lsp/workspacesymbol/a.RandomGopherVariableA")
+var RandomGopherVariableA = "a" //@symbol("RandomGopherVariableA", "RandomGopherVariableA", "Variable", "", "a.RandomGopherVariableA")
 
-const RandomGopherConstantA = "a" //@symbol("RandomGopherConstantA", "RandomGopherConstantA", "Constant", "", "golang.org/x/tools/internal/lsp/workspacesymbol/a.RandomGopherConstantA")
+const RandomGopherConstantA = "a" //@symbol("RandomGopherConstantA", "RandomGopherConstantA", "Constant", "", "a.RandomGopherConstantA")
 
 const (
-	randomgopherinvariable = iota //@symbol("randomgopherinvariable", "randomgopherinvariable", "Constant", "", "golang.org/x/tools/internal/lsp/workspacesymbol/a.randomgopherinvariable")
+	randomgopherinvariable = iota //@symbol("randomgopherinvariable", "randomgopherinvariable", "Constant", "", "a.randomgopherinvariable")
 )
diff --git a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/b/b.go b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/b/b.go
index 31bb923..89ce0d9 100644
--- a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/b/b.go
+++ b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/b/b.go
@@ -1,7 +1,7 @@
 package b
 
-var RandomGopherVariableB = "b" //@symbol("RandomGopherVariableB", "RandomGopherVariableB", "Variable", "", "golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherVariableB")
+var RandomGopherVariableB = "b" //@symbol("RandomGopherVariableB", "RandomGopherVariableB", "Variable", "", "b.RandomGopherVariableB")
 
-type RandomGopherStructB struct { //@symbol("RandomGopherStructB", "RandomGopherStructB", "Struct", "", "golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherStructB")
-	Bar int //@mark(bBar, "Bar"), symbol("Bar", "Bar", "Field", "RandomGopherStructB", "golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherStructB.Bar")
+type RandomGopherStructB struct { //@symbol("RandomGopherStructB", "RandomGopherStructB", "Struct", "", "b.RandomGopherStructB")
+	Bar int //@mark(bBar, "Bar"), symbol("Bar", "Bar", "Field", "RandomGopherStructB", "b.RandomGopherStructB.Bar")
 }
diff --git "a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/casesensitive/\041dunk.golden" "b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/casesensitive/\041dunk.golden"
index 9bcd639..e990607 100644
--- "a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/casesensitive/\041dunk.golden"
+++ "b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/casesensitive/\041dunk.golden"
@@ -1,2 +1,2 @@
 -- workspace_symbol --
-symbols/main.go:58:6-10 golang.org/x/tools/internal/lsp/symbols.Dunk Function
+symbols/main.go:58:6-10 main.Dunk Function
diff --git a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/casesensitive/dunk.golden b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/casesensitive/dunk.golden
index 041a87c..b8a91ea 100644
--- a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/casesensitive/dunk.golden
+++ b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/casesensitive/dunk.golden
@@ -1,2 +1,2 @@
 -- workspace_symbol --
-symbols/main.go:60:6-10 golang.org/x/tools/internal/lsp/symbols.dunk Function
+symbols/main.go:60:6-10 main.dunk Function
diff --git a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/randoma.golden b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/randoma.golden
index 3fe3775..8423a57 100644
--- a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/randoma.golden
+++ b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/randoma.golden
@@ -1,6 +1,6 @@
 -- workspace_symbol --
-workspacesymbol/a/a.go:3:5-26 golang.org/x/tools/internal/lsp/workspacesymbol/a.RandomGopherVariableA Variable
-workspacesymbol/a/a.go:5:7-28 golang.org/x/tools/internal/lsp/workspacesymbol/a.RandomGopherConstantA Constant
-workspacesymbol/a/a.go:8:2-24 golang.org/x/tools/internal/lsp/workspacesymbol/a.randomgopherinvariable Constant
-workspacesymbol/b/b.go:3:5-26 golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherVariableB Variable
-workspacesymbol/b/b.go:6:2-5 golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherStructB.Bar Field
+workspacesymbol/a/a.go:3:5-26 a.RandomGopherVariableA Variable
+workspacesymbol/a/a.go:5:7-28 a.RandomGopherConstantA Constant
+workspacesymbol/a/a.go:8:2-24 a.randomgopherinvariable Constant
+workspacesymbol/b/b.go:3:5-26 b.RandomGopherVariableB Variable
+workspacesymbol/b/b.go:6:2-5 b.RandomGopherStructB.Bar Field
diff --git a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/randomb.golden b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/randomb.golden
index 9108df7..7c34266 100644
--- a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/randomb.golden
+++ b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/randomb.golden
@@ -1,6 +1,6 @@
 -- workspace_symbol --
-workspacesymbol/a/a.go:3:5-26 golang.org/x/tools/internal/lsp/workspacesymbol/a.RandomGopherVariableA Variable
-workspacesymbol/a/a.go:8:2-24 golang.org/x/tools/internal/lsp/workspacesymbol/a.randomgopherinvariable Constant
-workspacesymbol/b/b.go:3:5-26 golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherVariableB Variable
-workspacesymbol/b/b.go:5:6-25 golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherStructB Struct
-workspacesymbol/b/b.go:6:2-5 golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherStructB.Bar Field
+workspacesymbol/a/a.go:3:5-26 a.RandomGopherVariableA Variable
+workspacesymbol/a/a.go:8:2-24 a.randomgopherinvariable Constant
+workspacesymbol/b/b.go:3:5-26 b.RandomGopherVariableB Variable
+workspacesymbol/b/b.go:5:6-25 b.RandomGopherStructB Struct
+workspacesymbol/b/b.go:6:2-5 b.RandomGopherStructB.Bar Field
diff --git a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/rgop.golden b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/rgop.golden
index 98c65ca..fa43cc9 100644
--- a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/rgop.golden
+++ b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/fuzzy/rgop.golden
@@ -1,7 +1,7 @@
 -- workspace_symbol --
-workspacesymbol/a/a.go:3:5-26 golang.org/x/tools/internal/lsp/workspacesymbol/a.RandomGopherVariableA Variable
-workspacesymbol/a/a.go:5:7-28 golang.org/x/tools/internal/lsp/workspacesymbol/a.RandomGopherConstantA Constant
-workspacesymbol/a/a.go:8:2-24 golang.org/x/tools/internal/lsp/workspacesymbol/a.randomgopherinvariable Constant
-workspacesymbol/b/b.go:3:5-26 golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherVariableB Variable
-workspacesymbol/b/b.go:5:6-25 golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherStructB Struct
-workspacesymbol/b/b.go:6:2-5 golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherStructB.Bar Field
+workspacesymbol/a/a.go:3:5-26 a.RandomGopherVariableA Variable
+workspacesymbol/a/a.go:5:7-28 a.RandomGopherConstantA Constant
+workspacesymbol/a/a.go:8:2-24 a.randomgopherinvariable Constant
+workspacesymbol/b/b.go:3:5-26 b.RandomGopherVariableB Variable
+workspacesymbol/b/b.go:5:6-25 b.RandomGopherStructB Struct
+workspacesymbol/b/b.go:6:2-5 b.RandomGopherStructB.Bar Field
diff --git a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/randomgophervar.golden b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/randomgophervar.golden
index 30c3492..5f559b0 100644
--- a/internal/lsp/testdata/lsp/primarymod/workspacesymbol/randomgophervar.golden
+++ b/internal/lsp/testdata/lsp/primarymod/workspacesymbol/randomgophervar.golden
@@ -1,3 +1,3 @@
 -- workspace_symbol --
-workspacesymbol/a/a.go:3:5-26 golang.org/x/tools/internal/lsp/workspacesymbol/a.RandomGopherVariableA Variable
-workspacesymbol/b/b.go:3:5-26 golang.org/x/tools/internal/lsp/workspacesymbol/b.RandomGopherVariableB Variable
+workspacesymbol/a/a.go:3:5-26 a.RandomGopherVariableA Variable
+workspacesymbol/b/b.go:3:5-26 b.RandomGopherVariableB Variable
diff --git a/internal/lsp/workspace_symbol.go b/internal/lsp/workspace_symbol.go
index a233d44..20c5763 100644
--- a/internal/lsp/workspace_symbol.go
+++ b/internal/lsp/workspace_symbol.go
@@ -18,5 +18,6 @@
 
 	views := s.session.Views()
 	matcher := s.session.Options().SymbolMatcher
-	return source.WorkspaceSymbols(ctx, matcher, views, params.Query)
+	style := s.session.Options().SymbolStyle
+	return source.WorkspaceSymbols(ctx, matcher, style, views, params.Query)
 }