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

x/tools/gopls: errors when using with monaco-languageclient #43420

Closed
palkerecsenyi opened this issue Dec 29, 2020 · 2 comments
Closed

x/tools/gopls: errors when using with monaco-languageclient #43420

palkerecsenyi opened this issue Dec 29, 2020 · 2 comments
Labels
FrozenDueToAge gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@palkerecsenyi
Copy link

palkerecsenyi commented Dec 29, 2020

What version of Go are you using (go version)?

$ go version
go version go1.15.6 linux/amd64

Does this issue reproduce with the latest release?

Yes, this is the latest release.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/root/Go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/root/Go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build619587994=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I'm trying to use the latest version of gopls (0.6.1) to provide a language server for a browser-based instance of the Monaco editor, using vscode-ws-jsonrpc and monaco-languageclient with a React app. I've got this working with pyls and bash-language-server perfectly fine, but when I try it with gopls I get some errors.

Logs

View browser logs
A request has failed. See the output for more information.

lsp.palcode.dev: [Error - 18:21:01] Starting client failed

Couldn't start client lsp.palcode.dev

monaco-commands.ts:12 Uncaught (in promise) TypeError: Cannot read property 'addCommand' of undefined
at MonacoCommands.registerCommand (monaco-commands.ts:12)
at Object.registerCommand (vscode-api.ts:788)
at ExecuteCommandFeature.register (client.js:1650)
at ExecuteCommandFeature.initialize (client.js:1630)
at MonacoLanguageClient.initializeFeatures (client.js:2462)
at client.js:2147

These server logs were generated with the rpc.trace option turned on.

View server logs
0|lsp  | JSON Server: [Trace - 18:23:35.683 PM] Sending request 'initialize - (0)'.
0|lsp  | Params: {"clientInfo":{"name":"vscode"},"rootPath":null,"rootUri":null,"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]}},"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,"tagSupport":{"valueSet":[1]}},"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}},"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},"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,"linkSupport":true},"implementation":{"dynamicRegistration":true,"linkSupport":true},"colorProvider":{"dynamicRegistration":true},"foldingRange":{"dynamicRegistration":true,"rangeLimit":5000,"lineFoldingOnly":true},"declaration":{"dynamicRegistration":true,"linkSupport":true}}},"trace":"off","workspaceFolders":null,"processId":1279748}
0|lsp  | 
0|lsp  | 
0|lsp  | JSON Server: [Trace - 18:23:35.693 PM] Received response 'initialize - (0)' in 9ms.
0|lsp  | Result: {"capabilities":{"textDocumentSync":{"openClose":true,"change":2,"save":{}},"completionProvider":{"triggerCharacters":["."]},"hoverProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":true,"referencesProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"codeActionProvider":{"codeActionKinds":["quickfix","refactor.extract","refactor.rewrite","source.fixAll","source.organizeImports"]},"codeLensProvider":{},"documentLinkProvider":{},"workspaceSymbolProvider":true,"documentFormattingProvider":true,"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"renameProvider":{"prepareProvider":true},"foldingRangeProvider":true,"executeCommandProvider":{"commands":["gopls.generate","gopls.fill_struct","gopls.regenerate_cgo","gopls.test","gopls.tidy","gopls.update_go_sum","gopls.undeclared_name","gopls.go_get_package","gopls.add_dependency","gopls.upgrade_dependency","gopls.remove_dependency","gopls.vendor","gopls.extract_variable","gopls.extract_function","gopls.gc_details","gopls.generate_gopls_mod"]},"callHierarchyProvider":true,"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":"workspace/didChangeWorkspaceFolders"}}},"serverInfo":{"name":"gopls","version":"{\"path\":\"golang.org/x/tools/gopls\",\"version\":\"v0.6.1\",\"sum\":\"h1:vD171EDBkyUVyp9B45IYXklV/VEfbHgX0FKw0Q0dO30=\",\"deps\":[{\"path\":\"github.com/BurntSushi/toml\",\"version\":\"v0.3.1\",\"sum\":\"h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\"},{\"path\":\"github.com/google/go-cmp\",\"version\":\"v0.5.1\",\"sum\":\"h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=\"},{\"path\":\"github.com/sergi/go-diff\",\"version\":\"v1.1.0\",\"sum\":\"h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=\"},{\"path\":\"golang.org/x/mod\",\"version\":\"v0.3.0\",\"sum\":\"h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=\"},{\"path\":\"golang.org/x/sync\",\"version\":\"v0.0.0-20201020160332-67f06af15bc9\",\"sum\":\"h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=\"},{\"path\":\"golang.org/x/tools\",\"version\":\"v0.0.0-20201217163546-c88dec5c6b05\",\"sum\":\"h1:4hzTNH658xirWc4MvAx9HK2/2hY6z42i1+lRK8OzeJE=\"},{\"path\":\"golang.org/x/xerrors\",\"version\":\"v0.0.0-20200804184101-5ec99f83aff1\",\"sum\":\"h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=\"},{\"path\":\"honnef.co/go/tools\",\"version\":\"v0.0.1-2020.1.6\",\"sum\":\"h1:W18jzjh8mfPez+AwGLxmOImucz/IFjpNlrKVnaj2YVc=\"},{\"path\":\"mvdan.cc/gofumpt\",\"version\":\"v0.0.0-20200927160801-5bfeb2e70dd6\",\"sum\":\"h1:z+/YqapuV7VZPvBb3GYmuEJbA88M3PFUxaHilHYVCpQ=\"},{\"path\":\"mvdan.cc/xurls/v2\",\"version\":\"v2.2.0\",\"sum\":\"h1:NSZPykBXJFCetGZykLAxaL6SIpvbVy/UFEniIfHAa8A=\"}]}"}}
0|lsp  | 
0|lsp  | 
0|lsp  | JSON Server: [Trace - 18:23:35.741 PM] Sending notification 'initialized'.
0|lsp  | Params: {}
0|lsp  | 
0|lsp  | 
0|lsp  | JSON Server: [Trace - 18:23:35.745 PM] Received request 'client/registerCapability - (1)'.
0|lsp  | Params: {"registrations":[{"id":"workspace/didChangeConfiguration","method":"workspace/didChangeConfiguration"},{"id":"workspace/didChangeWorkspaceFolders","method":"workspace/didChangeWorkspaceFolders"}]}
0|lsp  | 
0|lsp  | 
0|lsp  | JSON Server: [Trace - 18:23:35.746 PM] Sending request 'shutdown - (1)'.
0|lsp  | Params: 
0|lsp  | 
0|lsp  | 
0|lsp  | JSON Server: [Trace - 18:23:35.815 PM] Sending response 'client/registerCapability - (1)' in 70ms.
0|lsp  | Result: 
0|lsp  | 
0|lsp  | 
0|lsp  | JSON Server: [Trace - 18:23:35.818 PM] Received response 'shutdown - (1)' in 71ms.
0|lsp  | Result: null
0|lsp  | 
0|lsp  | 
0|lsp  | [Trace - 18:23:35.818 PM] Received notification 'window/logMessage'.
0|lsp  | Params: {"type":3,"message":"2020/12/29 18:23:35 Shutdown session\n\tshutdown_session=1\n"}
0|lsp  | 
0|lsp  | 
0|lsp  | JSON Server: [Trace - 18:23:36.213 PM] Sending notification 'exit'.
0|lsp  | Params: 

Here's the frontend code I'm using:

import {
    CloseAction,
    createConnection,
    ErrorAction,
    MonacoLanguageClient,
    MonacoServices,
} from 'monaco-languageclient';
import { listen, MessageConnection } from 'vscode-ws-jsonrpc';
import { editor } from 'monaco-editor';
import { TaskLanguage } from '../types';

function createLanguageClient(connection: MessageConnection) {
    return new MonacoLanguageClient({
        name: 'lsp.palcode.dev',
        clientOptions: {
            documentSelector: ['go'],
            errorHandler: {
                error: () => ErrorAction.Continue,
                closed: () => CloseAction.DoNotRestart,
            }
        },
        connectionProvider: {
            get(errorHandler, closeHandler) {
                return Promise.resolve(createConnection(
                    connection,
                    errorHandler,
                    closeHandler,
                ));
            }
        }
    })
}

    try {
        MonacoServices.get();
    } catch (e) {
        MonacoServices.install(editor);
    }

    const webSocket = new WebSocket(lspURL + '/' + language);
    webSocket.onerror = () => {};
    let pingInterval: number;
    listen({
        webSocket,
        onConnection: (connection) => {
            const client = createLanguageClient(connection);
            const disposable = client.start();
            connection.onClose(() => disposable.dispose());
            connection.onError(() => {});

            pingInterval = window.setInterval(() => {
                webSocket.send('ping');
            }, 20000);
        },
    });

And here's my backend code:

const http = require("http");
const rpc = require('vscode-ws-jsonrpc');
const server = require('vscode-ws-jsonrpc/lib/server');
const lsp = require('vscode-languageserver');
const ws = require("ws");
const languages = require("./languages");

function launch(socket) {
    const reader = new rpc.WebSocketMessageReader(socket);
    const writer = new rpc.WebSocketMessageWriter(socket);
    const socketConnection = server.createConnection(reader, writer, () => socket.dispose());
    const serverConnection = server.createServerProcess('JSON', '/root/Go/bin/gopls', ['-rpc.trace', 'serve']);
    server.forward(socketConnection, serverConnection, message => {
        if (rpc.isRequestMessage(message)) {
            if (message.method === lsp.InitializeRequest.type.method) {
                const initializeParams = message.params;
                initializeParams.processId = process.pid;
            }
        }
        return message;
    });
}

const server = http.createServer().listen(8080);
    const socket = new ws.Server({
        server,
        perMessageDeflate: false,
    });

    socket.on('connection', (client) => {
        const iWebSocket = {
            send: content => client.send(content),
            onMessage: cb => client.onmessage = event => {
                if (event.data !== 'ping') {
                    cb(event.data);
                }
            },
            onError: cb => client.onerror = event => {
                if ('message' in event) {
                    cb(event.message)
                }
            },
            onClose: cb => client.onclose = event => cb(event.code, event.reason),
            dispose: () => client.close(),
        };

        launch(iWebSocket);
    });

I realise this error may have very little to do with gopls and could be more related to the other libraries I'm using, but I'm not too sure what's causing it. Thanks for the help, and please let me know if you need any more logs/info.

What did you expect to see?

I'm expecting to see all features of Gopls functioning in my frontend Monaco editor.

What did you see instead?

The above JS errors are thrown on the frontend with (seemingly) no error message on the backend. The Monaco editor has no LSP functionality.

@gopherbot gopherbot added Tools This label describes issues relating to any tools in the x/tools repository. gopls Issues related to the Go language server, gopls. labels Dec 29, 2020
@gopherbot gopherbot added this to the Unreleased milestone Dec 29, 2020
@stamblerre
Copy link
Contributor

stamblerre commented Dec 29, 2020

It looks like the client has a problem registering the commands the gopls sends in initialization request--do the other servers send commands in the list of capabilities? It looks like initialization fails, and then the client sends gopls a shutdown request. Is it possible to add more error logging?

As you said, I don't think this is related to gopls itself.

@stamblerre stamblerre changed the title x/tools/gopls: Unexplained errors when using with monaco-languageclient x/tools/gopls: errors when using with monaco-languageclient Dec 29, 2020
@stamblerre stamblerre added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Dec 29, 2020
@palkerecsenyi
Copy link
Author

Thanks for the reply! I've established that it's almost certainly not an issue with gopls but rather with monaco-languageclient. In case anyone else experiences issues like this, I've opened an issue here: TypeFox/monaco-languageclient#244

Thanks again for the help

@stamblerre stamblerre removed this from the gopls/unplanned milestone Dec 31, 2020
@golang golang locked and limited conversation to collaborators Dec 31, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

3 participants