Description
When using OmniSharp LSP from emacs lsp-mode, the initialize handshake is as shown at the bottom. The server response contains "textDocumentSync": 0
, so lsp-mode sends no textDocument/didChange notifications.
The relevant code in LanguageServer.cs
is also shown below. The check for ccp.HasStaticHandler(textDocumentCapabilities.Synchronization)
returns false because although there is a TextDocumentSyncHandler
registered (specifically OmnisharpTextDocumentSyncHandler
), TextDocumentSyncHandler
doesn't provide IWillSaveTextDocumentHandler
or IWillSaveWaitUntilTextDocumentHandler
, both of which are linked to SynchronizationCapability
.
Removing the check causes the server to return a textDocumentSync options block, but the change
item is set to 1 (full) rather than 2 (incremental). This appears to be because there are two OmnisharpTextDocumentSyncHandlers registered, one for cake and one for cs/csx, and the cake one doesn't handle incremental. Not sure if that should be a separate issue for omnisharp-roslyn, but it means you can't send incremental changes for cs/csx files because the Min() call in the code below means it picks up kind 1.
if (ccp.HasStaticHandler(textDocumentCapabilities.Synchronization))
{
var textDocumentSyncKind = _collection.ContainsHandler(typeof(IDidChangeTextDocumentHandler))
? _collection
.Select(x => x.Handler)
.OfType<IDidChangeTextDocumentHandler>()
.Where(x => x.GetRegistrationOptions()?.SyncKind != TextDocumentSyncKind.None)
.Min(z => z.GetRegistrationOptions()?.SyncKind)
: TextDocumentSyncKind.None;
if (_clientVersion == ClientVersion.Lsp2)
{
serverCapabilities.TextDocumentSync = textDocumentSyncKind;
}
else
{
serverCapabilities.TextDocumentSync = new TextDocumentSyncOptions()
{
Change = textDocumentSyncKind ?? TextDocumentSyncKind.None,
OpenClose = _collection.ContainsHandler(typeof(IDidOpenTextDocumentHandler)) || _collection.ContainsHandler(typeof(IDidCloseTextDocumentHandler)),
Save = _collection.ContainsHandler(typeof(IDidSaveTextDocumentHandler)) ?
new SaveOptions() { IncludeText = true /* TODO: Make configurable */ } :
null,
WillSave = _collection.ContainsHandler(typeof(IWillSaveTextDocumentHandler)),
WillSaveWaitUntil = _collection.ContainsHandler(typeof(IWillSaveWaitUntilTextDocumentHandler))
};
}
}
[Trace - 12:19:49 PM] Sending request 'initialize - (55)'.
Params: {
"processId": 33868,
"rootPath": "p:/experiments/LspTest/",
"rootUri": "file:///p:/experiments/LspTest/",
"capabilities": {
"workspace": {
"workspaceEdit": {
"documentChanges": true,
"resourceOperations": [
"create",
"rename",
"delete"
]
},
"applyEdit": true,
"symbol": {
"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": false
},
"didChangeWatchedFiles": {
"dynamicRegistration": true
},
"workspaceFolders": true,
"configuration": true
},
"textDocument": {
"declaration": {
"linkSupport": true
},
"definition": {
"linkSupport": true
},
"implementation": {
"linkSupport": true
},
"typeDefinition": {
"linkSupport": true
},
"synchronization": {
"didSave": true,
"willSaveWaitUntil": true
},
"documentSymbol": {
"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
},
"formatting": {
"dynamicRegistration": true
},
"codeAction": {
"dynamicRegistration": true,
"codeActionLiteralSupport": {
"codeActionKind": {
"valueSet": [
"",
"quickfix",
"refactor",
"refactor.extract",
"refactor.inline",
"refactor.rewrite",
"source",
"source.organizeImports"
]
}
}
},
"completion": {
"completionItem": {
"snippetSupport": true,
"documentationFormat": [
"markdown"
]
},
"contextSupport": true
},
"signatureHelp": {
"signatureInformation": {
"parameterInformation": {
"labelOffsetSupport": true
}
}
},
"documentLink": {
"dynamicRegistration": true
},
"hover": {
"contentFormat": [
"markdown",
"plaintext"
]
},
"foldingRange": {
"dynamicRegistration": true,
"rangeLimit": null,
"lineFoldingOnly": false
}
}
},
"initializationOptions": null
}
[Trace - 12:20:01 PM] Received response 'initialize - (55)' in 753ms.
Result: {
"capabilities": {
"experimental": {
},
"renameProvider": {
"prepareProvider": null
},
"documentOnTypeFormattingProvider": {
"moreTriggerCharacter": [
"}",
")"
],
"firstTriggerCharacter": ";"
},
"documentRangeFormattingProvider": true,
"documentFormattingProvider": null,
"codeLensProvider": {
"resolveProvider": true
},
"workspaceSymbolProvider": null,
"documentSymbolProvider": true,
"documentHighlightProvider": null,
"referencesProvider": true,
"definitionProvider": true,
"signatureHelpProvider": {
"triggerCharacters": [
".",
"?",
"["
]
},
"completionProvider": {
"triggerCharacters": [
"."
],
"resolveProvider": null
},
"hoverProvider": true,
"textDocumentSync": 0
}
}