2

I'm toying around LSP and I cannot get past first stage. Am using Python as client language since it is simple to work with. All I do is:

  1. Connect to LSP - This works fine
  2. Send Initialize JSON RPC - Client report success
  3. Get response - Empty result

I have tried everything I could and read whatever I could find but I had no success. I hope for someone more conversant with LSP to help me pointing out what am doing wrong.

Here is my Python code. I tried with PHP Language Server but shouldn't matter the kind of server used.

import socket
import sys 

initReq = """
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": " initialize",
    "params": {
        "processId": null,
        "rootPath": "/Users/stefano/Testing/PHPSources",
        "rootUri": "file:///Users/stefano/Testing/PHPSources",
        "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,
                    "tagSupport": 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
                    },
                    "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,
                    "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,
                    "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
                },
                "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
                }
            }
        },
        "initializationOptions": {
            "storagePath": "/Users/hosanna/Library/Application Support/Code/User/workspaceStorage/30bd6a399166f4f329c9f383d63b74ca/bmewburn.vscode-intelephense-client",
            "clearCache": false
        },
        "trace": "verbose",
        "workspaceFolders": [
            {
                "uri": "file:///Users/stefano/Testing/PHPSources",
                "name": "TransportationApp"
            }
        ]
    }
}
"""

host = '127.0.0.1'
port = 8088

# create socket
print('# Creating socket')
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
    print('Failed to create socket')
    sys.exit()

# Connect to remote server
print('# Connecting to server, ' + host)
s.connect((host , port))

# Send data to remote server
print('# Sending data to server')

try:
    s.sendall(initReq.encode('utf-8'))
except socket.error:
    print('Send failed')
    sys.exit()

# Receive data
print('# Receive data from server')
reply = s.recv(4096)

print(reply) 
Stefano Mtangoo
  • 6,017
  • 6
  • 47
  • 93

1 Answers1

2

I was missing the header part and its respective new lines. Thanks to rcjsuen for helping on Github

format for reference should be:

Content-Length: <length>\r\n
\r\n
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "textDocument/didOpen",
    "params": {
        ...
    }
}
Stefano Mtangoo
  • 6,017
  • 6
  • 47
  • 93
  • Currently I am wondering if it works to interact with the language server by directly sending JSON RPC. It seems that your code confirms it, but how to generate the valid json for LSP? Can you give me some instructions? – K. Symbol Jul 27 '19 at 09:53
  • LSP uses JSONRPC. You can see the Specs here: https://www.jsonrpc.org/specification – Stefano Mtangoo Jul 27 '19 at 11:00
  • Then the JSON payloa have to be combined with at least Content-Length header to make a valid Protocol compliant request (as my answer shows – Stefano Mtangoo Jul 27 '19 at 11:01
  • Thanks for answering, I am trying to generate valid LSP json according to: https://microsoft.github.io/language-server-protocol/specification , but currently I only managed to send initialize request as your code, did you try other methods (like didOpen/definition)? – K. Symbol Jul 27 '19 at 14:30
  • Yes I did, where do you get a problem? Do you get the response for initialize? – Stefano Mtangoo Jul 27 '19 at 14:43
  • I have got the right response for initialize, but error response for didOpen: "error":{"message":"Debug Failure. False expression.","code":-32001,"data":{}}} – K. Symbol Jul 27 '19 at 14:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/197091/discussion-between-stefano-mtangoo-and-k-symbol). – Stefano Mtangoo Jul 27 '19 at 14:54