language server protocol sdk implement for go

LSP(language server protocol) defines for golang

lsp types is from vscode-languageserver-node.

Project is working in progress.

Example

func main() {
	server := lsp.NewServer(&lsp.Options{CompletionProvider: &defines.CompletionOptions{
		TriggerCharacters: &[]string{"."},
	}})
	server.OnHover(func(ctx context.Context, req *defines.HoverParams) (result *defines.Hover, err error) {
		fmt.Println(req)
		return &defines.Hover{Contents: defines.MarkupContent{Kind: defines.MarkupKindPlainText, Value: "hello world"}}, nil
	})

	server.OnCompletion(func(ctx context.Context, req *defines.CompletionParams) (result *[]defines.CompletionItem, err error) {
		fmt.Println(req)
		d := defines.CompletionItemKindText
		return &[]defines.CompletionItem{defines.CompletionItem{
			Label:               "code",
			Kind:                &d,
			InsertText:          strPtr("Hello"),
		}}, nil
	})
}
Owner
Tobias Yin
A student.
Tobias Yin
Similar Resources

A TCP Server Framework with graceful shutdown, custom protocol.

xtcp A TCP Server Framework with graceful shutdown,custom protocol. Usage Define your protocol format: Before create server and client, you need defin

Dec 7, 2022

Scalable WebRTC Signaling Server with ayame-like protocol.

ayu ayu is WebRTC Signaling Server with ayame-like protocol. Scalable: ayu uses Redis to store room states, so it can be used on serverless platforms

Nov 11, 2022

Uses the Finger user information protocol to open a TCP connection that makes a request to a Finger server

Finger Client This client uses the Finger user information protocol to open a TCP connection that makes a request to a Finger server. Build and Run Ru

Oct 7, 2021

Go server for STOMP message protocol

Stomper A Go message queue implementing the STOMP protocol. Done Frame parsing TODO Server connection protocol Define interface for queueing Implement

Nov 9, 2022

Use pingser to create client and server based on ICMP Protocol to send and receive custom message content.

Use pingser to create client and server based on ICMP Protocol to send and receive custom message content.

pingser Use pingser to create client and server based on ICMP Protocol to send and receive custom message content. examples source code: ./examples Us

Nov 9, 2022

Syslogpars - Simple syslog server, working to UDP-protocol

syslogparse Simple syslog server, working to UDP-protocol. Server was tested wit

Jan 22, 2022

whatsup is the reference server implementation for the fmrl protocol

whatsup whatsup is the reference server implementation for the fmrl protocol. Currently whatsup has no web interface, but may gain one in the future.

Mar 25, 2022

A simple FTP protocol with client and server implemented in TypeScript and Golang

websocket-ftp A simple FTP protocol with client and server implemented in TypeScript and Golang. Example (Client) const buffer: Uint8Array = (new Text

Apr 14, 2022

TritonHTTP - A simple web server that implements a subset of the HTTP/1.1 protocol specification

TritonHTTP Spec Summary Here we provide a concise summary of the TritonHTTP spec. You should read the spec doc for more details and clarifications. HT

Nov 5, 2022
Comments
  • Problems using with VS Code

    Problems using with VS Code

    Hi @TobiasYin,

    First of all, thanks for the great project!

    Weirdly enough, I can't get the example working. No errors will be logged, but no feature is working. Even replacing go-lsp handlers with panic does not work. I tried with VS Code and a self-written extension (see details spoiler below).

    Do you have some working example code for client and server? No matter for which client editor. Or do you have an idea of what's missing?

    Below some code I've used for my vscode extension, if it helps you.

    I started with a blank VS Code extension and followed language-server-extension-guide. Additionally I set the TransportKind.stdio to match go-lsp's defaults.

    const serverOptions: ServerOptions = {
        command: "/path/to/compiled/go-lsp-master/example/main",
        args: [],
        transport: TransportKind.stdio, // also tried every other option
    };
    const clientOptions: LanguageClientOptions = {
        documentSelector: [
          { scheme: "file", language: "example" },
          { scheme: "file", pattern: "*.example" },
          { scheme: "file", language: "go" }, // to ensure there is no bug in the contributed language definition
          { scheme: "file", pattern: "*.go" },
        ]
       // also tried outputChannel and traceOutputChannel
    }
    client = new LanguageClient(
        "example",
        "Example Language Server",
        serverOptions,
        clientOptions
      );
    
    client.onReady().then(() => {
        console.log("Example client ready"); // will NOT be logged
    });
    
    client.start();
    
  • fix: missing server.Run() in README.md

    fix: missing server.Run() in README.md

    while trying your library I noticed the missing server.Run().

    @TobiasYin also: I noticed you didn't pick an open source license, yet. Wether or not I can use this project in production depends on the license you choose.

  • MethodNotFound Error

    MethodNotFound Error

    I am working on setting up a new Language Server for VS Code and am having some troubles with some incoming requests. It may be specific to workspace/* commands. When they are sent, a MethodNotFound response is sent.

    The logs look like this:

    use stdio mode.
    Request: [0] [initialize], content: [{"processId":485172,"clientInfo":{"name":"Visual Studio Code","version":"1.72.2"},"locale":"en-us","rootPath":"path_here","rootUri":"path_here","capabilities":{"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"],"failureHandling":"textOnlyTransactional","normalizesLineEndings":true,"changeAnnotationSupport":{"groupsOnLabel":true}},"configuration":true,"didChangeWatchedFiles":{"dynamicRegistration":true,"relativePatternSupport":true},"symbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[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]},"tagSupport":{"valueSet":[1]},"resolveSupport":{"properties":["location.range"]}},"codeLens":{"refreshSupport":true},"executeCommand":{"dynamicRegistration":true},"didChangeConfiguration":{"dynamicRegistration":true},"workspaceFolders":true,"semanticTokens":{"refreshSupport":true},"fileOperations":{"dynamicRegistration":true,"didCreate":true,"didRename":true,"didDelete":true,"willCreate":true,"willRename":true,"willDelete":true},"inlineValue":{"refreshSupport":true},"inlayHint":{"refreshSupport":true},"diagnostics":{"refreshSupport":true}},"textDocument":{"publishDiagnostics":{"relatedInformation":true,"versionSupport":false,"tagSupport":{"valueSet":[1,2]},"codeDescriptionSupport":true,"dataSupport":true},"synchronization":{"dynamicRegistration":true,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":true,"contextSupport":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":true,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":true,"preselectSupport":true,"tagSupport":{"valueSet":[1]},"insertReplaceSupport":true,"resolveSupport":{"properties":["documentation","detail","additionalTextEdits"]},"insertTextModeSupport":{"valueSet":[1,2]},"labelDetailsSupport":true},"insertTextMode":2,"completionItemKind":{"valueSet":[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]},"completionList":{"itemDefaults":["commitCharacters","editRange","insertTextFormat","insertTextMode"]}},"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"signatureHelp":{"dynamicRegistration":true,"signatureInformation":{"documentationFormat":["markdown","plaintext"],"parameterInformation":{"labelOffsetSupport":true},"activeParameterSupport":true},"contextSupport":true},"definition":{"dynamicRegistration":true,"linkSupport":true},"references":{"dynamicRegistration":true},"documentHighlight":{"dynamicRegistration":true},"documentSymbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[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]},"hierarchicalDocumentSymbolSupport":true,"tagSupport":{"valueSet":[1]},"labelSupport":true},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"disabledSupport":true,"dataSupport":true,"resolveSupport":{"properties":["edit"]},"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"honorsChangeAnnotations":false},"codeLens":{"dynamicRegistration":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"onTypeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true,"prepareSupportDefaultBehavior":1,"honorsChangeAnnotations":true},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"typeDefinition":{"dynamicRegistration":true,"linkSupport":true},"implementation":{"dynamicRegistration":true,"linkSupport":true},"colorProvider":{"dynamicRegistration":true},"foldingRange":{"dynamicRegistration":true,"rangeLimit":5000,"lineFoldingOnly":true,"foldingRangeKind":{"valueSet":["comment","imports","region"]},"foldingRange":{"collapsedText":false}},"declaration":{"dynamicRegistration":true,"linkSupport":true},"selectionRange":{"dynamicRegistration":true},"callHierarchy":{"dynamicRegistration":true},"semanticTokens":{"dynamicRegistration":true,"tokenTypes":["namespace","type","class","enum","interface","struct","typeParameter","parameter","variable","property","enumMember","event","function","method","macro","keyword","modifier","comment","string","number","regexp","operator","decorator"],"tokenModifiers":["declaration","definition","readonly","static","deprecated","abstract","async","modification","documentation","defaultLibrary"],"formats":["relative"],"requests":{"range":true,"full":{"delta":true}},"multilineTokenSupport":false,"overlappingTokenSupport":false,"serverCancelSupport":true,"augmentsSyntaxTokens":true},"linkedEditingRange":{"dynamicRegistration":true},"typeHierarchy":{"dynamicRegistration":true},"inlineValue":{"dynamicRegistration":true},"inlayHint":{"dynamicRegistration":true,"resolveSupport":{"properties":["tooltip","textEdits","label.tooltip","label.location","label.command"]}},"diagnostic":{"dynamicRegistration":true,"relatedDocumentSupport":false}},"window":{"showMessage":{"messageActionItem":{"additionalPropertiesSupport":true}},"showDocument":{"support":true},"workDoneProgress":true},"general":{"staleRequestSupport":{"cancel":true,"retryOnContentModified":["textDocument/semanticTokens/full","textDocument/semanticTokens/range","textDocument/semanticTokens/full/delta"]},"regularExpressions":{"engine":"ECMAScript","version":"ES2020"},"markdown":{"parser":"marked","version":"1.1.0"},"positionEncodings":["utf-16"]},"notebookDocument":{"synchronization":{"dynamicRegistration":true,"executionSummarySupport":true}}},"trace":"off","workspaceFolders":[{"uri":"path_here","name":"legv8_examples"}]}]
    Response: [0] res: [{"jsonrpc":"","id":0,"result":{"capabilities":{"hoverProvider":true}},"error":null}]
    Request: [<nil>] [initialized], content: [{}]
    Request: [<nil>] [workspace/didChangeConfiguration], content: [{"settings":{}}]
    Response: [<nil>] res: [{"jsonrpc":"","id":null,"result":null,"error":{"code":-32601,"message":"MethodNotFound","data":null}}]
    Request: [<nil>] [workspace/didChangeWatchedFiles], content: [{"changes":[{"uri":"path_here","type":2}]}]
    Response: [<nil>] res: [{"jsonrpc":"","id":null,"result":null,"error":{"code":-32601,"message":"MethodNotFound","data":null}}]
    

    And the simplified logic of what I have running is this:

    func main() {
    
    	server := lsp.NewServer(&lsp.Options{CompletionProvider: &defines.CompletionOptions{
    		TriggerCharacters: &[]string{"."},
    	}})
    
    	server.OnHover(func(ctx context.Context, req *defines.HoverParams) (result *defines.Hover, err error) {
    		logs.Println("hover: ", req)
    		file, err := ReadFile(req.TextDocument.Uri)
    		if err != nil {
    			logs.Println("hover: failed to read req.TextDocument.Uri" + err.Error())
    		}
    
    		w := getWord(file[req.Position.Line], int(req.Position.Character))
    		token := definitions.Tokens[w]
    
    		if token.Name == "" {
    			return &defines.Hover{Contents: defines.MarkupContent{Kind: defines.MarkupKindMarkdown, Value: "#### Unknown Token"}}, nil
    		}
    
    		return &defines.Hover{Contents: defines.MarkupContent{Kind: defines.MarkupKindMarkdown, Value: "### " + token.Name + "\n" + token.Description}}, nil
    	})
    
    	server.OnDidChangeWatchedFiles(func(ctx context.Context, req *defines.DidChangeWatchedFilesParams) (err error) {
    		logs.Println("test")
    		return nil
    	})
    
    	server.OnInitialized(func(ctx context.Context, req *defines.InitializeParams) (err error) {
    		return nil
    	})
    
    	server.OnDidChangeConfiguration(func(ctx context.Context, req *defines.DidChangeConfigurationParams) (err error) {
    		logs.Println("invoked OnDidChangeConfiguration")
    		return nil
    	})
    
    	server.OnInitialize(func(ctx context.Context, req *defines.InitializeParams) (result *defines.InitializeResult, err *defines.InitializeError) {
    		logs.Println("initialized")
    		s := &defines.InitializeResult{}
    		s.Capabilities.HoverProvider = true
    		s.Capabilities.WorkspaceSymbolProvider = true
    		s.Capabilities.DocumentFormattingProvider = true
    		return s, nil
    	})
    
    	server.Run()
    }
    

    In theory, shouldn't the server.OnDidChangeWatchedFiles be called when the workspace/didChangeWatchedFiles request comes in?

Related tags
Txt-lsp - A toy project with Language Server Protocol (LSP)

txt-lsp txt-lsp is a toy project where I play around with Language Server Protoc

Jan 22, 2022
wire protocol for multiplexing connections or streams into a single connection, based on a subset of the SSH Connection Protocol

qmux qmux is a wire protocol for multiplexing connections or streams into a single connection. It is based on the SSH Connection Protocol, which is th

Dec 26, 2022
A simple tool to convert socket5 proxy protocol to http proxy protocol

Socket5 to HTTP 这是一个超简单的 Socket5 代理转换成 HTTP 代理的小工具。 如何安装? Golang 用户 # Required Go 1.17+ go install github.com/mritd/s2h@master Docker 用户 docker pull m

Jan 2, 2023
Diameter stack and Base Protocol (RFC 6733) for the Go programming language

Diameter Base Protocol Package go-diameter is an implementation of the Diameter Base Protocol RFC 6733 and a stack for the Go programming language. St

Dec 28, 2022
SMPP 3.4 Protocol for the Go programming language

SMPP 3.4 This is an implementation of SMPP 3.4 for Go, based on the original smpp34 from Kevin Patel. The API has been refactored to idiomatic Go code

Dec 13, 2022
Implementation of Pinocchio Protocol in Go language

pinocchio-protocol-zksnarks Implementation of Pinocchio Protocol in Go language 1 零知识证明和zksnarks 1.1 为什么需要可证明的计算? 随着技术的发展,计算能力表现出不对称的特性,例如云计算等拥有大量的算力,

Nov 3, 2021
Layer2 version of wireguard with Floyd Warshall implement in go.

Etherguard 中文版README A Full Mesh Layer2 VPN based on wireguard-go OSPF can find best route based on it's cost. But sometimes the lentancy are differen

Dec 29, 2022
An experimental package that rely on go generics to implement collection functions utilities

go-underscore go-underscore is a utility-belt library for Golang that provides s

Mar 20, 2022
Let's implement some basic ZeroMQ publisher and subscriber in Golang. Utilize Envoy as a proxy.
Let's implement some basic ZeroMQ publisher and subscriber in Golang. Utilize Envoy as a proxy.

Envy proxy with ZeroMQ Solution tested on DigitalOcean Droplet. In case of re-creation VM follow this article. Introduction Let's implement some basic

Jan 25, 2022