sublimelsp / LSP

Client implementation of the Language Server Protocol for Sublime Text

Home Page:https://lsp.sublimetext.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LSP messaging does not properly handle trailing `.0` on integer values

IsaacShelton opened this issue · comments

Describe the bug

LSP messaging does not properly handle trailing .0 on integer values as per JSON spec.

To Reproduce

Send a server initialization response such as:

{
  "jsonrpc": "2.0",
  "id": 1.0,
  "result": {
    "capabilities": {
      "hoverProvider": true,
      "definitionProvider": true,
      "textDocumentSync": {
        "openClose": true,
        "change": 1.0
      }
    },
    "serverInfo": {
      "name": "adeptls",
      "version": "2.8"
    }
  }
}

Expected behavior

For the above response message, textDocument/didChange should be set to TextDocumentSyncKind.Full, but instead is ignored because 1.0 is not recognized as an integer.

Logs

Message sent by server:

[sending] {"jsonrpc":"2.0","id":1.0,"result":{"capabilities":{"hoverProvider":true,"definitionProvider":true,"textDocumentSync":{"openClose":true,"change":1.0},"completionProvider":{"triggerCharacters":["\\"]}},"serverInfo":{"name":"adeptls","version":"2.8"}}}

Client Log:

:: [10:17:06.975] --> adeptls initialize (1): {'initializationOptions': {}, 'processId': 72053, 'capabilities': {'textDocument': {'synchronization': {'didSave': True, 'willSave': True, 'dynamicRegistration': True, 'willSaveWaitUntil': True}, 'documentLink': {'dynamicRegistration': True, 'tooltipSupport': True}, 'documentHighlight': {'dynamicRegistration': True}, 'hover': {'contentFormat': ['markdown', 'plaintext'], 'dynamicRegistration': True}, 'diagnostic': {'relatedDocumentSupport': True, 'dynamicRegistration': True}, 'documentSymbol': {'tagSupport': {'valueSet': [1]}, 'symbolKind': {'valueSet': [10, 12, 5, 3, 13, 15, 17, 11, 4, 20, 7, 21, 8, 6, 18, 25, 24, 2, 16, 22, 23, 26, 9, 14, 19, 1]}, 'dynamicRegistration': True, 'hierarchicalDocumentSymbolSupport': True}, 'rename': {'prepareSupportDefaultBehavior': 1, 'dynamicRegistration': True, 'prepareSupport': True}, 'selectionRange': {'dynamicRegistration': True}, 'semanticTokens': {'dynamicRegistration': True, 'tokenModifiers': ['async', 'declaration', 'documentation', 'deprecated', 'static', 'abstract', 'definition', 'modification', 'defaultLibrary', 'readonly'], 'requests': {'full': {'delta': True}, 'range': True}, 'augmentsSyntaxTokens': True, 'multilineTokenSupport': True, 'formats': ['relative'], 'overlappingTokenSupport': False, 'tokenTypes': ['enum', 'function', 'macro', 'event', 'namespace', 'variable', 'comment', 'class', 'interface', 'struct', 'modifier', 'string', 'method', 'operator', 'property', 'number', 'enumMember', 'typeParameter', 'type', 'parameter', 'keyword', 'regexp', 'decorator']}, 'implementation': {'dynamicRegistration': True, 'linkSupport': True}, 'foldingRange': {'foldingRangeKind': {'valueSet': ['comment', 'imports', 'region']}, 'dynamicRegistration': True}, 'typeDefinition': {'dynamicRegistration': True, 'linkSupport': True}, 'completion': {'completionItemKind': {'valueSet': [13, 3, 7, 16, 6, 18, 8, 10, 5, 2, 24, 23, 9, 22, 17, 20, 25, 4, 11, 21, 19, 1, 15, 14, 12]}, 'completionItem': {'insertTextModeSupport': {'valueSet': [2]}, 'documentationFormat': ['markdown', 'plaintext'], 'tagSupport': {'valueSet': [1]}, 'snippetSupport': True, 'labelDetailsSupport': True, 'resolveSupport': {'properties': ['detail', 'documentation', 'additionalTextEdits']}, 'deprecatedSupport': True, 'insertReplaceSupport': True}, 'completionList': {'itemDefaults': ['editRange', 'insertTextFormat', 'data']}, 'dynamicRegistration': True, 'insertTextMode': 2}, 'colorProvider': {'dynamicRegistration': True}, 'callHierarchy': {'dynamicRegistration': True}, 'publishDiagnostics': {'tagSupport': {'valueSet': [2, 1]}, 'versionSupport': True, 'relatedInformation': True, 'dataSupport': True, 'codeDescriptionSupport': True}, 'declaration': {'dynamicRegistration': True, 'linkSupport': True}, 'codeLens': {'dynamicRegistration': True}, 'references': {'dynamicRegistration': True}, 'codeAction': {'codeActionLiteralSupport': {'codeActionKind': {'valueSet': ['quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source.fixAll', 'source.organizeImports']}}, 'resolveSupport': {'properties': ['edit']}, 'dynamicRegistration': True, 'dataSupport': True, 'isPreferredSupport': True}, 'typeHierarchy': {'dynamicRegistration': True}, 'formatting': {'dynamicRegistration': True}, 'signatureHelp': {'signatureInformation': {'documentationFormat': ['markdown', 'plaintext'], 'activeParameterSupport': True, 'parameterInformation': {'labelOffsetSupport': True}}, 'dynamicRegistration': True, 'contextSupport': True}, 'definition': {'dynamicRegistration': True, 'linkSupport': True}, 'inlayHint': {'resolveSupport': {'properties': ['textEdits', 'label.command']}, 'dynamicRegistration': True}, 'rangeFormatting': {'dynamicRegistration': True, 'rangesSupport': True}}, 'general': {'markdown': {'parser': 'Python-Markdown', 'version': '3.2.2'}, 'regularExpressions': {'engine': 'ECMAScript'}}, 'workspace': {'diagnostics': {'refreshSupport': True}, 'executeCommand': {}, 'applyEdit': True, 'workspaceEdit': {'failureHandling': 'abort', 'documentChanges': True}, 'configuration': True, 'symbol': {'resolveSupport': {'properties': ['location.range']}, 'symbolKind': {'valueSet': [10, 12, 5, 3, 13, 15, 17, 11, 4, 20, 7, 21, 8, 6, 18, 25, 24, 2, 16, 22, 23, 26, 9, 14, 19, 1]}, 'dynamicRegistration': True, 'tagSupport': {'valueSet': [1]}}, 'didChangeConfiguration': {'dynamicRegistration': True}, 'inlayHint': {'refreshSupport': True}, 'codeLens': {'refreshSupport': True}, 'workspaceFolders': True, 'semanticTokens': {'refreshSupport': True}}, 'window': {'showMessage': {'messageActionItem': {'additionalPropertiesSupport': True}}, 'workDoneProgress': True, 'showDocument': {'support': True}}}, 'rootPath': None, 'clientInfo': {'version': '1.28.0', 'name': 'Sublime Text LSP'}, 'rootUri': None, 'workspaceFolders': None}
:: [10:17:07.127] <<< adeptls (1) (duration: 151ms): {'serverInfo': {'version': '2.8', 'name': 'adeptls'}, 'capabilities': {'textDocumentSync': {'didOpen': {}, 'didClose': {}}, 'definitionProvider': True, 'hoverProvider': True, 'completionProvider': {'triggerCharacters': ['\\']}}}
:: [10:17:07.127]  -> adeptls initialized: {}
:: [10:17:07.129]  -> adeptls textDocument/didOpen: <params with 12090 characters>
:: [10:17:07.182] <-  adeptls textDocument/publishDiagnostics: {'version': 0.0, 'diagnostics': [], 'uri': 'file:///Users/isaac/AdeptProjects/AdeptLSP/src/main.adept'}

JSONRPC spec says:

id
An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2]

It doesn't say "MUST NOT" but still.

It's not only with the id of the response, it's also that a value of 1.0 for textDocumentSync.change is not recognized.

The LSP spec says nothing about fractional parts, the messaging is in JSON, and by the JSON spec, 1.0 is the same as 1.

Also, the LSP spec defines integers as JavaScript to be number

Do what you like though

The place you've linked defines integer, uinteger and decimal explicitly. All are mapped to number, I guess due to it being based on typescript typing system but that doesn't mean that decimal values are allowed in place of integer and uinteger. And for sure not in place of enum values which might technically be numbers under the hood in typescript case but spec doesn't specify that.

They are specified as JSON, and JSON does not have the concept of integers, only numbers

In JSON, there is no difference between 1 and 1.0.

The entire protocol is in JSON. What is there to argue here?

I'm not going to debate with you guys anymore on this bug as it seems like you guys are not open to admitting fault in your software nor fixing it

The LSP specification can impose additional restrictions on top of JSON specification and as far I understand this is what is happening here. You can ask at LSP specification repo if you think otherwise.