pax_global_header00006660000000000000000000000064142250210450014505gustar00rootroot0000000000000052 comment=f0a2b0c3e59965b1a8a362916b8bfd5fd38acd60 golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/000077500000000000000000000000001422502104500223245ustar00rootroot00000000000000golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/.github/000077500000000000000000000000001422502104500236645ustar00rootroot00000000000000golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/.github/workflows/000077500000000000000000000000001422502104500257215ustar00rootroot00000000000000golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/.github/workflows/lsif.yml000066400000000000000000000004601422502104500274010ustar00rootroot00000000000000name: LSIF on: - push jobs: lsif-go: runs-on: ubuntu-latest container: sourcegraph/lsif-go steps: - uses: actions/checkout@v1 - name: Generate LSIF data run: lsif-go - name: Upload LSIF data run: src lsif upload -github-token=${{ secrets.GITHUB_TOKEN }} golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/LICENSE000066400000000000000000000020371422502104500233330ustar00rootroot00000000000000Copyright (c) 2018 Sourcegraph Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/README.md000066400000000000000000000003101422502104500235750ustar00rootroot00000000000000# go-lsp Package lsp contains Go types for the messages used in the Language Server Protocol. See https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md for more information. golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/doc.go000066400000000000000000000003301422502104500234140ustar00rootroot00000000000000// Package lsp contains Go types for the messages used in the Language // Server Protocol. // // See https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md // for more information. package lsp golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/go.mod000066400000000000000000000000561422502104500234330ustar00rootroot00000000000000module github.com/sourcegraph/go-lsp go 1.14 golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/jsonrpc2.go000066400000000000000000000023021422502104500244100ustar00rootroot00000000000000package lsp import ( "encoding/json" "strconv" ) // ID represents a JSON-RPC 2.0 request ID, which may be either a // string or number (or null, which is unsupported). type ID struct { // At most one of Num or Str may be nonzero. If both are zero // valued, then IsNum specifies which field's value is to be used // as the ID. Num uint64 Str string // IsString controls whether the Num or Str field's value should be // used as the ID, when both are zero valued. It must always be // set to true if the request ID is a string. IsString bool } func (id ID) String() string { if id.IsString { return strconv.Quote(id.Str) } return strconv.FormatUint(id.Num, 10) } // MarshalJSON implements json.Marshaler. func (id ID) MarshalJSON() ([]byte, error) { if id.IsString { return json.Marshal(id.Str) } return json.Marshal(id.Num) } // UnmarshalJSON implements json.Unmarshaler. func (id *ID) UnmarshalJSON(data []byte) error { // Support both uint64 and string IDs. var v uint64 if err := json.Unmarshal(data, &v); err == nil { *id = ID{Num: v} return nil } var v2 string if err := json.Unmarshal(data, &v2); err != nil { return err } *id = ID{Str: v2, IsString: true} return nil } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/000077500000000000000000000000001422502104500236435ustar00rootroot00000000000000golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/cache.go000066400000000000000000000021421422502104500252340ustar00rootroot00000000000000package lspext import "encoding/json" // See https://github.com/sourcegraph/language-server-protocol/pull/14 // CacheGetParams is the input for 'cache/get'. The response is any or null. type CacheGetParams struct { // Key is the cache key. The key namespace is shared for a language // server, but with other language servers. For example the PHP // language server on different workspaces share the same key // namespace, but does not share the namespace with a Go language // server. Key string `json:"key"` } // CacheSetParams is the input for the notification 'cache/set'. type CacheSetParams struct { // Key is the cache key. The key namespace is shared for a language // server, but with other language servers. For example the PHP // language server on different workspaces share the same key // namespace, but does not share the namespace with a Go language // server. Key string `json:"key"` // Value is type any. We use json.RawMessage since we expect caching // implementation to cache the raw bytes, and not bother with // Unmarshaling/Marshalling. Value *json.RawMessage `json:"value"` } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/context_exec.go000066400000000000000000000005651422502104500266700ustar00rootroot00000000000000package lspext // ExecParams contains the parameters for the exec LSP request. type ExecParams struct { Command string `json:"command"` Arguments []string `json:"arguments"` } // ExecResult contains the result for the exec LSP response. type ExecResult struct { Stdout string `json:"stdout"` Stderr string `json:"stderr"` ExitCode int `json:"exitCode"` } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/filesext.go000066400000000000000000000007411422502104500260170ustar00rootroot00000000000000package lspext import "github.com/sourcegraph/go-lsp" // See https://github.com/sourcegraph/language-server-protocol/pull/4. // ContentParams is the input for 'textDocument/content'. The response is a // 'TextDocumentItem'. type ContentParams struct { TextDocument lsp.TextDocumentIdentifier `json:"textDocument"` } // FilesParams is the input for 'workspace/xfiles'. The response is '[]TextDocumentIdentifier' type FilesParams struct { Base string `json:"base,omitempty"` } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/fs.go000066400000000000000000000011561422502104500246050ustar00rootroot00000000000000package lspext import ( "os" "path" "time" ) // FileInfo is the map-based implementation of FileInfo. type FileInfo struct { Name_ string `json:"name"` Size_ int64 `json:"size"` Dir_ bool `json:"dir"` } func (fi FileInfo) IsDir() bool { return fi.Dir_ } func (fi FileInfo) ModTime() time.Time { return time.Time{} } func (fi FileInfo) Mode() os.FileMode { if fi.IsDir() { return 0755 | os.ModeDir } return 0444 } func (fi FileInfo) Name() string { return path.Base(fi.Name_) } func (fi FileInfo) Size() int64 { return int64(fi.Size_) } func (fi FileInfo) Sys() interface{} { return nil } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/implementation.go000066400000000000000000000023301422502104500272150ustar00rootroot00000000000000package lspext import "github.com/sourcegraph/go-lsp" // ImplementationLocation is a superset of lsp.Location with additional Go-specific information // about the implementation. type ImplementationLocation struct { lsp.Location // the location of the implementation // Type is the type of implementation relationship described by this location. // // If a type T was queried, the set of possible values are: // // - "to": named or ptr-to-named types assignable to interface T // - "from": named interfaces assignable from T (or only from *T if Ptr == true) // // If a method M on type T was queried, the same set of values above is used, except they refer // to methods on the described type (not the described type itself). // // (This type description is taken from golang.org/x/tools/cmd/guru.) Type string `json:"type,omitempty"` // Ptr is whether this implementation location is only assignable from a pointer *T (where T is // the queried type). Ptr bool `json:"ptr,omitempty"` // Method is whether a method was queried. If so, then the implementation locations refer to the // corresponding methods on the types found by the implementation query (not the types // themselves). Method bool `json:"method"` } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/lspext.go000066400000000000000000000061331422502104500255140ustar00rootroot00000000000000package lspext import ( "fmt" "sort" "strings" "github.com/sourcegraph/go-lsp" ) // WorkspaceSymbolParams is the extension workspace/symbol parameter type. type WorkspaceSymbolParams struct { Query string `json:"query,omitempty"` Limit int `json:"limit"` Symbol SymbolDescriptor `json:"symbol,omitempty"` } // WorkspaceReferencesParams is parameters for the `workspace/xreferences` extension // // See: https://github.com/sourcegraph/language-server-protocol/blob/master/extension-workspace-reference.md // type WorkspaceReferencesParams struct { // Query represents metadata about the symbol that is being searched for. Query SymbolDescriptor `json:"query"` // Hints provides optional hints about where the language server should // look in order to find the symbol (this is an optimization). It is up to // the language server to define the schema of this object. Hints map[string]interface{} `json:"hints,omitempty"` // Limit if positive will limit the number of results returned. Limit int `json:"limit,omitempty"` } // ReferenceInformation represents information about a reference to programming // constructs like variables, classes, interfaces etc. type ReferenceInformation struct { // Reference is the location in the workspace where the `symbol` has been // referenced. Reference lsp.Location `json:"reference"` // Symbol is metadata information describing the symbol being referenced. Symbol SymbolDescriptor `json:"symbol"` } // SymbolDescriptor represents information about a programming construct like a // variable, class, interface, etc that has a reference to it. It is up to the // language server to define the schema of this object. // // SymbolDescriptor usually uniquely identifies a symbol, but it is not // guaranteed to do so. type SymbolDescriptor map[string]interface{} // SymbolLocationInformation is the response type for the `textDocument/xdefinition` extension. type SymbolLocationInformation struct { // A concrete location at which the definition is located, if any. Location lsp.Location `json:"location,omitempty"` // Metadata about the definition. Symbol SymbolDescriptor `json:"symbol"` } // Contains tells if this SymbolDescriptor fully contains all of the keys and // values in the other symbol descriptor. func (s SymbolDescriptor) Contains(other SymbolDescriptor) bool { for k, v := range other { v2, ok := s[k] if !ok || v != v2 { return false } } return true } // String returns a consistently ordered string representation of the // SymbolDescriptor. It is useful for testing. func (s SymbolDescriptor) String() string { sm := make(sortedMap, 0, len(s)) for k, v := range s { sm = append(sm, mapValue{key: k, value: v}) } sort.Sort(sm) var str string for _, v := range sm { str += fmt.Sprintf("%s:%v ", v.key, v.value) } return strings.TrimSpace(str) } type mapValue struct { key string value interface{} } type sortedMap []mapValue func (s sortedMap) Len() int { return len(s) } func (s sortedMap) Less(i, j int) bool { return s[i].key < s[j].key } func (s sortedMap) Swap(i, j int) { s[i], s[j] = s[j], s[i] } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/partial.go000066400000000000000000000007641422502104500256350ustar00rootroot00000000000000package lspext import "github.com/sourcegraph/go-lsp" // PartialResultParams is the input for "$/partialResult", a notification. type PartialResultParams struct { // ID is the jsonrpc2 ID of the request we are returning partial // results for. ID lsp.ID `json:"id"` // Patch is a JSON patch as specified at http://jsonpatch.com/ // // It is an interface{}, since our only requirement is that it JSON // marshals to a valid list of JSON Patch operations. Patch interface{} `json:"patch"` } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/proxy_lspext.go000066400000000000000000000144071422502104500267600ustar00rootroot00000000000000// 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"` } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/proxy_lspext_test.go000066400000000000000000000031321422502104500300100ustar00rootroot00000000000000package lspext import ( "encoding/json" "reflect" "strings" "testing" "github.com/sourcegraph/go-lsp" ) func TestWalkURIFields(t *testing.T) { tests := map[string][]lsp.DocumentURI{ `{"textDocument":{"uri":"u1"}}`: []lsp.DocumentURI{"u1"}, `{"uri":"u1"}`: []lsp.DocumentURI{"u1"}, } for objStr, wantURIs := range tests { var obj interface{} if err := json.Unmarshal([]byte(objStr), &obj); err != nil { t.Error(err) continue } var uris []lsp.DocumentURI collect := func(uri lsp.DocumentURI) { uris = append(uris, uri) } update := func(uri lsp.DocumentURI) lsp.DocumentURI { return "XXX" } WalkURIFields(obj, collect, update) if !reflect.DeepEqual(uris, wantURIs) { t.Errorf("%s: got URIs %q, want %q", objStr, uris, wantURIs) } wantObj := objStr for _, uri := range uris { wantObj = strings.Replace(wantObj, string(uri), "XXX", -1) } gotObj, err := json.Marshal(obj) if err != nil { t.Error(err) continue } if string(gotObj) != wantObj { t.Errorf("%s: got obj %q, want %q after updating URI pointers", objStr, gotObj, wantObj) } } } func TestWalkURIFields_struct(t *testing.T) { v := lsp.PublishDiagnosticsParams{URI: "u1"} var uris []lsp.DocumentURI collect := func(uri lsp.DocumentURI) { uris = append(uris, uri) } update := func(uri lsp.DocumentURI) lsp.DocumentURI { return "XXX" } WalkURIFields(&v, collect, update) if want := []lsp.DocumentURI{"u1"}; !reflect.DeepEqual(uris, want) { t.Errorf("got %v, want %v", uris, want) } if want := "XXX"; string(v.URI) != want { t.Errorf("got %q, want %q", v.URI, want) } } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/lspext/workspace_packages.go000066400000000000000000000031711422502104500300300ustar00rootroot00000000000000package lspext import ( "fmt" "sort" "strings" ) // WorkspacePackagesParams is parameters for the `workspace/xpackages` extension. // // See: https://github.com/sourcegraph/language-server-protocol/blob/7fd3c1/extension-workspace-references.md type WorkspacePackagesParams struct{} // PackageInformation is the metadata associated with a build-system- // or package-manager-level package. Sometimes, languages have // abstractions called "packages" as well, but this refers // specifically to packages as defined by the build system or package // manager. E.g., Python pip packages (NOT Python language packages or // modules), Go packages, Maven packages (NOT Java language packages), // npm modules (NOT JavaScript language modules). PackageInformation // includes both attributes of the package itself and attributes of // the package's dependencies. type PackageInformation struct { // Package is the set of attributes of the package Package PackageDescriptor `json:"package,omitempty"` // Dependencies is the list of dependency attributes Dependencies []DependencyReference `json:"dependencies,omitempty"` } // PackageDescriptor identifies a package (usually but not always uniquely). type PackageDescriptor map[string]interface{} // String returns a consistently ordered string representation of the // PackageDescriptor. It is useful for testing. func (s PackageDescriptor) String() string { sm := make(sortedMap, 0, len(s)) for k, v := range s { sm = append(sm, mapValue{key: k, value: v}) } sort.Sort(sm) var str string for _, v := range sm { str += fmt.Sprintf("%s:%v ", v.key, v.value) } return strings.TrimSpace(str) } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/service.go000066400000000000000000000656011422502104500243230ustar00rootroot00000000000000package lsp import ( "bytes" "encoding/base64" "encoding/binary" "encoding/json" "strings" ) type None struct{} type InitializeParams struct { ProcessID int `json:"processId,omitempty"` // RootPath is DEPRECATED in favor of the RootURI field. RootPath string `json:"rootPath,omitempty"` RootURI DocumentURI `json:"rootUri,omitempty"` ClientInfo ClientInfo `json:"clientInfo,omitempty"` Trace Trace `json:"trace,omitempty"` InitializationOptions interface{} `json:"initializationOptions,omitempty"` Capabilities ClientCapabilities `json:"capabilities"` WorkDoneToken string `json:"workDoneToken,omitempty"` } // Root returns the RootURI if set, or otherwise the RootPath with 'file://' prepended. func (p *InitializeParams) Root() DocumentURI { if p.RootURI != "" { return p.RootURI } if strings.HasPrefix(p.RootPath, "file://") { return DocumentURI(p.RootPath) } return DocumentURI("file://" + p.RootPath) } type DocumentURI string type ClientInfo struct { Name string `json:"name,omitempty"` Version string `json:"version,omitempty"` } type Trace string type ClientCapabilities struct { Workspace WorkspaceClientCapabilities `json:"workspace,omitempty"` TextDocument TextDocumentClientCapabilities `json:"textDocument,omitempty"` Window WindowClientCapabilities `json:"window,omitempty"` Experimental interface{} `json:"experimental,omitempty"` // Below are Sourcegraph extensions. They do not live in lspext since // they are extending the field InitializeParams.Capabilities // XFilesProvider indicates the client provides support for // workspace/xfiles. This is a Sourcegraph extension. XFilesProvider bool `json:"xfilesProvider,omitempty"` // XContentProvider indicates the client provides support for // textDocument/xcontent. This is a Sourcegraph extension. XContentProvider bool `json:"xcontentProvider,omitempty"` // XCacheProvider indicates the client provides support for cache/get // and cache/set. XCacheProvider bool `json:"xcacheProvider,omitempty"` } type WorkspaceClientCapabilities struct { WorkspaceEdit struct { DocumentChanges bool `json:"documentChanges,omitempty"` ResourceOperations []string `json:"resourceOperations,omitempty"` } `json:"workspaceEdit,omitempty"` ApplyEdit bool `json:"applyEdit,omitempty"` Symbol struct { SymbolKind struct { ValueSet []int `json:"valueSet,omitempty"` } `json:"symbolKind,omitEmpty"` } `json:"symbol,omitempty"` ExecuteCommand *struct { DynamicRegistration bool `json:"dynamicRegistration,omitempty"` } `json:"executeCommand,omitempty"` DidChangeWatchedFiles *struct { DynamicRegistration bool `json:"dynamicRegistration,omitempty"` } `json:"didChangeWatchedFiles,omitempty"` WorkspaceFolders bool `json:"workspaceFolders,omitempty"` Configuration bool `json:"configuration,omitempty"` } type TextDocumentClientCapabilities struct { Declaration *struct { LinkSupport bool `json:"linkSupport,omitempty"` } `json:"declaration,omitempty"` Definition *struct { LinkSupport bool `json:"linkSupport,omitempty"` } `json:"definition,omitempty"` Implementation *struct { LinkSupport bool `json:"linkSupport,omitempty"` DynamicRegistration bool `json:"dynamicRegistration,omitempty"` } `json:"implementation,omitempty"` TypeDefinition *struct { LinkSupport bool `json:"linkSupport,omitempty"` } `json:"typeDefinition,omitempty"` Synchronization *struct { WillSave bool `json:"willSave,omitempty"` DidSave bool `json:"didSave,omitempty"` WillSaveWaitUntil bool `json:"willSaveWaitUntil,omitempty"` } `json:"synchronization,omitempty"` DocumentSymbol struct { SymbolKind struct { ValueSet []int `json:"valueSet,omitempty"` } `json:"symbolKind,omitEmpty"` HierarchicalDocumentSymbolSupport bool `json:"hierarchicalDocumentSymbolSupport,omitempty"` } `json:"documentSymbol,omitempty"` Formatting *struct { DynamicRegistration bool `json:"dynamicRegistration,omitempty"` } `json:"formatting,omitempty"` RangeFormatting *struct { DynamicRegistration bool `json:"dynamicRegistration,omitempty"` } `json:"rangeFormatting,omitempty"` Rename *struct { DynamicRegistration bool `json:"dynamicRegistration,omitempty"` PrepareSupport bool `json:"prepareSupport,omitempty"` } `json:"rename,omitempty"` SemanticHighlightingCapabilities *struct { SemanticHighlighting bool `json:"semanticHighlighting,omitempty"` } `json:"semanticHighlightingCapabilities,omitempty"` CodeAction struct { DynamicRegistration bool `json:"dynamicRegistration,omitempty"` IsPreferredSupport bool `json:"isPreferredSupport,omitempty"` CodeActionLiteralSupport struct { CodeActionKind struct { ValueSet []CodeActionKind `json:"valueSet,omitempty"` } `json:"codeActionKind,omitempty"` } `json:"codeActionLiteralSupport,omitempty"` } `json:"codeAction,omitempty"` Completion struct { CompletionItem struct { DocumentationFormat []DocumentationFormat `json:"documentationFormat,omitempty"` SnippetSupport bool `json:"snippetSupport,omitempty"` } `json:"completionItem,omitempty"` CompletionItemKind struct { ValueSet []CompletionItemKind `json:"valueSet,omitempty"` } `json:"completionItemKind,omitempty"` ContextSupport bool `json:"contextSupport,omitempty"` } `json:"completion,omitempty"` SignatureHelp *struct { SignatureInformation struct { ParameterInformation struct { LabelOffsetSupport bool `json:"labelOffsetSupport,omitempty"` } `json:"parameterInformation,omitempty"` } `json:"signatureInformation,omitempty"` } `json:"signatureHelp,omitempty"` DocumentLink *struct { DynamicRegistration bool `json:"dynamicRegistration,omitempty"` TooltipSupport bool `json:"tooltipSupport,omitempty"` } `json:"documentLink,omitempty"` Hover *struct { ContentFormat []string `json:"contentFormat,omitempty"` } `json:"hover,omitempty"` FoldingRange *struct { DynamicRegistration bool `json:"dynamicRegistration,omitempty"` RangeLimit interface{} `json:"rangeLimit,omitempty"` LineFoldingOnly bool `json:"lineFoldingOnly,omitempty"` } `json:"foldingRange,omitempty"` CallHierarchy *struct { DynamicRegistration bool `json:"dynamicRegistration,omitempty"` } `json:"callHierarchy,omitempty"` ColorProvider *struct { DynamicRegistration bool `json:"dynamicRegistration,omitempty"` } `json:"colorProvider,omitempty"` } type WindowClientCapabilities struct { WorkDoneProgress bool `json:"workDoneProgress,omitempty"` } type InitializeResult struct { Capabilities ServerCapabilities `json:"capabilities,omitempty"` } type InitializeError struct { Retry bool `json:"retry"` } type ResourceOperation string const ( ROCreate ResourceOperation = "create" RODelete ResourceOperation = "delete" RORename ResourceOperation = "rename" ) // TextDocumentSyncKind is a DEPRECATED way to describe how text // document syncing works. Use TextDocumentSyncOptions instead (or the // Options field of TextDocumentSyncOptionsOrKind if you need to // support JSON-(un)marshaling both). type TextDocumentSyncKind int const ( TDSKNone TextDocumentSyncKind = 0 TDSKFull TextDocumentSyncKind = 1 TDSKIncremental TextDocumentSyncKind = 2 ) type TextDocumentSyncOptions struct { OpenClose bool `json:"openClose,omitempty"` Change TextDocumentSyncKind `json:"change"` WillSave bool `json:"willSave,omitempty"` WillSaveWaitUntil bool `json:"willSaveWaitUntil,omitempty"` Save *SaveOptions `json:"save,omitempty"` } // TextDocumentSyncOptions holds either a TextDocumentSyncKind or // TextDocumentSyncOptions. The LSP API allows either to be specified // in the (ServerCapabilities).TextDocumentSync field. type TextDocumentSyncOptionsOrKind struct { Kind *TextDocumentSyncKind Options *TextDocumentSyncOptions } // MarshalJSON implements json.Marshaler. func (v *TextDocumentSyncOptionsOrKind) MarshalJSON() ([]byte, error) { if v == nil { return []byte("null"), nil } if v.Kind != nil { return json.Marshal(v.Kind) } return json.Marshal(v.Options) } // UnmarshalJSON implements json.Unmarshaler. func (v *TextDocumentSyncOptionsOrKind) UnmarshalJSON(data []byte) error { if bytes.Equal(data, []byte("null")) { *v = TextDocumentSyncOptionsOrKind{} return nil } var kind TextDocumentSyncKind if err := json.Unmarshal(data, &kind); err == nil { // Create equivalent TextDocumentSyncOptions using the same // logic as in vscode-languageclient. Also set the Kind field // so that JSON-marshaling and unmarshaling are inverse // operations (for backward compatibility, preserving the // original input but accepting both). *v = TextDocumentSyncOptionsOrKind{ Options: &TextDocumentSyncOptions{OpenClose: true, Change: kind}, Kind: &kind, } return nil } var tmp TextDocumentSyncOptions if err := json.Unmarshal(data, &tmp); err != nil { return err } *v = TextDocumentSyncOptionsOrKind{Options: &tmp} return nil } type SaveOptions struct { IncludeText bool `json:"includeText"` } type ServerCapabilities struct { TextDocumentSync *TextDocumentSyncOptionsOrKind `json:"textDocumentSync,omitempty"` HoverProvider bool `json:"hoverProvider,omitempty"` CompletionProvider *CompletionOptions `json:"completionProvider,omitempty"` SignatureHelpProvider *SignatureHelpOptions `json:"signatureHelpProvider,omitempty"` DefinitionProvider bool `json:"definitionProvider,omitempty"` TypeDefinitionProvider bool `json:"typeDefinitionProvider,omitempty"` ReferencesProvider bool `json:"referencesProvider,omitempty"` DocumentHighlightProvider bool `json:"documentHighlightProvider,omitempty"` DocumentSymbolProvider bool `json:"documentSymbolProvider,omitempty"` WorkspaceSymbolProvider bool `json:"workspaceSymbolProvider,omitempty"` ImplementationProvider bool `json:"implementationProvider,omitempty"` CodeActionProvider bool `json:"codeActionProvider,omitempty"` CodeLensProvider *CodeLensOptions `json:"codeLensProvider,omitempty"` DocumentFormattingProvider bool `json:"documentFormattingProvider,omitempty"` DocumentRangeFormattingProvider bool `json:"documentRangeFormattingProvider,omitempty"` DocumentOnTypeFormattingProvider *DocumentOnTypeFormattingOptions `json:"documentOnTypeFormattingProvider,omitempty"` RenameProvider bool `json:"renameProvider,omitempty"` ExecuteCommandProvider *ExecuteCommandOptions `json:"executeCommandProvider,omitempty"` SemanticHighlighting *SemanticHighlightingOptions `json:"semanticHighlighting,omitempty"` // XWorkspaceReferencesProvider indicates the server provides support for // xworkspace/references. This is a Sourcegraph extension. XWorkspaceReferencesProvider bool `json:"xworkspaceReferencesProvider,omitempty"` // XDefinitionProvider indicates the server provides support for // textDocument/xdefinition. This is a Sourcegraph extension. XDefinitionProvider bool `json:"xdefinitionProvider,omitempty"` // XWorkspaceSymbolByProperties indicates the server provides support for // querying symbols by properties with WorkspaceSymbolParams.symbol. This // is a Sourcegraph extension. XWorkspaceSymbolByProperties bool `json:"xworkspaceSymbolByProperties,omitempty"` Experimental interface{} `json:"experimental,omitempty"` } type CompletionOptions struct { ResolveProvider bool `json:"resolveProvider,omitempty"` TriggerCharacters []string `json:"triggerCharacters,omitempty"` } type DocumentOnTypeFormattingOptions struct { FirstTriggerCharacter string `json:"firstTriggerCharacter"` MoreTriggerCharacter []string `json:"moreTriggerCharacter,omitempty"` } type CodeLensOptions struct { ResolveProvider bool `json:"resolveProvider,omitempty"` } type SignatureHelpOptions struct { TriggerCharacters []string `json:"triggerCharacters,omitempty"` } type ExecuteCommandOptions struct { Commands []string `json:"commands"` } type ExecuteCommandParams struct { Command string `json:"command"` Arguments []interface{} `json:"arguments,omitempty"` } type SemanticHighlightingOptions struct { Scopes [][]string `json:"scopes,omitempty"` } type CompletionItemKind int const ( _ CompletionItemKind = iota CIKText CIKMethod CIKFunction CIKConstructor CIKField CIKVariable CIKClass CIKInterface CIKModule CIKProperty CIKUnit CIKValue CIKEnum CIKKeyword CIKSnippet CIKColor CIKFile CIKReference CIKFolder CIKEnumMember CIKConstant CIKStruct CIKEvent CIKOperator CIKTypeParameter ) func (c CompletionItemKind) String() string { return completionItemKindName[c] } var completionItemKindName = map[CompletionItemKind]string{ CIKText: "text", CIKMethod: "method", CIKFunction: "function", CIKConstructor: "constructor", CIKField: "field", CIKVariable: "variable", CIKClass: "class", CIKInterface: "interface", CIKModule: "module", CIKProperty: "property", CIKUnit: "unit", CIKValue: "value", CIKEnum: "enum", CIKKeyword: "keyword", CIKSnippet: "snippet", CIKColor: "color", CIKFile: "file", CIKReference: "reference", CIKFolder: "folder", CIKEnumMember: "enumMember", CIKConstant: "constant", CIKStruct: "struct", CIKEvent: "event", CIKOperator: "operator", CIKTypeParameter: "typeParameter", } type CompletionItem struct { Label string `json:"label"` Kind CompletionItemKind `json:"kind,omitempty"` Detail string `json:"detail,omitempty"` Documentation string `json:"documentation,omitempty"` SortText string `json:"sortText,omitempty"` FilterText string `json:"filterText,omitempty"` InsertText string `json:"insertText,omitempty"` InsertTextFormat InsertTextFormat `json:"insertTextFormat,omitempty"` TextEdit *TextEdit `json:"textEdit,omitempty"` Data interface{} `json:"data,omitempty"` } type CompletionList struct { IsIncomplete bool `json:"isIncomplete"` Items []CompletionItem `json:"items"` } type CompletionTriggerKind int const ( CTKInvoked CompletionTriggerKind = 1 CTKTriggerCharacter = 2 ) type DocumentationFormat string const ( DFPlainText DocumentationFormat = "plaintext" ) type CodeActionKind string const ( CAKEmpty CodeActionKind = "" CAKQuickFix CodeActionKind = "quickfix" CAKRefactor CodeActionKind = "refactor" CAKRefactorExtract CodeActionKind = "refactor.extract" CAKRefactorInline CodeActionKind = "refactor.inline" CAKRefactorRewrite CodeActionKind = "refactor.rewrite" CAKSource CodeActionKind = "source" CAKSourceOrganizeImports CodeActionKind = "source.organizeImports" ) type InsertTextFormat int const ( ITFPlainText InsertTextFormat = 1 ITFSnippet = 2 ) type CompletionContext struct { TriggerKind CompletionTriggerKind `json:"triggerKind"` TriggerCharacter string `json:"triggerCharacter,omitempty"` } type CompletionParams struct { TextDocumentPositionParams Context CompletionContext `json:"context,omitempty"` } type Hover struct { Contents []MarkedString `json:"contents"` Range *Range `json:"range,omitempty"` } type hover Hover func (h Hover) MarshalJSON() ([]byte, error) { if h.Contents == nil { return json.Marshal(hover{ Contents: []MarkedString{}, Range: h.Range, }) } return json.Marshal(hover(h)) } type MarkedString markedString type markedString struct { Language string `json:"language"` Value string `json:"value"` isRawString bool } func (m *MarkedString) UnmarshalJSON(data []byte) error { if d := strings.TrimSpace(string(data)); len(d) > 0 && d[0] == '"' { // Raw string var s string if err := json.Unmarshal(data, &s); err != nil { return err } m.Value = s m.isRawString = true return nil } // Language string ms := (*markedString)(m) return json.Unmarshal(data, ms) } func (m MarkedString) MarshalJSON() ([]byte, error) { if m.isRawString { return json.Marshal(m.Value) } return json.Marshal((markedString)(m)) } // RawMarkedString returns a MarkedString consisting of only a raw // string (i.e., "foo" instead of {"value":"foo", "language":"bar"}). func RawMarkedString(s string) MarkedString { return MarkedString{Value: s, isRawString: true} } type SignatureHelp struct { Signatures []SignatureInformation `json:"signatures"` ActiveSignature int `json:"activeSignature"` ActiveParameter int `json:"activeParameter"` } type SignatureInformation struct { Label string `json:"label"` Documentation string `json:"documentation,omitempty"` Parameters []ParameterInformation `json:"parameters,omitempty"` } type ParameterInformation struct { Label string `json:"label"` Documentation string `json:"documentation,omitempty"` } type ReferenceContext struct { IncludeDeclaration bool `json:"includeDeclaration"` // Sourcegraph extension XLimit int `json:"xlimit,omitempty"` } type ReferenceParams struct { TextDocumentPositionParams Context ReferenceContext `json:"context"` } type DocumentHighlightKind int const ( Text DocumentHighlightKind = 1 Read = 2 Write = 3 ) type DocumentHighlight struct { Range Range `json:"range"` Kind int `json:"kind,omitempty"` } type DocumentSymbolParams struct { TextDocument TextDocumentIdentifier `json:"textDocument"` } type SymbolKind int // The SymbolKind values are defined at https://microsoft.github.io/language-server-protocol/specification. const ( SKFile SymbolKind = 1 SKModule SymbolKind = 2 SKNamespace SymbolKind = 3 SKPackage SymbolKind = 4 SKClass SymbolKind = 5 SKMethod SymbolKind = 6 SKProperty SymbolKind = 7 SKField SymbolKind = 8 SKConstructor SymbolKind = 9 SKEnum SymbolKind = 10 SKInterface SymbolKind = 11 SKFunction SymbolKind = 12 SKVariable SymbolKind = 13 SKConstant SymbolKind = 14 SKString SymbolKind = 15 SKNumber SymbolKind = 16 SKBoolean SymbolKind = 17 SKArray SymbolKind = 18 SKObject SymbolKind = 19 SKKey SymbolKind = 20 SKNull SymbolKind = 21 SKEnumMember SymbolKind = 22 SKStruct SymbolKind = 23 SKEvent SymbolKind = 24 SKOperator SymbolKind = 25 SKTypeParameter SymbolKind = 26 ) func (s SymbolKind) String() string { return symbolKindName[s] } var symbolKindName = map[SymbolKind]string{ SKFile: "File", SKModule: "Module", SKNamespace: "Namespace", SKPackage: "Package", SKClass: "Class", SKMethod: "Method", SKProperty: "Property", SKField: "Field", SKConstructor: "Constructor", SKEnum: "Enum", SKInterface: "Interface", SKFunction: "Function", SKVariable: "Variable", SKConstant: "Constant", SKString: "String", SKNumber: "Number", SKBoolean: "Boolean", SKArray: "Array", SKObject: "Object", SKKey: "Key", SKNull: "Null", SKEnumMember: "EnumMember", SKStruct: "Struct", SKEvent: "Event", SKOperator: "Operator", SKTypeParameter: "TypeParameter", } type SymbolInformation struct { Name string `json:"name"` Kind SymbolKind `json:"kind"` Location Location `json:"location"` ContainerName string `json:"containerName,omitempty"` } type WorkspaceSymbolParams struct { Query string `json:"query"` Limit int `json:"limit"` } type ConfigurationParams struct { Items []ConfigurationItem `json:"items"` } type ConfigurationItem struct { ScopeURI string `json:"scopeUri,omitempty"` Section string `json:"section,omitempty"` } type ConfigurationResult []interface{} type CodeActionContext struct { Diagnostics []Diagnostic `json:"diagnostics"` } type CodeActionParams struct { TextDocument TextDocumentIdentifier `json:"textDocument"` Range Range `json:"range"` Context CodeActionContext `json:"context"` } type CodeLensParams struct { TextDocument TextDocumentIdentifier `json:"textDocument"` } type CodeLens struct { Range Range `json:"range"` Command Command `json:"command,omitempty"` Data interface{} `json:"data,omitempty"` } type DocumentFormattingParams struct { TextDocument TextDocumentIdentifier `json:"textDocument"` Options FormattingOptions `json:"options"` } type FormattingOptions struct { TabSize int `json:"tabSize"` InsertSpaces bool `json:"insertSpaces"` Key string `json:"key"` } type RenameParams struct { TextDocument TextDocumentIdentifier `json:"textDocument"` Position Position `json:"position"` NewName string `json:"newName"` } type DidOpenTextDocumentParams struct { TextDocument TextDocumentItem `json:"textDocument"` } type DidChangeTextDocumentParams struct { TextDocument VersionedTextDocumentIdentifier `json:"textDocument"` ContentChanges []TextDocumentContentChangeEvent `json:"contentChanges"` } type TextDocumentContentChangeEvent struct { Range *Range `json:"range,omitEmpty"` RangeLength uint `json:"rangeLength,omitEmpty"` Text string `json:"text"` } type DidCloseTextDocumentParams struct { TextDocument TextDocumentIdentifier `json:"textDocument"` } type DidSaveTextDocumentParams struct { TextDocument TextDocumentIdentifier `json:"textDocument"` } type MessageType int const ( MTError MessageType = 1 MTWarning = 2 Info = 3 Log = 4 ) type ShowMessageParams struct { Type MessageType `json:"type"` Message string `json:"message"` } type MessageActionItem struct { Title string `json:"title"` } type ShowMessageRequestParams struct { Type MessageType `json:"type"` Message string `json:"message"` Actions []MessageActionItem `json:"actions"` } type LogMessageParams struct { Type MessageType `json:"type"` Message string `json:"message"` } type DidChangeConfigurationParams struct { Settings interface{} `json:"settings"` } type FileChangeType int const ( Created FileChangeType = 1 Changed = 2 Deleted = 3 ) type FileEvent struct { URI DocumentURI `json:"uri"` Type int `json:"type"` } type DidChangeWatchedFilesParams struct { Changes []FileEvent `json:"changes"` } type PublishDiagnosticsParams struct { URI DocumentURI `json:"uri"` Diagnostics []Diagnostic `json:"diagnostics"` } type DocumentRangeFormattingParams struct { TextDocument TextDocumentIdentifier `json:"textDocument"` Range Range `json:"range"` Options FormattingOptions `json:"options"` } type DocumentOnTypeFormattingParams struct { TextDocument TextDocumentIdentifier `json:"textDocument"` Position Position `json:"position"` Ch string `json:"ch"` Options FormattingOptions `json:"formattingOptions"` } type CancelParams struct { ID ID `json:"id"` } type SemanticHighlightingParams struct { TextDocument VersionedTextDocumentIdentifier `json:"textDocument"` Lines []SemanticHighlightingInformation `json:"lines"` } // SemanticHighlightingInformation represents a semantic highlighting // information that has to be applied on a specific line of the text // document. type SemanticHighlightingInformation struct { // Line is the zero-based line position in the text document. Line int `json:"line"` // Tokens is a base64 encoded string representing every single highlighted // characters with its start position, length and the "lookup table" index of // the semantic highlighting [TextMate scopes](https://manual.macromates.com/en/language_grammars). // If the `tokens` is empty or not defined, then no highlighted positions are // available for the line. Tokens SemanticHighlightingTokens `json:"tokens,omitempty"` } type semanticHighlightingInformation struct { Line int `json:"line"` Tokens *string `json:"tokens"` } // MarshalJSON implements json.Marshaler. func (v *SemanticHighlightingInformation) MarshalJSON() ([]byte, error) { tokens := string(v.Tokens.Serialize()) return json.Marshal(&semanticHighlightingInformation{ Line: v.Line, Tokens: &tokens, }) } // UnmarshalJSON implements json.Unmarshaler. func (v *SemanticHighlightingInformation) UnmarshalJSON(data []byte) error { var info semanticHighlightingInformation err := json.Unmarshal(data, &info) if err != nil { return err } if info.Tokens != nil { v.Tokens, err = DeserializeSemanticHighlightingTokens([]byte(*info.Tokens)) if err != nil { return err } } v.Line = info.Line return nil } type SemanticHighlightingTokens []SemanticHighlightingToken func (v SemanticHighlightingTokens) Serialize() []byte { var chunks [][]byte // Writes each token to `tokens` in the byte format specified by the LSP // proposal. Described below: // |<---- 4 bytes ---->|<-- 2 bytes -->|<--- 2 bytes -->| // | character | length | index | for _, token := range v { chunk := make([]byte, 8) binary.BigEndian.PutUint32(chunk[:4], token.Character) binary.BigEndian.PutUint16(chunk[4:6], token.Length) binary.BigEndian.PutUint16(chunk[6:], token.Scope) chunks = append(chunks, chunk) } src := make([]byte, len(chunks)*8) for i, chunk := range chunks { copy(src[i*8:i*8+8], chunk) } dst := make([]byte, base64.StdEncoding.EncodedLen(len(src))) base64.StdEncoding.Encode(dst, src) return dst } func DeserializeSemanticHighlightingTokens(src []byte) (SemanticHighlightingTokens, error) { dst := make([]byte, base64.StdEncoding.DecodedLen(len(src))) n, err := base64.StdEncoding.Decode(dst, src) if err != nil { return nil, err } var chunks [][]byte for i := 7; i < len(dst[:n]); i += 8 { chunks = append(chunks, dst[i-7:i+1]) } var tokens SemanticHighlightingTokens for _, chunk := range chunks { tokens = append(tokens, SemanticHighlightingToken{ Character: binary.BigEndian.Uint32(chunk[:4]), Length: binary.BigEndian.Uint16(chunk[4:6]), Scope: binary.BigEndian.Uint16(chunk[6:]), }) } return tokens, nil } type SemanticHighlightingToken struct { Character uint32 Length uint16 Scope uint16 } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/service_test.go000066400000000000000000000112771422502104500253620ustar00rootroot00000000000000package lsp import ( "bytes" "encoding/json" "reflect" "testing" ) func TestTextDocumentSyncOptionsOrKind_MarshalUnmarshalJSON(t *testing.T) { kindPtr := func(kind TextDocumentSyncKind) *TextDocumentSyncKind { return &kind } tests := []struct { data []byte want *TextDocumentSyncOptionsOrKind }{ { data: []byte(`2`), want: &TextDocumentSyncOptionsOrKind{ Options: &TextDocumentSyncOptions{ OpenClose: true, Change: TDSKIncremental, }, Kind: kindPtr(2), }, }, { data: []byte(`{"openClose":true,"change":1,"save":{"includeText":true}}`), want: &TextDocumentSyncOptionsOrKind{ Options: &TextDocumentSyncOptions{ OpenClose: true, Change: TDSKFull, Save: &SaveOptions{IncludeText: true}, }, }, }, } for _, test := range tests { var got TextDocumentSyncOptionsOrKind if err := json.Unmarshal(test.data, &got); err != nil { t.Error(err) continue } if !reflect.DeepEqual(&got, test.want) { t.Errorf("got %+v, want %+v", got, test.want) continue } data, err := json.Marshal(&got) if err != nil { t.Error(err) continue } if !bytes.Equal(data, test.data) { t.Errorf("got JSON %q, want %q", data, test.data) } } } func TestMarkedString_MarshalUnmarshalJSON(t *testing.T) { tests := []struct { data []byte want MarkedString }{{ data: []byte(`{"language":"go","value":"foo"}`), want: MarkedString{Language: "go", Value: "foo", isRawString: false}, }, { data: []byte(`{"language":"","value":"foo"}`), want: MarkedString{Language: "", Value: "foo", isRawString: false}, }, { data: []byte(`"foo"`), want: MarkedString{Language: "", Value: "foo", isRawString: true}, }} for _, test := range tests { var m MarkedString if err := json.Unmarshal(test.data, &m); err != nil { t.Errorf("json.Unmarshal error: %s", err) continue } if !reflect.DeepEqual(test.want, m) { t.Errorf("Unmarshaled %q, expected %+v, but got %+v", string(test.data), test.want, m) continue } marshaled, err := json.Marshal(m) if err != nil { t.Errorf("json.Marshal error: %s", err) continue } if string(marshaled) != string(test.data) { t.Errorf("Marshaled result expected %s, but got %s", string(test.data), string(marshaled)) } } } func TestHover(t *testing.T) { tests := []struct { data []byte want Hover skipUnmarshal bool skipMarshal bool }{{ data: []byte(`{"contents":[{"language":"go","value":"foo"}]}`), want: Hover{Contents: []MarkedString{{Language: "go", Value: "foo", isRawString: false}}}, }, { data: []byte(`{"contents":[]}`), want: Hover{Contents: nil}, skipUnmarshal: true, // testing we don't marshal nil }} for _, test := range tests { if !test.skipUnmarshal { var h Hover if err := json.Unmarshal(test.data, &h); err != nil { t.Errorf("json.Unmarshal error: %s", err) continue } if !reflect.DeepEqual(test.want, h) { t.Errorf("Unmarshaled %q, expected %+v, but got %+v", string(test.data), test.want, h) continue } } if !test.skipMarshal { marshaled, err := json.Marshal(&test.want) if err != nil { t.Errorf("json.Marshal error: %s", err) continue } if string(marshaled) != string(test.data) { t.Errorf("Marshaled result expected %s, but got %s", string(test.data), string(marshaled)) } } } } func TestSemanticHighlightingTokens(t *testing.T) { tests := []struct { data SemanticHighlightingTokens want string }{{ data: nil, want: `{"line":0,"tokens":""}`, }, { data: SemanticHighlightingTokens{ { Character: 1, Length: 2, Scope: 3, }, }, want: `{"line":0,"tokens":"AAAAAQACAAM="}`, }, { // Double check correctness by adapting test from: // https://github.com/gluon-lang/lsp-types/blob/647f7013625c3cd45c1d3fe53a2e3656d091c36a/src/lib.rs#L4057 data: SemanticHighlightingTokens{ { Character: 0x00000001, Length: 0x0002, Scope: 0x0003, }, { Character: 0x00112222, Length: 0x0FF0, Scope: 0x0202, }, }, want: `{"line":0,"tokens":"AAAAAQACAAMAESIiD/ACAg=="}`, }} for _, test := range tests { info := SemanticHighlightingInformation{ Tokens: test.data, } marshaled, err := json.Marshal(&info) if err != nil { t.Errorf("json.Marshal error: %s", err) continue } if string(marshaled) != test.want { t.Errorf("Marshaled result expected %s, but got %s", test.want, string(marshaled)) continue } var s SemanticHighlightingInformation if err := json.Unmarshal(marshaled, &s); err != nil { t.Errorf("json.Unmarshal error: %s", err) continue } if !reflect.DeepEqual(test.data, s.Tokens) { t.Errorf("Expected %+v, but got %+v", test.want, s) } } } golang-github-sourcegraph-go-lsp-0.0~git20200429.219e11d/structures.go000066400000000000000000000061471422502104500251060ustar00rootroot00000000000000package lsp import "fmt" type Position struct { /** * Line position in a document (zero-based). */ Line int `json:"line"` /** * Character offset on a line in a document (zero-based). */ Character int `json:"character"` } func (p Position) String() string { return fmt.Sprintf("%d:%d", p.Line, p.Character) } type Range struct { /** * The range's start position. */ Start Position `json:"start"` /** * The range's end position. */ End Position `json:"end"` } func (r Range) String() string { return fmt.Sprintf("%s-%s", r.Start, r.End) } type Location struct { URI DocumentURI `json:"uri"` Range Range `json:"range"` } type Diagnostic struct { /** * The range at which the message applies. */ Range Range `json:"range"` /** * The diagnostic's severity. Can be omitted. If omitted it is up to the * client to interpret diagnostics as error, warning, info or hint. */ Severity DiagnosticSeverity `json:"severity,omitempty"` /** * The diagnostic's code. Can be omitted. */ Code string `json:"code,omitempty"` /** * A human-readable string describing the source of this * diagnostic, e.g. 'typescript' or 'super lint'. */ Source string `json:"source,omitempty"` /** * The diagnostic's message. */ Message string `json:"message"` } type DiagnosticSeverity int const ( Error DiagnosticSeverity = 1 Warning = 2 Information = 3 Hint = 4 ) type Command struct { /** * Title of the command, like `save`. */ Title string `json:"title"` /** * The identifier of the actual command handler. */ Command string `json:"command"` /** * Arguments that the command handler should be * invoked with. */ Arguments []interface{} `json:"arguments"` } type TextEdit struct { /** * The range of the text document to be manipulated. To insert * text into a document create a range where start === end. */ Range Range `json:"range"` /** * The string to be inserted. For delete operations use an * empty string. */ NewText string `json:"newText"` } type WorkspaceEdit struct { /** * Holds changes to existing resources. */ Changes map[string][]TextEdit `json:"changes"` } type TextDocumentIdentifier struct { /** * The text document's URI. */ URI DocumentURI `json:"uri"` } type TextDocumentItem struct { /** * The text document's URI. */ URI DocumentURI `json:"uri"` /** * The text document's language identifier. */ LanguageID string `json:"languageId"` /** * The version number of this document (it will strictly increase after each * change, including undo/redo). */ Version int `json:"version"` /** * The content of the opened text document. */ Text string `json:"text"` } type VersionedTextDocumentIdentifier struct { TextDocumentIdentifier /** * The version number of this document. */ Version int `json:"version"` } type TextDocumentPositionParams struct { /** * The text document. */ TextDocument TextDocumentIdentifier `json:"textDocument"` /** * The position inside the text document. */ Position Position `json:"position"` }