1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
// Package lspx contains extensions to the LSP protocol.
//
// An overview of the different protocol variants:
//
// // vanilla LSP
// github.com/sourcegraph/go-langserver/pkg/lsp
//
// // proxy (http gateway) server LSP extensions
// github.com/sourcegraph/sourcegraph/xlang
//
// // (this package) build/lang server LSP extensions
// github.com/sourcegraph/sourcegraph/xlang/lspx
//
package lspext
import (
"reflect"
"time"
"github.com/sourcegraph/go-lsp"
)
// DependencyReference represents a reference to a dependency. []DependencyReference
// is the return type for the build server workspace/xdependencies method.
type DependencyReference struct {
// Attributes describing the dependency that is being referenced. It is up
// to the language server to define the schema of this object.
Attributes map[string]interface{} `json:"attributes,omitempty"`
// Hints is treated as an opaque object and passed directly by Sourcegraph
// into the language server's workspace/xreferences method to help narrow
// down the search space for the references to the symbol.
//
// If a language server emits no hints, Sourcegraph will pass none as a
// parameter to workspace/xreferences which means it must search the entire
// repository (workspace) in order to find references. workspace/xdependencies
// should emit sufficient hints here for making all workspace/xreference
// queries complete in a reasonable amount of time (less than a few seconds
// for very large repositories). For example, one may include the
// containing "package" or other build-system level "code unit". Emitting
// the exact file is not recommended in general as that would produce more
// data for little performance gain in most situations.
Hints map[string]interface{} `json:"hints,omitempty"`
}
// TelemetryEventParams is a telemetry/event message sent from a
// build/lang server back to the proxy. The information here is
// forwarded to our opentracing system.
type TelemetryEventParams struct {
Op string `json:"op"` // the operation name
StartTime time.Time `json:"startTime"` // when the operation started
EndTime time.Time `json:"endTime"` // when the operation ended
Tags map[string]string `json:"tags,omitempty"` // other metadata
}
type InitializeParams struct {
lsp.InitializeParams
// OriginalRootURI is the original rootUri for this LSP session,
// before any path rewriting occurred. It is typically a Git clone
// URL of the form
// "git://github.com/facebook/react.git?rev=master#lib".
//
// The Go lang/build server uses this to infer the import path
// root (and directory structure) to use for a workspace.
OriginalRootURI lsp.DocumentURI `json:"originalRootUri"`
// Mode is the name of the language. It is used to determine the correct
// language server to route a request to, and to inform a language server
// what languages it should contribute.
Mode string `json:"mode"`
}
// WalkURIFields walks the LSP params/result object for fields
// containing document URIs.
//
// If collect is non-nil, it calls collect(uri) for every URI
// encountered. Callers can use this to collect a list of all document
// URIs referenced in the params/result.
//
// If update is non-nil, it updates all document URIs in an LSP
// params/result with the value of f(existingURI). Callers can use
// this to rewrite paths in the params/result.
//
// TODO(sqs): does not support WorkspaceEdit (with a field whose
// TypeScript type is {[uri: string]: TextEdit[]}.
func WalkURIFields(o interface{}, collect func(lsp.DocumentURI), update func(lsp.DocumentURI) lsp.DocumentURI) {
var walk func(o interface{})
walk = func(o interface{}) {
switch o := o.(type) {
case map[string]interface{}:
for k, v := range o { // Location, TextDocumentIdentifier, TextDocumentItem, etc.
if k == "uri" {
s, ok := v.(string)
if !ok {
s2, ok2 := v.(lsp.DocumentURI)
s = string(s2)
ok = ok2
}
if ok {
if collect != nil {
collect(lsp.DocumentURI(s))
}
if update != nil {
o[k] = update(lsp.DocumentURI(s))
}
continue
}
}
walk(v)
}
case []interface{}: // Location[]
for _, v := range o {
walk(v)
}
default: // structs with a "URI" field
rv := reflect.ValueOf(o)
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
if rv.Kind() == reflect.Struct {
if fv := rv.FieldByName("URI"); fv.Kind() == reflect.String {
if collect != nil {
collect(lsp.DocumentURI(fv.String()))
}
if update != nil {
fv.SetString(string(update(lsp.DocumentURI(fv.String()))))
}
}
for i := 0; i < rv.NumField(); i++ {
fv := rv.Field(i)
if fv.Kind() == reflect.Ptr || fv.Kind() == reflect.Struct || fv.Kind() == reflect.Array {
walk(fv.Interface())
}
}
}
}
}
walk(o)
}
// ClientProxyInitializeParams are sent by the client to the proxy in
// the "initialize" request. It has a non-standard field "mode", which
// is the name of the language (using vscode terminology); "go" or
// "typescript", for example.
type ClientProxyInitializeParams struct {
lsp.InitializeParams
InitializationOptions ClientProxyInitializationOptions `json:"initializationOptions"`
// Mode is DEPRECATED; it was moved to the subfield
// initializationOptions.Mode. It is still here for backward
// compatibility until the xlang service is upgraded.
Mode string `json:"mode,omitempty"`
}
// ClientProxyInitializationOptions is the "initializationOptions"
// field of the "initialize" request params sent from the client to
// the LSP client proxy.
type ClientProxyInitializationOptions struct {
Mode string `json:"mode"`
// Same as, but takes precedence over, InitializeParams.rootUri.
// vscode-languageserver-node's LanguageClient doesn't allow overriding
// InitializeParams.rootUri, so clients that use vscode-languageserver-node
// instead set InitializeParams.initializationOptions.rootUri.
RootURI *lsp.DocumentURI `json:"rootUri,omitempty"`
// Session, if set, causes this session to be isolated from other
// LSP sessions using the same workspace and mode. See
// (contextID).session for more information.
Session string `json:"session,omitempty"`
// ZipURL is the zip URL to forward to the language server.
ZipURL string `json:"zipURL,omitempty"`
}
|