LSP not forwarding config values

I’m not sure if this is a problem with my language server, or an issue with Nova. The problem I am having is that none of my configured extensions preferences are being received by the language server, and it is falling back to its defaults.
This leads me to believe that the settings are not being sent in a format that this LSP expects. Is there any way to debug this?

I am unable to turn verbose logging on in the language server on, as I am unable to flip that setting due to the above issue.

Having an RPC log is essential for troubleshooting. I can’t give you the opening Nova / Language Server dialog for your language server, but I can give you one from a language server.

Here is the opening exchange of Nova talking to the gopls language server in my (unpublished) Go extension. The “Sending” and “Received” are from Nova’s point of view. The initializationOptions in the message are passed through via the last argument of the LanguageClient constructor. (Here I have a function that feeds in the values for…reasons, but they could be a literal set of key-value pairs.)

var clientOptions = {
    // The set of document syntaxes for which the server is valid
    syntaxes: ['go'],
    initializationOptions: gopls.Settings(),
};
var client = new LanguageClient(
    'gopls',
    'gopls',
    serverOptions,
    clientOptions
);

[Trace - 09:13:21.248 AM] Sending request ‘initialize - (0)’.

Nova sends this to the language server

Params:

{
    "capabilities": {
        "workspace": {
            "configuration": true,
            "applyEdit": true,
            "executeCommand": {},
            "workspaceFolders": true,
            "workspaceEdit": {
                "failureHandling": "undo",
                "documentChanges": true,
                "resourceOperations": [
                    "create",
                    "rename",
                    "delete"
                ]
            }
        },
        "textDocument": {
            "rename": {
                "prepareSupport": true
            },
            "codeAction": {
                "codeActionLiteralSupport": {
                    "codeActionKind": {
                        "valueSet": [
                            "",
                            "quickfix",
                            "refactor",
                            "refactor.inline",
                            "refactor.extract",
                            "refactor.rewrite",
                            "source",
                            "source.organizeImports"
                        ]
                    }
                },
                "isPreferredSupport": true
            },
            "hover": {
                "contentFormat": [
                    "markdown",
                    "plaintext"
                ]
            },
            "completion": {
                "completionItem": {
                    "snippetSupport": true,
                    "deprecatedSupport": true,
                    "commitCharactersSupport": true,
                    "documentationFormat": [
                        "markdown",
                        "plaintext"
                    ],
                    "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
                    ]
                },
                "contextSupport": true
            },
            "codeLens": {},
            "documentHighlight": {},
            "synchronization": {
                "didSave": true,
                "willSave": true,
                "willSaveWaitUntil": true
            },
            "publishDiagnostics": {
                "versionSupport": true,
                "relatedInformation": true
            },
            "declaration": {
                "linkSupport": true
            },
            "typeDefinition": {
                "linkSupport": true
            },
            "definition": {
                "linkSupport": true
            },
            "implementation": {
                "linkSupport": true
            },
            "signatureHelp": {
                "signatureInformation": {
                    "documentationFormat": [
                        "markdown",
                        "plaintext"
                    ]
                }
            }
        }
    },
    "workspaceFolders": [
        {
            "uri": "file:///Users/jfieber/Documents/code/github.com/jfieber/wgn/",
            "name": "wgn"
        }
    ],
    "rootPath": "/Volumes/gamut/Users/jfieber/Documents/code/github.com/jfieber/wgn",
    "processId": 732,
    "initializationOptions": {
        "ui.completion.usePlaceholders": true,
        "build.buildFlags": [],
        "formatting.gofumpt": false,
        "ui.navigation.importShortcut": "Both",
        "ui.navigation.symbolMatcher": "Fuzzy",
        "formatting.local": "",
        "ui.documentation.linksInHover": true,
        "build.directoryFilters": [],
        "ui.navigation.symbolStyle": "Dynamic",
        "ui.documentation.hoverKind": "FullDocumentation",
        "ui.completion.matcher": "Fuzzy",
        "ui.documentation.linkTarget": "pkg.go.dev"
    },
    "rootUri": "file:///Users/jfieber/Documents/code/github.com/jfieber/wgn/",
    "clientInfo": {
        "name": "Nova",
        "version": "6.1"
    }
}

[Trace - 09:13:21.249 AM] Received response ‘initialize - (0)’ in 1ms.

This is from the language server.

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.add_dependency",
                "gopls.add_import",
                "gopls.apply_fix",
                "gopls.check_upgrades",
                "gopls.gc_details",
                "gopls.generate",
                "gopls.generate_gopls_mod",
                "gopls.go_get_package",
                "gopls.list_known_packages",
                "gopls.regenerate_cgo",
                "gopls.remove_dependency",
                "gopls.run_tests",
                "gopls.test",
                "gopls.tidy",
                "gopls.toggle_gc_details",
                "gopls.update_go_sum",
                "gopls.upgrade_dependency",
                "gopls.vendor"
            ]
        },
        "callHierarchyProvider": true,
        "workspace": {
            "workspaceFolders": {
                "supported": true,
                "changeNotifications": "workspace/didChangeWorkspaceFolders"
            }
        }
    },
    "serverInfo": {
        "name": "gopls",
        "version": "{\"path\":\"golang.org/x/tools/gopls\",\"version\":\"v0.6.9\",\"sum\":\"h1:LBBcE2y3Tb4bp79JVLWCQBbvYCFEs5ADGWsQDoSLk1Q=\",\"deps\":[{\"path\":\"github.com/BurntSushi/toml\",\"version\":\"v0.3.1\",\"sum\":\"h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\"},{\"path\":\"github.com/google/go-cmp\",\"version\":\"v0.5.4\",\"sum\":\"h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=\"},{\"path\":\"github.com/sergi/go-diff\",\"version\":\"v1.1.0\",\"sum\":\"h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=\"},{\"path\":\"golang.org/x/mod\",\"version\":\"v0.4.1\",\"sum\":\"h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=\"},{\"path\":\"golang.org/x/sync\",\"version\":\"v0.0.0-20201020160332-67f06af15bc9\",\"sum\":\"h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=\"},{\"path\":\"golang.org/x/sys\",\"version\":\"v0.0.0-20210124154548-22da62e12c0c\",\"sum\":\"h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=\"},{\"path\":\"golang.org/x/tools\",\"version\":\"v0.1.1-0.20210319172145-bda8f5cee399\",\"sum\":\"h1:O5bm8buX/OaamnfcBrkjn0SPUIU30jFmaS8lP+ikkxs=\"},{\"path\":\"golang.org/x/xerrors\",\"version\":\"v0.0.0-20200804184101-5ec99f83aff1\",\"sum\":\"h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=\"},{\"path\":\"honnef.co/go/tools\",\"version\":\"v0.1.1\",\"sum\":\"h1:EVDuO03OCZwpV2t/tLLxPmPiomagMoBOgfPt0FM+4IY=\"},{\"path\":\"mvdan.cc/gofumpt\",\"version\":\"v0.1.0\",\"sum\":\"h1:hsVv+Y9UsZ/mFZTxJZuHVI6shSQCtzZ11h1JEFPAZLw=\"},{\"path\":\"mvdan.cc/xurls/v2\",\"version\":\"v2.2.0\",\"sum\":\"h1:NSZPykBXJFCetGZykLAxaL6SIpvbVy/UFEniIfHAa8A=\"}]}"
    }
}

[Trace - 09:13:21.249 AM] Sending notification ‘initialized’.
Params:

{}

The language server can ask Nova for the workspace configuration at any time. The section is a configuration scope and the values come from Nova’s configuration item key space. So in the response, where you see ui.completion.usePlaceholders, the actual Nova configuration item key is gopls.ui.completion.usePlaceholders. Nova just enumerates the keys starting with gopls. and hands them over. Whether your language server request stuff in exactly the same way, I don’t know.

(@logan: would be super nifty if we could register a callback to supply the workspace configuration. I would love to keep the gopls options scoped to my extension. The problem case: I flip back and forth between my Go extension, and the Go extension in the registry by @GwynethLlewelyn, the two currently have no choice but to compete over the gopls. configuration key space. Hand-editing UserConfiguration.json when switching isn’t a great option.)

[Trace - 09:13:21.250 AM] Received request ‘workspace/configuration - (1)’.

Params:

{
    "items": [
        {
            "scopeUri": "file:///Users/jfieber/Documents/code/github.com/jfieber/wgn/",
            "section": "gopls"
        }
    ]
}

[Trace - 09:13:21.264 AM] Sending response ‘workspace/configuration - (1)’ in 13ms.
Result:

[
    {
        "ui.completion.usePlaceholders": true,
        "ui.navigation.importShortcut": "Both",
        "build.buildFlags": [],
        "formatting.gofumpt": false,
        "ui.navigation.symbolMatcher": "Fuzzy",
        "formatting.local": "",
        "ui.documentation.linksInHover": true,
        "ui.navigation.symbolStyle": "Dynamic",
        "build.directoryFilters": [],
        "ui.documentation.hoverKind": "FullDocumentation",
        "ui.completion.matcher": "Fuzzy",
        "ui.documentation.linkTarget": "pkg.go.dev"
    }
]
1 Like

@jrf Thank you for your detailed and lengthy answer! A bit more investigation into the logs that I can see is revealing that something is wrong with how the language server is being initialized.:

Intelephense LSP[11:50:04.270000] Initialising intelephense 1.5.4

Intelephense LSP[11:50:04.273000] Reading state from /Users/mike/Library/Application Support/Nova/Workspaces/DE463EA1-CEBF-4F37-BD5D-156307D0B058/genealabs.intelephense/intelephense/78cd880d.

Intelephense LSP[11:50:05.321000] Initialised in 1051 ms

Intelephense LSP[11:50:05.388000] Registering request handler for workspace/didChangeWorkspaceFolders failed.

Intelephense LSP[11:50:05.395000] (node:42473) UnhandledPromiseRejectionWarning: Error: Invalid parameter: registrations


Intelephense LSP[11:50:05.395000] Registrations must be of type Registration[]


Intelephense LSP[11:50:05.395000]     at /Users/mike/Library/Application Support/Nova/Workspaces/DE463EA1-CEBF-4F37-BD5D-156307D0B058/genealabs.intelephense/node_modules/intelephense/lib/intelephense.js:3:168725


Intelephense LSP[11:50:05.395000]     at /Users/mike/Library/Application Support/Nova/Workspaces/DE463EA1-CEBF-4F37-BD5D-156307D0B058/genealabs.intelephense/node_modules/intelephense/lib/intelephense.js:3:169019


Intelephense LSP[11:50:05.395000]     at Immediate.<anonymous> (/Users/mike/Library/Application Support/Nova/Workspaces/DE463EA1-CEBF-4F37-BD5D-156307D0B058/genealabs.intelephense/node_modules/intelephense/lib/intelephense.js:3:169378)


Intelephense LSP[11:50:05.395000]     at processImmediate (internal/timers.js:458:21)


Intelephense LSP[11:50:05.395000] (Use `node --trace-warnings ...` to show where the warning was created)


Intelephense LSP[11:50:05.395000] (node:42473) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)


Intelephense LSP[11:50:05.395000] (node:42473) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.


Intelephense LSP[11:50:05.920000] file:///Users/mike/Developer/Sites/totalitylms.com/vendor/composer/autoload_classmap.php is over the maximum file size of 1000000 bytes.

Intelephense LSP[11:50:05.920000] file:///Users/mike/Developer/Sites/totalitylms.com/vendor/composer/autoload_static.php is over the maximum file size of 1000000 bytes.

Intelephense LSP[11:50:05.931000] file:///Users/mike/Developer/Sites/totalitylms.com/vendor/fakerphp/faker/src/Faker/Provider/nl_BE/Text.php is over the maximum file size of 1000000 bytes.

Intelephense LSP[11:50:05.935000] Indexing started.

Intelephense LSP[11:50:06.141000] Indexing ended. 3 files indexed in 0s.

Intelephense LSP[11:50:06.142000] Writing state to /Users/mike/Library/Application Support/Nova/Workspaces/DE463EA1-CEBF-4F37-BD5D-156307D0B058/genealabs.intelephense/intelephense/78cd880d.

Intelephense LSP[11:50:07.333000] Wrote state in 1.2s.

The log shows that something isn’t right with how the language server is being registered. That would explain why I can’t get config options to work. In newer versions of the LSP these errors are not present (at least not in output), yet it is also not registering config values, and also is not indexing the project files (which works on this older version).

Do you have access to un-minified/obfuscated source? (I’m presuming from the line:column address you are dealing with minified code.) From this, it is hard to tell if it is exploding due to something in the initialization exchange, or if it is just exploding for some other reason.

If you haven’t dug here, the vs code extension might reveal some useful debug knobs.