Return key does not trigger Language Server `onTypeFormatting` request (no `end` completion)
Ruby LSP has a feature to automatically add ends, e.g. after def method_name. It uses the textDocument/onTypeFormatting language server request.
In Zed, this doesn't work. I suspect this is a bug in Zed rather than the extension, but I'm logging it here first until I learn more.
Example (comparing with VS Code)
In Ruby LSP with VS Code, enable verbose logging.
You'll also need to enable "editor.formatOnType": true since it's disabled by default.
Now type the following:
def foo
The logs will show a request:
Sending request 'textDocument/onTypeFormatting - (41)'.
{
"textDocument": { "uri": "file:///Users/andy/src/github.com/Shopify/ruby-lsp/x.rb" },
"position": { "line": 3, "character": 1 },
"ch": "d",
"options": { "tabSize": 2, "insertSpaces": true }
}
and an empty response
Received response 'textDocument/onTypeFormatting - (41)' in 1ms.
Now press return and you'll see a second request:
Sending request 'textDocument/onTypeFormatting - (48)'.
{
"textDocument": { "uri": "file:///Users/andy/src/github.com/Shopify/ruby-lsp/x.rb" },
"position": { "line": 4, "character": 2 },
"ch": "\n",
"options": {
"tabSize": 2,
"insertSpaces": true
}
}
and a response, which causes an end to be added:
[
{
"range": {
"start": { "line": 4, "character": 2 },
"end": { "line": 4, "character": 2 }
},
"newText": "\n"
},
{
"range": {
"start": { "line": 4, "character": 2 },
"end": { "line": 4, "character": 2 }
},
"newText": "end"
},
{
"range": {
"start": { "line": 4, "character": 2 },
"end": { "line": 4, "character": 2 }
},
"newText": "$0"
}
]
In Zed, we see the first request:
// Send:
{"jsonrpc":"2.0","id":39,"method":"textDocument/onTypeFormatting",
"params":{"textDocument":{"uri":"file:///Users/andy/src/github.com/Shopify/ruby-lsp/x.rb"},"position":{"line":0,"character":1},
"ch":"d",
"options":{"tabSize":2,"insertSpaces":true,"trimTrailingWhitespace":true,"insertFinalNewline":true,"trimFinalNewlines":true}}}
// Receive:
{"id":39,"result":[],"jsonrpc":"2.0"}
but after pressing return, there is no second request.
#38 may be related.
I looked to see how the Lua extension handles this, since it also has end, but it's a different approach. It's based on textDocument/publishDiagnostics. So after you type if true then, a suggested fix pops up to add the end, and hitting return selects that.
// Receive:
{
"jsonrpc": "2.0",
"method": "textDocument/publishDiagnostics",
"params": {
"diagnostics": [
{
"code": "miss-exp",
"data": "syntax",
"message": "<exp> expected.",
"range": {
"end": {
"character": 2,
"line": 0
},
"start": {
"character": 2,
"line": 0
}
},
"severity": 1,
"source": "Lua Syntax Check."
},
{
"code": "miss-end",
"data": "syntax",
"message": "Miss corresponding `end` .",
"range": {
"end": {
"character": 2,
"line": 0
},
"start": {
"character": 0,
"line": 0
}
},
"severity": 1,
"source": "Lua Syntax Check."
}
],
"uri": "/Users/andy/src/github.com/Shopify/ruby-lsp/x.lua",
"version": 238
}
}
// Receive:
{
"id": 926,
"jsonrpc": "2.0",
"result": {
"insertText": "if $1 then\n\t$0\nend",
"insertTextFormat": 2,
"kind": 15,
"label": "if .. then",
"sortText": "0001"
}
}
This likely relates to more_trigger_character:
https://github.com/Shopify/ruby-lsp/blob/f3ff6a36afbc7134d640c8e6be54c7c8f63f0aaf/lib/ruby_lsp/requests/on_type_formatting.rb#L15
Mentioned here (moreTriggerCharacter) in the spec:
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_onTypeFormatting
This seems to be a Zed issue. According to Claude Code's codebase inspection, Zed doesn't send document/onTypeFormatting requests when pressing enter, not only in Ruby files.
AI summary
⏺ Based on my analysis of the Zed codebase, no, Zed does NOT send document/onTypeFormatting LSP requests when pressing Enter.
Here's what I found:
Key Evidence
1. Separate code paths:
- Regular character input goes through handle_input() (editor.rs:4037) which calls trigger_on_type_formatting() (editor.rs:4380)
- Pressing Enter uses a dedicated newline() function (editor.rs:4468) that does NOT call trigger_on_type_formatting()
2. The newline function: The newline() function handles its own logic for inserting newlines, comment continuation, and indentation, but never triggers on-type formatting.
3. Test evidence: The test test_on_type_formatting_is_applied_after_autoindent (editor_tests.rs:17073) confirms this:
- It simulates pressing Enter at line 17094
- Then simulates pressing "." at line 17114
- Only the "." character triggers the on-type formatting request, not the newline
4. Implementation details: While trigger_on_type_formatting() only accepts single-character input (editor.rs:5398), which "\n" would satisfy, the newline action bypasses this
code path entirely.
So even if a language server declares "\n" as a trigger character in its documentOnTypeFormattingProvider, Zed won't send the request because Enter key presses use a separate
implementation that doesn't participate in on-type formatting.
I had opened https://github.com/zed-industries/zed/issues/12383, but if it's indeed not specific to Ruby, I think it should be opened as a generic issue.