mirror of
https://github.com/golang/go
synced 2024-11-18 14:24:44 -07:00
aa94e735be
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>
212 lines
4.4 KiB
Go
212 lines
4.4 KiB
Go
// 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 (
|
|
"testing"
|
|
|
|
"golang.org/x/tools/internal/lsp/fake"
|
|
"golang.org/x/tools/internal/lsp/protocol"
|
|
)
|
|
|
|
const symbolSetup = `
|
|
-- go.mod --
|
|
module mod.com
|
|
|
|
go 1.12
|
|
-- main.go --
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
func main() { // function
|
|
fmt.Println("Hello")
|
|
}
|
|
|
|
var myvar int // variable
|
|
|
|
type myType string // basic type
|
|
|
|
type myDecoder json.Decoder // to use the encoding/json import
|
|
|
|
func (m *myType) Blahblah() {} // method
|
|
|
|
type myStruct struct { // struct type
|
|
myStructField int // struct field
|
|
}
|
|
|
|
type myInterface interface { // interface
|
|
DoSomeCoolStuff() string // interface method
|
|
}
|
|
-- p/p.go --
|
|
package p
|
|
|
|
const Message = "Hello World." // constant
|
|
`
|
|
|
|
var caseSensitiveSymbolChecks = map[string]*expSymbolInformation{
|
|
"main": {
|
|
Name: pString("main.main"),
|
|
Kind: pKind(protocol.Function),
|
|
Location: &expLocation{
|
|
Path: pString("main.go"),
|
|
Range: &expRange{
|
|
Start: &expPos{
|
|
Line: pInt(7),
|
|
Column: pInt(5),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"Message": {
|
|
Name: pString("p.Message"),
|
|
Kind: pKind(protocol.Constant),
|
|
Location: &expLocation{
|
|
Path: pString("p/p.go"),
|
|
Range: &expRange{
|
|
Start: &expPos{
|
|
Line: pInt(2),
|
|
Column: pInt(6),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"myvar": {
|
|
Name: pString("main.myvar"),
|
|
Kind: pKind(protocol.Variable),
|
|
Location: &expLocation{
|
|
Path: pString("main.go"),
|
|
Range: &expRange{
|
|
Start: &expPos{
|
|
Line: pInt(11),
|
|
Column: pInt(4),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"myType": {
|
|
Name: pString("main.myType"),
|
|
Kind: pKind(protocol.String),
|
|
Location: &expLocation{
|
|
Path: pString("main.go"),
|
|
Range: &expRange{
|
|
Start: &expPos{
|
|
Line: pInt(13),
|
|
Column: pInt(5),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"Blahblah": {
|
|
Name: pString("main.myType.Blahblah"),
|
|
Kind: pKind(protocol.Method),
|
|
Location: &expLocation{
|
|
Path: pString("main.go"),
|
|
Range: &expRange{
|
|
Start: &expPos{
|
|
Line: pInt(17),
|
|
Column: pInt(17),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"NewEncoder": {
|
|
Name: pString("json.NewEncoder"),
|
|
Kind: pKind(protocol.Function),
|
|
},
|
|
"myStruct": {
|
|
Name: pString("main.myStruct"),
|
|
Kind: pKind(protocol.Struct),
|
|
Location: &expLocation{
|
|
Path: pString("main.go"),
|
|
Range: &expRange{
|
|
Start: &expPos{
|
|
Line: pInt(19),
|
|
Column: pInt(5),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
// TODO: not sure we should be returning struct fields
|
|
"myStructField": {
|
|
Name: pString("main.myStruct.myStructField"),
|
|
Kind: pKind(protocol.Field),
|
|
Location: &expLocation{
|
|
Path: pString("main.go"),
|
|
Range: &expRange{
|
|
Start: &expPos{
|
|
Line: pInt(20),
|
|
Column: pInt(1),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"myInterface": {
|
|
Name: pString("main.myInterface"),
|
|
Kind: pKind(protocol.Interface),
|
|
Location: &expLocation{
|
|
Path: pString("main.go"),
|
|
Range: &expRange{
|
|
Start: &expPos{
|
|
Line: pInt(23),
|
|
Column: pInt(5),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
// TODO: not sure we should be returning interface methods
|
|
"DoSomeCoolStuff": {
|
|
Name: pString("main.myInterface.DoSomeCoolStuff"),
|
|
Kind: pKind(protocol.Method),
|
|
Location: &expLocation{
|
|
Path: pString("main.go"),
|
|
Range: &expRange{
|
|
Start: &expPos{
|
|
Line: pInt(24),
|
|
Column: pInt(1),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
var caseInsensitiveSymbolChecks = map[string]*expSymbolInformation{
|
|
"Main": caseSensitiveSymbolChecks["main"],
|
|
}
|
|
|
|
var fuzzySymbolChecks = map[string]*expSymbolInformation{
|
|
"Mn": caseSensitiveSymbolChecks["main"],
|
|
}
|
|
|
|
// TestSymbolPos tests that, at a basic level, we get the correct position
|
|
// information for symbols matches that are returned.
|
|
func TestSymbolPos(t *testing.T) {
|
|
checkChecks(t, "caseSensitive", caseSensitiveSymbolChecks)
|
|
checkChecks(t, "caseInsensitive", caseInsensitiveSymbolChecks)
|
|
checkChecks(t, "fuzzy", fuzzySymbolChecks)
|
|
}
|
|
|
|
func checkChecks(t *testing.T, matcher string, checks map[string]*expSymbolInformation) {
|
|
t.Helper()
|
|
opts := []RunOption{
|
|
WithEditorConfig(fake.EditorConfig{SymbolMatcher: &matcher}),
|
|
}
|
|
runner.Run(t, symbolSetup, func(t *testing.T, env *Env) {
|
|
t.Run(matcher, func(t *testing.T) {
|
|
for query, exp := range checks {
|
|
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,\ngot: %v", query, exp, res)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}, opts...)
|
|
}
|