Skip to content

Commit 9657119

Browse files
authored
feat(lsp): expose Sourcegraph Precise code navigation through LSP (#1243)
Implements an LSP server that proxies requests to Sourcegraph's code intelligence backend via GraphQL. The server communicates over stdio and is designed for use with editors like Neovim or coding agents like Claude Code.
1 parent c921cc5 commit 9657119

File tree

8 files changed

+1405
-35
lines changed

8 files changed

+1405
-35
lines changed

cmd/src/lsp.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"io"
7+
8+
"github.com/sourcegraph/src-cli/internal/api"
9+
"github.com/sourcegraph/src-cli/internal/lsp"
10+
)
11+
12+
func init() {
13+
usage := `
14+
'src lsp' runs a Language Server Protocol server that proxies LSP
15+
requests to Sourcegraph's code intelligence backend.
16+
17+
The server communicates over stdio (stdin/stdout) and is designed
18+
to be used with editors like Neovim.
19+
20+
Prerequisites:
21+
- The working directory must be inside a Git repository
22+
- The repository must be indexed on your Sourcegraph instance
23+
- SRC_ENDPOINT and SRC_ACCESS_TOKEN environment variables must be set
24+
25+
Supported LSP methods:
26+
- textDocument/definition
27+
- textDocument/references
28+
- textDocument/hover
29+
- textDocument/documentHighlight
30+
31+
Example Neovim configuration (0.11+):
32+
33+
vim.lsp.config['src-lsp'] = {
34+
cmd = { 'src', 'lsp' },
35+
root_markers = { '.git' },
36+
filetypes = { 'go', 'typescript', 'python' },
37+
}
38+
vim.lsp.enable('src-lsp')
39+
`
40+
41+
flagSet := flag.NewFlagSet("lsp", flag.ExitOnError)
42+
apiFlags := api.NewFlags(flagSet)
43+
44+
usageFunc := func() {
45+
fmt.Println(usage)
46+
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src %s':\n", flagSet.Name())
47+
flagSet.PrintDefaults()
48+
}
49+
50+
handler := func(args []string) error {
51+
if err := flagSet.Parse(args); err != nil {
52+
return err
53+
}
54+
55+
client := cfg.apiClient(apiFlags, io.Discard)
56+
57+
srv, err := lsp.NewServer(client)
58+
if err != nil {
59+
return err
60+
}
61+
62+
return srv.Run()
63+
}
64+
65+
commands = append(commands, &command{
66+
flagSet: flagSet,
67+
handler: handler,
68+
usageFunc: usageFunc,
69+
})
70+
}

go.mod

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ require (
2929
github.com/sourcegraph/scip v0.6.1
3030
github.com/sourcegraph/sourcegraph/lib v0.0.0-20240709083501-1af563b61442
3131
github.com/stretchr/testify v1.11.1
32-
golang.org/x/net v0.47.0
32+
github.com/tliron/glsp v0.2.2
3333
golang.org/x/sync v0.18.0
3434
google.golang.org/api v0.256.0
3535
google.golang.org/protobuf v1.36.10
3636
gopkg.in/yaml.v3 v3.0.1
3737
jaytaylor.com/html2text v0.0.0-20200412013138-3577fbdbcff7
38-
k8s.io/api v0.32.3
39-
k8s.io/apimachinery v0.32.3
40-
k8s.io/client-go v0.32.3
38+
k8s.io/api v0.33.2
39+
k8s.io/apimachinery v0.33.2
40+
k8s.io/client-go v0.33.2
4141
)
4242

4343
require (
@@ -79,11 +79,13 @@ require (
7979
github.com/go-jose/go-jose/v4 v4.1.2 // indirect
8080
github.com/go-logr/stdr v1.2.2 // indirect
8181
github.com/gofrs/uuid/v5 v5.0.0 // indirect
82-
github.com/google/gnostic-models v0.6.8 // indirect
83-
github.com/google/go-containerregistry v0.15.2 // indirect
82+
github.com/google/gnostic-models v0.6.9 // indirect
83+
github.com/google/go-containerregistry v0.19.1 // indirect
8484
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
8585
github.com/google/s2a-go v0.1.9 // indirect
86+
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
8687
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
88+
github.com/iancoleman/strcase v0.3.0 // indirect
8789
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
8890
github.com/jackc/pgconn v1.14.3 // indirect
8991
github.com/jackc/pgio v1.0.0 // indirect
@@ -95,12 +97,18 @@ require (
9597
github.com/morikuni/aec v1.0.0 // indirect
9698
github.com/opencontainers/go-digest v1.0.0 // indirect
9799
github.com/opencontainers/image-spec v1.1.0-rc4 // indirect
100+
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
98101
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
99102
github.com/rs/cors v1.11.0 // indirect
103+
github.com/sasha-s/go-deadlock v0.3.5 // indirect
104+
github.com/segmentio/ksuid v1.0.4 // indirect
100105
github.com/sirupsen/logrus v1.9.3 // indirect
101106
github.com/sourcegraph/beaut v0.0.0-20240611013027-627e4c25335a // indirect
107+
github.com/sourcegraph/jsonrpc2 v0.2.0 // indirect
102108
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
103109
github.com/tetratelabs/wazero v1.3.0 // indirect
110+
github.com/tliron/commonlog v0.2.19 // indirect
111+
github.com/tliron/kutil v0.3.27 // indirect
104112
github.com/vbatts/tar-split v0.11.3 // indirect
105113
github.com/x448/float16 v0.8.4 // indirect
106114
github.com/xlab/treeprint v1.2.0 // indirect
@@ -117,10 +125,12 @@ require (
117125
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
118126
go.opentelemetry.io/otel/trace v1.38.0 // indirect
119127
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
128+
golang.org/x/net v0.47.0 // indirect
120129
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect
121130
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
122131
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 // indirect
123132
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
133+
sigs.k8s.io/randfill v1.0.0 // indirect
124134
)
125135

126136
require (
@@ -149,12 +159,12 @@ require (
149159
github.com/cockroachdb/errors v1.12.0 // indirect
150160
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
151161
github.com/cockroachdb/redact v1.1.6 // indirect
152-
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
162+
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
153163
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
154164
github.com/dlclark/regexp2 v1.11.0 // indirect
155165
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
156166
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
157-
github.com/fatih/color v1.15.0 // indirect
167+
github.com/fatih/color v1.16.0 // indirect
158168
github.com/getsentry/sentry-go v0.27.0 // indirect
159169
github.com/ghodss/yaml v1.0.0 // indirect
160170
github.com/go-logr/logr v1.4.3 // indirect
@@ -205,8 +215,8 @@ require (
205215
github.com/rogpeppe/go-internal v1.13.1 // indirect
206216
github.com/russross/blackfriday/v2 v2.1.0 // indirect
207217
github.com/sourcegraph/log v0.0.0-20250923023806-517b6960b55b // indirect
208-
github.com/spf13/cobra v1.7.0 // indirect
209-
github.com/spf13/pflag v1.0.5 // indirect
218+
github.com/spf13/cobra v1.9.1 // indirect
219+
github.com/spf13/pflag v1.0.6 // indirect
210220
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
211221
github.com/stretchr/objx v0.5.2 // indirect
212222
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
@@ -230,11 +240,11 @@ require (
230240
gopkg.in/inf.v0 v0.9.1 // indirect; direct
231241
gopkg.in/yaml.v2 v2.4.0 // indirect
232242
k8s.io/klog/v2 v2.130.1 // indirect
233-
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
243+
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
234244
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
235245
mvdan.cc/gofumpt v0.5.0 // indirect
236246
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
237-
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
247+
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
238248
sigs.k8s.io/yaml v1.4.0 // indirect
239249
)
240250

0 commit comments

Comments
 (0)