The LanguageClient API doesn't seem to support `workspace/didChangeConfiguration`

Despite the docs stating that the LanguageClient API supports workspace/didChangeConfiguration that doesn’t seem to be the case, although maybe I’m just using the API wrong?

I’m working on the Intelephense language server extension and trying to add an option that will allow people to modify which stubs are available to the language server. That has to be done through the workspace/configuration language server API.

This is what I’m trying right now, without success:

client.start();

// Send notification 2 seconds after server starts before sending
// new configuration to make sure server is running.
setTimeout(() => {
	client.sendNotification(
		'workspace/didChangeConfiguration',
		{
			settings: {
				intelephense: {
					stubs: [...stubsDefault, 'wordpress'],
				},
				'intelephense.stubs': [
					...stubsDefault,
					'wordpress',
				],
			},
			intelephense: {
				stubs: [...stubsDefault, 'wordpress'],
			},
			'intelephense.stubs': [
				...stubsDefault,
				'wordpress',
			],
			'settings.intelephense.stubs': [
				...stubsDefault,
				'wordpress',
			],
		}
	);
}, 2000);

I’ve also tried wrapping the object parameter in an array ([ { intelephense: { stubs: [ /* ... */ ] } } ]), and that doesn’t work either.

None of the ways I’ve tried here successfully update the stubs used by Intelephense; it still can’t find any information about WordPress functions.

Am I not using the API correctly? Is this an issue in Nova? Or do I need to implement support for workspace/configuration manually?

I’m really not sure how to proceed here, and would love to get some input on what the intended use of the API is.

The workspace/didChangeConfiguration is not a message you send from your extension, but is sent by Nova itself. The data Nova sends comes from your extension’s Preferences and properties set with the Configuration API.

Here I have a user visible preferences item, defined in the extension’s config JSON (this being just a fragment of the config):

{
   "key": "gopls.ui.completion.usePlaceholders",
   "title": "usePlaceholders",
   "description": "placeholders enables placeholders for function parameters or struct  fields in completion responses.",
   "type": "boolean",
   "default": false
}

When I check or uncheck the box in the extension preferences UI, Nova sends this language server automatically:

[Trace - 20:10:03.667 PM] Sending notification 'workspace/didChangeConfiguration'.
Params: {"settings":{"gopls":{"ui.completion.usePlaceholders":true}}}

So, it is a matter of arranging the data, either with the user visible Preferences configuration, or set programmatically with the Configuration API, but then letting Nova and the language server handle the actually message exchange.

Related to this, the language server can also ask Nova for workspace configuration more or less whenever it wants. Continuing with the example, Nova gets this request from the gopls language server, which asks for configuration scoped to a “section” named gopls, where a “section” in Nova’s universe is simply the first part before the first dot (.) of extension preferences key. So for this request from gopls for the "gopls" section:

[Trace - 20:10:03.667 PM] Received request 'workspace/configuration - (2)'.
Params: {"items":[{"section":"gopls"}]}

Nova responds with all the extension preferences keys starting with gopls.:

[Trace - 20:10:03.668 PM] Sending response 'workspace/configuration - (2)' in 0ms.
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"}]

I hope that helps!

-john

4 Likes

Ah, that makes sense, I guess. And worked too, so thank you! :smiley:

@logan y’all might want to consider adding this to the documentation, and at least refer to it in the LanguageClient API docs. I would’ve never figured this out without @jrf pointing this out :slight_smile:

Feature request @logan: The gopls language server has a nice dump of all RPC messages. It would be nifty if Nova could also do that in a language server independent fashion. Seeing the whole conversation is super helpful in understanding the boundary between the Nova-language server dialog, and supplemental extension-language server dialog used to fill in LSP bits that Nova doesn’t yet support as built in.

4 Likes

That is indeed a good suggestion! I will look into this.