Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features status #2

Closed
mickael-menu opened this issue Mar 27, 2021 · 7 comments
Closed

Features status #2

mickael-menu opened this issue Mar 27, 2021 · 7 comments

Comments

@mickael-menu
Copy link
Contributor

Albeit in early stage, your project is looking very promising!

It would be helpful to have a list of supported features to know if glsp could be a good fit for a given project. I'm trying to figure out if I should go with glsp or https://github.com/sourcegraph/go-lsp.

I would be willing to contribute as well if something I need is missing.

@tliron
Copy link
Owner

tliron commented Mar 27, 2021

Thank you! I think the README mentions the supported features.

The main difference between this and go-lsp is also mentioned in the README: much more comprehensive coverage. Also, the code is documented with links to every struct and message in the LSP specification, so you can double-check as well as get instruction on how to use each message. What else do you think should be listed?

I started this project because go-lsp was insufficient.

@mickael-menu
Copy link
Contributor Author

Thank you! I think the README mentions the supported features.

Ha I assumed it was more a goal than the actual state of the project, because of the disclaimer. Then that sounds great!

This is an early release. Some features are not yet fully implemented.

Also, the code is documented with links to every struct and message in the LSP specification, so you can double-check as well as get instruction on how to use each message. What else do you think should be listed?

The code is well documented and clear. Maybe a minimal implementation example could help to get started. I played a bit with glsp but didn't manage to make it work with coc.nvim yet.

First, I got the following crash: panic: logging not configured [recovered], which I solved by adding:

_ "github.com/tliron/kutil/logging/simple"

But it is not very obvious how to actually get the log messages.

At the moment my test LSP server seems to be stuck in the "starting" phase of coc.nvim. I couldn't figure out how to make it run despite checking your Puccini LS. Do you have any idea what could be missing?

package cmd

import (
	"fmt"
	"log"

	"github.com/tliron/glsp"
	protocol "github.com/tliron/glsp/protocol_3_16"
	"github.com/tliron/glsp/server"
	_ "github.com/tliron/kutil/logging/simple"
)

// LSP starts a server implementing the Language Server Protocol.
type LSP struct{}

var handler = protocol.Handler{}
var logger *log.Logger

func (cmd *LSP) Run() error {
	handler.Initialize = initialize
	handler.Initialized = initialized
	handler.Shutdown = shutdown
	handler.LogTrace = logTrace
	handler.SetTrace = setTrace
	handler.TextDocumentCompletion = textDocumentCompletion

	debug := true
	server := server.NewServer(&handler, "zk-lsp", debug)
	fmt.Println("STARTING")
	return server.RunTCP(":4230")
}

// initialize implements protocol.InitializeFunc
// Returns: InitializeResult | InitializeError
func initialize(context *glsp.Context, params *protocol.InitializeParams) (interface{}, error) {
	log.Println("INITIALIZE")

	// clientCapabilities = &params.Capabilities
	if params.Trace != nil {
		protocol.SetTraceValue(*params.Trace)
	}

	resolveProvider := true
	serverCapabilities := handler.CreateServerCapabilities()
	serverCapabilities.TextDocumentSync = protocol.TextDocumentSyncKindIncremental
	serverCapabilities.CompletionProvider = &protocol.CompletionOptions{
		ResolveProvider:   &resolveProvider,
		TriggerCharacters: []string{"#"},
	}

	version := "1.0"
	return &protocol.InitializeResult{
		Capabilities: serverCapabilities,
		ServerInfo: &protocol.InitializeResultServerInfo{
			Name:    "zk-lsp",
			Version: &version,
		},
	}, nil
}

// protocol.TextDocumentCompletionFunc signature
// Returns: []CompletionItem | CompletionList | nil
func textDocumentCompletion(context *glsp.Context, params *protocol.CompletionParams) (interface{}, error) {
	var completionItems []protocol.CompletionItem
	completionItems = append(completionItems, protocol.CompletionItem{
		Label: "server",
	})
	log.Println("COMPLETION")
	return completionItems, nil
}

// protocol.InitializedFunc signature
func initialized(context *glsp.Context, params *protocol.InitializedParams) error {
	log.Println("INITIALIZED")
	return nil
}

// protocol.ShutdownFunc signature
func shutdown(context *glsp.Context) error {
	protocol.SetTraceValue(protocol.TraceValueOff)
	return nil
}

// protocol.LogTraceFunc signature
func logTrace(context *glsp.Context, params *protocol.LogTraceParams) error {
	return nil
}

// protocol.SetTraceFunc signature
func setTrace(context *glsp.Context, params *protocol.SetTraceParams) error {
	protocol.SetTraceValue(params.Value)
	return nil
}

@tliron
Copy link
Owner

tliron commented Mar 27, 2021

Some of the pain points you are experiencing are why I put a "early release" warning. The problem is that indeed I did not do testing in many environments, for example no testing with coc.vim. Also I'm not sure how correct my TCP code is. Any help in debugging this would be very appreciated! I will assist in whatever way I can.

Logging can help a lot, of course. :) To enable logging you need to call logging.Configure with the verbosity (max is 2). See this example.

@mickael-menu
Copy link
Contributor Author

mickael-menu commented Mar 27, 2021

Thanks, that did the trick for the logging 👍 There's some progress!

I figured that using stdio might be simpler than TCP, however I get the following error from Vim:

Screenshot 2021-03-27 at 21 08 40

2021-03-27T21:08:28.109 INFO (pid:30131) [services] - registered service "languageserver.zk"
2021-03-27T21:08:28.113 INFO (pid:30131) [services] - zk state change: stopped => starting
2021-03-27T21:08:28.117 INFO (pid:30131) [plugin] - coc.nvim 0.0.79-6fe357fc97 initialized with node: v15.1.0 after 54ms
2021-03-27T21:08:28.123 INFO (pid:30131) [language-client-index] - Language server "languageserver.zk" started with 30133
2021-03-27T21:08:28.501 ERROR (pid:30131) [server] - uncaughtException Error: Header must provide a Content-Length property.
    at StreamMessageReader.onData (/Users/mickael/.vim/plugged/coc.nvim/build/index.js:18138:27)
    at Socket.<anonymous> (/Users/mickael/.vim/plugged/coc.nvim/build/index.js:18123:18)
    at Socket.emit (node:events:327:20)
    at addChunk (node:internal/streams/readable:304:12)
    at readableAddChunk (node:internal/streams/readable:279:9)
    at Socket.Readable.push (node:internal/streams/readable:218:10)
    at Pipe.onStreamRead (node:internal/stream_base_commons:192:23)

And here are the logs from glsp, the connection seems to have been successful:

2021/03/27 21:08:28.497  INFO [zk-lsp.server] reading from stdin, writing to stdout
2021/03/27 21:08:28.499 DEBUG [zk-lsp.rpc] jsonrpc2: --> request #0: initialize: {"processId":30131,"rootPath":"/Users/mickael/Dropbox/Notes","rootUri":"file:///Users/mickael/Dropbox/Notes","capabilities":{"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"],"failureHandling":"textOnlyTransactional"},"didChangeConfiguration":{"dynamicRegistration":true},"didChangeWatchedFiles":{"dynamicRegistration":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]}},"executeCommand":{"dynamicRegistration":true},"configuration":true,"workspaceFolders":true},"textDocument":{"publishDiagnostics":{"relatedInformation":true,"versionSupport":false,"tagSupport":{"valueSet":[1,2]}},"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},"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]}},"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"signatureHelp":{"dynamicRegistration":true,"signatureInformation":{"documentationFormat":["markdown","plaintext"],"parameterInformation":{"labelOffsetSupport":true}}},"definition":{"dynamicRegistration":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]}},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"codeLens":{"dynamicRegistration":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"onTypeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"typeDefinition":{"dynamicRegistration":true},"implementation":{"dynamicRegistration":true},"declaration":{"dynamicRegistration":true},"colorProvider":{"dynamicRegistration":true},"foldingRange":{"dynamicRegistration":true,"rangeLimit":5000,"lineFoldingOnly":true},"selectionRange":{"dynamicRegistration":true}},"window":{"workDoneProgress":true}},"initializationOptions":{},"trace":"verbose","workspaceFolders":[{"uri":"file:///Users/mickael/Dropbox/Notes","name":"Notes"}],"clientInfo":{"name":"coc.nvim","version":"0.0.79"},"workDoneToken":"9a61d353-d957-4adb-9cec-fd1ddf994a0b"}
2021/03/27 21:08:28.499 DEBUG [zk-lsp.rpc] jsonrpc2: <-- result #0: initialize: {"capabilities":{"textDocumentSync":2,"completionProvider":{"triggerCharacters":["#"],"resolveProvider":true}},"serverInfo":{"name":"zk-lsp","version":"1.0"}}

@mickael-menu
Copy link
Contributor Author

mickael-menu commented Mar 27, 2021

It might be that coc.nvim is more demanding, because I managed to run my LS with Sublime Text:

:: --> zk initialize(1): {'initializationOptions': {}, 'rootPath': None, 'clientInfo': {'version': '0.14.3', 'name': 'Sublime Text LSP'}, 'capabilities': {'workspace': {'workspaceEdit': {'documentChanges': True, 'failureHandling': 'abort'}, 'didChangeConfiguration': {'dynamicRegistration': True}, 'applyEdit': True, 'executeCommand': {}, 'configuration': 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]}}, 'workspaceFolders': True}, 'window': {'showMessage': {'messageActionItem': {'additionalPropertiesSupport': True}}, 'workDoneProgress': True}, 'experimental': {}, 'textDocument': {'hover': {'contentFormat': ['markdown', 'plaintext'], 'dynamicRegistration': True}, 'declaration': {'dynamicRegistration': True, 'linkSupport': True}, 'completion': {'completionItem': {'snippetSupport': True}, 'dynamicRegistration': True, '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]}}, 'rangeFormatting': {'dynamicRegistration': True}, 'references': {'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}, 'definition': {'dynamicRegistration': True, 'linkSupport': True}, 'synchronization': {'didSave': True, 'willSave': True, 'dynamicRegistration': True, 'willSaveWaitUntil': True}, 'documentHighlight': {'dynamicRegistration': True}, 'colorProvider': {'dynamicRegistration': True}, 'signatureHelp': {'signatureInformation': {'documentationFormat': ['markdown', 'plaintext'], 'parameterInformation': {'labelOffsetSupport': True}}, 'dynamicRegistration': True}, 'publishDiagnostics': {'relatedInformation': True}, 'rename': {'dynamicRegistration': True}, 'typeDefinition': {'dynamicRegistration': True, 'linkSupport': True}, 'implementation': {'dynamicRegistration': True, 'linkSupport': True}, 'formatting': {'dynamicRegistration': True}, 'codeAction': {'codeActionLiteralSupport': {'codeActionKind': {'valueSet': []}}, 'dynamicRegistration': True}}}, 'rootUri': None, 'processId': 31466, 'workspaceFolders': None}
zk: 2021/03/27 21:45:08 INITIALIZE
:: <<< zk 1: {'capabilities': {'completionProvider': {'triggerCharacters': ['#'], 'resolveProvider': True}, 'textDocumentSync': 2}, 'serverInfo': {'version': '1.0', 'name': 'zk-lsp'}}
zk: 2021/03/27 21:45:08 INITIALIZED
::  -> zk initialized: {}
2021/03/27 21:45:08.263  INFO [zk-lsp.server] reading from stdin, writing to stdout
2021/03/27 21:45:08.264 DEBUG [zk-lsp.rpc] jsonrpc2: --> request #1: initialize: {"initializationOptions":{},"rootPath":null,"clientInfo":{"version":"0.14.3","name":"Sublime Text LSP"},"capabilities":{"workspace":{"workspaceEdit":{"documentChanges":true,"failureHandling":"abort"},"didChangeConfiguration":{"dynamicRegistration":true},"applyEdit":true,"executeCommand":{},"configuration":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]}},"workspaceFolders":true},"window":{"showMessage":{"messageActionItem":{"additionalPropertiesSupport":true}},"workDoneProgress":true},"experimental":{},"textDocument":{"hover":{"contentFormat":["markdown","plaintext"],"dynamicRegistration":true},"declaration":{"dynamicRegistration":true,"linkSupport":true},"completion":{"completionItem":{"snippetSupport":true},"dynamicRegistration":true,"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]}},"rangeFormatting":{"dynamicRegistration":true},"references":{"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},"definition":{"dynamicRegistration":true,"linkSupport":true},"synchronization":{"didSave":true,"willSave":true,"dynamicRegistration":true,"willSaveWaitUntil":true},"documentHighlight":{"dynamicRegistration":true},"colorProvider":{"dynamicRegistration":true},"signatureHelp":{"signatureInformation":{"documentationFormat":["markdown","plaintext"],"parameterInformation":{"labelOffsetSupport":true}},"dynamicRegistration":true},"publishDiagnostics":{"relatedInformation":true},"rename":{"dynamicRegistration":true},"typeDefinition":{"dynamicRegistration":true,"linkSupport":true},"implementation":{"dynamicRegistration":true,"linkSupport":true},"formatting":{"dynamicRegistration":true},"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":[]}},"dynamicRegistration":true}}},"rootUri":null,"processId":31466,"workspaceFolders":null}
2021/03/27 21:45:08.265 DEBUG [zk-lsp.rpc] jsonrpc2: <-- result #1: initialize: {"capabilities":{"textDocumentSync":2,"completionProvider":{"triggerCharacters":["#"],"resolveProvider":true}},"serverInfo":{"name":"zk-lsp","version":"1.0"}}
2021/03/27 21:45:08.265 DEBUG [zk-lsp.rpc] jsonrpc2: --> notif: initialized: {}

Is there a way to debug the actual JSON-RPC messages sent with glsp, to see if the Content-Length header is really missing?

I was able to run a similar LS made with go-lsp, so I think my coc.nvim setup is fine.

@mickael-menu
Copy link
Contributor Author

So, it was really dumb...

I figured out a way to print the output from glsp, and it seemed correct:

2021/03/28 11:29:48.590  INFO [zk-lsp.server] WRITING: "Content-Length: 192\r\n\r\n{\"id\":0,\"result\":{\"capabilities\":{\"textDocumentSync\":2,\"completionProvider\":{\"triggerCharacters\":[\"#\"],\"resolveProvider\":true}},\"serverInfo\":{\"name\":\"zk-lsp\",\"version\":\"1.0\"}},\"jsonrpc\":\"2.0\"}"

The issue was that I added some stdout log in my cli app, which of course was messing up the protocol communication when using the stdio mode. After removing it, it's working properly and I get some basic completion 👍

Closing this issue, thanks and keep up the good work!

@tliron
Copy link
Owner

tliron commented Mar 29, 2021

Ha, that might have happened to me once or twice, too...

By the way, one quirk of GLSP is that it absolutely requires the Content-Length header. It is not optional.

@asmaloney asmaloney mentioned this issue Aug 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants