diff --git a/cmd/frontend/graphqlbackend/schema.go b/cmd/frontend/graphqlbackend/schema.go index 98ed88991959..1e1b21974256 100644 --- a/cmd/frontend/graphqlbackend/schema.go +++ b/cmd/frontend/graphqlbackend/schema.go @@ -1464,6 +1464,8 @@ type Symbol { url: String! # The canonical URL to this symbol (using an immutable revision specifier). canonicalURL: String! + # Whether or not the symbol is local to the file it's defined in. + fileLocal: Boolean! } # A location inside a resource (in a repository at a specific commit). diff --git a/cmd/frontend/graphqlbackend/schema.graphql b/cmd/frontend/graphqlbackend/schema.graphql index dda10fac104c..c65b9a420e1e 100755 --- a/cmd/frontend/graphqlbackend/schema.graphql +++ b/cmd/frontend/graphqlbackend/schema.graphql @@ -1471,6 +1471,8 @@ type Symbol { url: String! # The canonical URL to this symbol (using an immutable revision specifier). canonicalURL: String! + # Whether or not the symbol is local to the file it's defined in. + fileLocal: Boolean! } # A location inside a resource (in a repository at a specific commit). diff --git a/cmd/frontend/graphqlbackend/search.go b/cmd/frontend/graphqlbackend/search.go index a8174a306470..dd23052cd192 100644 --- a/cmd/frontend/graphqlbackend/search.go +++ b/cmd/frontend/graphqlbackend/search.go @@ -616,7 +616,7 @@ func newSearchResultResolver(result interface{}, score int) *searchSuggestionRes return &searchSuggestionResolver{result: r, score: score, length: len(r.path), label: r.path} case *symbolResolver: - return &searchSuggestionResolver{result: r, score: score, length: len(r.symbol.Name + " " + r.symbol.ContainerName), label: r.symbol.Name + " " + r.symbol.ContainerName} + return &searchSuggestionResolver{result: r, score: score, length: len(r.symbol.Name + " " + r.symbol.Parent), label: r.symbol.Name + " " + r.symbol.Parent} default: panic("never here") diff --git a/cmd/frontend/graphqlbackend/search_suggestions.go b/cmd/frontend/graphqlbackend/search_suggestions.go index 6d30026fc3f0..79f9e1d64628 100644 --- a/cmd/frontend/graphqlbackend/search_suggestions.go +++ b/cmd/frontend/graphqlbackend/search_suggestions.go @@ -118,19 +118,19 @@ func (r *searchResolver) Suggestions(ctx context.Context, args *searchSuggestion for _, fileMatch := range fileMatches { for _, sr := range fileMatch.symbols { score := 20 - if sr.symbol.ContainerName == "" { + if sr.symbol.Parent == "" { score++ } if len(sr.symbol.Name) < 12 { score++ } - switch sr.symbol.Kind { + switch ctagsKindToLSPSymbolKind(sr.symbol.Kind) { case lsp.SKFunction, lsp.SKMethod: score += 2 case lsp.SKClass: score += 3 } - if len(sr.symbol.Name) >= 4 && strings.Contains(strings.ToLower(string(sr.symbol.Location.URI)), strings.ToLower(sr.symbol.Name)) { + if len(sr.symbol.Name) >= 4 && strings.Contains(strings.ToLower(sr.uri.String()), strings.ToLower(sr.symbol.Name)) { score++ } results = append(results, newSearchResultResolver(sr, score)) @@ -246,7 +246,7 @@ func (r *searchResolver) Suggestions(ctx context.Context, args *searchSuggestion k.file = s.path case *symbolResolver: k.repoName = s.location.resource.commit.repo.repo.Name - k.symbol = s.symbol.Name + s.symbol.ContainerName + k.symbol = s.symbol.Name + s.symbol.Parent default: panic(fmt.Sprintf("unhandled: %#v", s)) } diff --git a/cmd/frontend/graphqlbackend/search_symbols.go b/cmd/frontend/graphqlbackend/search_symbols.go index fe8a6f3a2117..9b5a837836f7 100644 --- a/cmd/frontend/graphqlbackend/search_symbols.go +++ b/cmd/frontend/graphqlbackend/search_symbols.go @@ -148,7 +148,7 @@ func searchSymbolsInRepo(ctx context.Context, repoRevs *search.RepositoryRevisio if inputRev != "" { commit.inputRev = &inputRev } - symbolRes := toSymbolResolver(symbolToLSPSymbolInformation(symbol, baseURI), strings.ToLower(symbol.Language), commit) + symbolRes := toSymbolResolver(symbol, baseURI, strings.ToLower(symbol.Language), commit) uri := makeFileMatchURIFromSymbol(symbolRes, inputRev) if fileMatch, ok := fileMatchesByURI[uri]; ok { fileMatch.symbols = append(fileMatch.symbols, symbolRes) @@ -178,21 +178,11 @@ func makeFileMatchURIFromSymbol(symbolResolver *symbolResolver, inputRev string) return uri } -// symbolToLSPSymbolInformation converts a symbols service Symbol struct to an LSP SymbolInformation -// baseURI is the git://repo?rev base URI for the symbol that is extended with the file path -func symbolToLSPSymbolInformation(s protocol.Symbol, baseURI *gituri.URI) lsp.SymbolInformation { +func symbolRange(s protocol.Symbol) lsp.Range { ch := ctagsSymbolCharacter(s) - return lsp.SymbolInformation{ - Name: s.Name + s.Signature, - ContainerName: s.Parent, - Kind: ctagsKindToLSPSymbolKind(s.Kind), - Location: lsp.Location{ - URI: lsp.DocumentURI(baseURI.WithFilePath(s.Path).String()), - Range: lsp.Range{ - Start: lsp.Position{Line: s.Line - 1, Character: ch}, - End: lsp.Position{Line: s.Line - 1, Character: ch + len(s.Name)}, - }, - }, + return lsp.Range{ + Start: lsp.Position{Line: s.Line - 1, Character: ch}, + End: lsp.Position{Line: s.Line - 1, Character: ch + len(s.Name)}, } } diff --git a/cmd/frontend/graphqlbackend/symbols.go b/cmd/frontend/graphqlbackend/symbols.go index 61b70c16eeea..0d60131fe681 100644 --- a/cmd/frontend/graphqlbackend/symbols.go +++ b/cmd/frontend/graphqlbackend/symbols.go @@ -6,13 +6,11 @@ import ( "strings" "time" - lsp "github.com/sourcegraph/go-lsp" "github.com/sourcegraph/sourcegraph/cmd/frontend/backend" "github.com/sourcegraph/sourcegraph/cmd/frontend/graphqlbackend/graphqlutil" "github.com/sourcegraph/sourcegraph/pkg/api" "github.com/sourcegraph/sourcegraph/pkg/gituri" "github.com/sourcegraph/sourcegraph/pkg/symbols/protocol" - log15 "gopkg.in/inconshreveable/log15.v2" ) type symbolsArgs struct { @@ -74,7 +72,7 @@ func computeSymbols(ctx context.Context, commit *gitCommitResolver, query *strin } resolvers := make([]*symbolResolver, 0, len(symbols)) for _, symbol := range symbols { - resolver := toSymbolResolver(symbolToLSPSymbolInformation(symbol, baseURI), strings.ToLower(symbol.Language), commit) + resolver := toSymbolResolver(symbol, baseURI, strings.ToLower(symbol.Language), commit) if resolver == nil { continue } @@ -83,22 +81,18 @@ func computeSymbols(ctx context.Context, commit *gitCommitResolver, query *strin return resolvers, err } -func toSymbolResolver(symbol lsp.SymbolInformation, lang string, commitResolver *gitCommitResolver) *symbolResolver { +func toSymbolResolver(symbol protocol.Symbol, baseURI *gituri.URI, lang string, commitResolver *gitCommitResolver) *symbolResolver { resolver := &symbolResolver{ symbol: symbol, language: lang, + uri: baseURI.WithFilePath(symbol.Path), } - uri, err := gituri.Parse(string(symbol.Location.URI)) - if err != nil { - log15.Warn("Omitting symbol with invalid URI from results.", "uri", symbol.Location.URI, "error", err) - return nil - } - symbolRange := symbol.Location.Range // copy + symbolRange := symbolRange(symbol) resolver.location = &locationResolver{ resource: &gitTreeEntryResolver{ commit: commitResolver, - path: uri.Fragment, - stat: createFileInfo(uri.Fragment, false), // assume the path refers to a file (not dir) + path: resolver.uri.Fragment, + stat: createFileInfo(resolver.uri.Fragment, false), // assume the path refers to a file (not dir) }, lspRange: &symbolRange, } @@ -118,22 +112,23 @@ func (r *symbolConnectionResolver) PageInfo(ctx context.Context) (*graphqlutil.P } type symbolResolver struct { - symbol lsp.SymbolInformation + symbol protocol.Symbol language string location *locationResolver + uri *gituri.URI } func (r *symbolResolver) Name() string { return r.symbol.Name } func (r *symbolResolver) ContainerName() *string { - if r.symbol.ContainerName == "" { + if r.symbol.Parent == "" { return nil } - return &r.symbol.ContainerName + return &r.symbol.Parent } func (r *symbolResolver) Kind() string /* enum SymbolKind */ { - return strings.ToUpper(r.symbol.Kind.String()) + return strings.ToUpper(ctagsKindToLSPSymbolKind(r.symbol.Kind).String()) } func (r *symbolResolver) Language() string { return r.language } @@ -143,3 +138,5 @@ func (r *symbolResolver) Location() *locationResolver { return r.location } func (r *symbolResolver) URL(ctx context.Context) (string, error) { return r.location.URL(ctx) } func (r *symbolResolver) CanonicalURL() (string, error) { return r.location.CanonicalURL() } + +func (r *symbolResolver) FileLocal() bool { return r.symbol.FileLimited } diff --git a/cmd/symbols/internal/pkg/ctags/parser.go b/cmd/symbols/internal/pkg/ctags/parser.go index 44d721086415..d873533ad229 100644 --- a/cmd/symbols/internal/pkg/ctags/parser.go +++ b/cmd/symbols/internal/pkg/ctags/parser.go @@ -67,7 +67,7 @@ func NewParser(ctagsCommand string) (Parser, error) { cmd := exec.Command(ctagsCommand, "--_interactive="+opt, "--fields=*", "--languages=Basic,C,C#,C++,Clojure,Cobol,CSS,CUDA,D,Elixir,elm,Erlang,Go,haskell,Java,JavaScript,kotlin,Lisp,Lua,MatLab,ObjectiveC,OCaml,Perl,Perl6,PHP,Protobuf,Python,R,Ruby,Rust,scala,Scheme,Sh,swift,Tcl,typescript,Verilog,Vim", - "--map-CSS=+.scss", "--map-CSS=+.less", "--map-CSS=+.sass", "--file-scope=no", + "--map-CSS=+.scss", "--map-CSS=+.less", "--map-CSS=+.sass", "--kinds-Go=-p", // omit because 1 symbol per `package` keyword (1 for each file in a package) is not useful ) in, err := cmd.StdinPipe() @@ -183,6 +183,7 @@ type reply struct { Scope string `json:"scope"` ScopeKind string `json:"scopeKind"` Access string `json:"access"` + File bool `json:"file"` Signature string `json:"signature"` Pattern string `json:"pattern"` } @@ -209,15 +210,16 @@ func (p *ctagsProcess) Parse(name string, content []byte) (entries []Entry, err } entries = append(entries, Entry{ - Name: rep.Name, - Path: rep.Path, - Line: rep.Line, - Kind: rep.Kind, - Language: rep.Language, - Parent: rep.Scope, - ParentKind: rep.ScopeKind, - Pattern: rep.Pattern, - Signature: rep.Signature, + Name: rep.Name, + Path: rep.Path, + Line: rep.Line, + Kind: rep.Kind, + Language: rep.Language, + Parent: rep.Scope, + ParentKind: rep.ScopeKind, + Pattern: rep.Pattern, + Signature: rep.Signature, + FileLimited: rep.File, }) } diff --git a/cmd/symbols/internal/symbols/search.go b/cmd/symbols/internal/symbols/search.go index 429f115561f7..4eb8927a806d 100644 --- a/cmd/symbols/internal/symbols/search.go +++ b/cmd/symbols/internal/symbols/search.go @@ -231,10 +231,10 @@ func filterSymbols(ctx context.Context, db *sqlx.DB, args protocol.SearchArgs) ( } // The version of the symbols database schema. This is included in the database -// filenames to prevent a newer version of the symbols service attempting to -// read from a database created by an older (and likely incompatible) symbols +// filenames to prevent a newer version of the symbols service from attempting +// to read from a database created by an older (and likely incompatible) symbols // service. Increment this when you change the database schema. -const symbolsDBVersion = 1 +const symbolsDBVersion = 2 // symbolInDB is the same as `protocol.Symbol`, but with two additional columns: // namelowercase and pathlowercase, which enable indexed case insensitive