Repository navigation
Add support for SnippetTextEdit - #2884
Conversation
| def on_workspace_apply_edit(self, params: ApplyWorkspaceEditParams) -> Promise[ApplyWorkspaceEditResult]: | ||
| return self.apply_workspace_edit_async(params.get('edit', {}), label=params.get('label')) \ | ||
| .then(lambda _: {"applied": True}) | ||
| is_refactoring = params.get('metadata', {}).get('isRefactoring', False) |
There was a problem hiding this comment.
This is a "drive-by" change to add support for WorkspaceEditMetadata from the LSP 3.18 specs.
| def _get_region(self, edit: TextEdit | AnnotatedTextEdit | SnippetTextEdit) -> tuple[int, sublime.Region]: | ||
| range_ = edit['range'] | ||
| start = parse_lsp_position(range_['start']) | ||
| end = parse_lsp_position(range_['end']) | ||
| region = sublime.Region( | ||
| self.view.text_point_utf16(*start, clamp_column=True), | ||
| self.view.text_point_utf16(*end, clamp_column=True) | ||
| ) | ||
| return start[0], region |
There was a problem hiding this comment.
That one is less efficient because it converts to custom Point objects first, and it would unnecessarily access the start twice from the range dict (because we also need start separately).
I used range_to_region initially, but then decided to align with the current implementation in LspApplyDocumentEditCommand:
Lines 143 to 146 in 9a3c394
and
Lines 158 to 161 in 9a3c394
| if scheme == "file" and line_content: | ||
| end_row, end_col_utf16 = parse_lsp_position(edit['range']['end']) | ||
| new_text_rows = edit['newText'].split('\n') | ||
| new_text = sublime.expand_variables(edit['snippet']['value'], {}) if is_snippet_text_edit(edit) else \ |
There was a problem hiding this comment.
Can you explain why are we calling expand_variables on a snippet?
I would expect snippet to contain tab stops, not variables to expand.
There was a problem hiding this comment.
expand_variables (with empty variables) automatically eliminates the placeholders. So this converts the SnippetTextEdit into the 'newText' from a regular TextEdit, which is needed if we don't want to insert it as a snippet (e.g. if not focused view, etc.).
There was a problem hiding this comment.
It's basically a built-in and more powerful variant of what you re-invented with custom regex and string replacement at
Lines 174 to 176 in 9a3c394
>>> sublime.expand_variables('Hello, ${1:name}!$0', {})
'Hello, name!'
There was a problem hiding this comment.
I think the only places where two consecutive backslashes are used in source code would be in LaTeX and also in strings with Windows paths. But I imagine that would be quite rare to happen in WorkspaceEdits / SnippetTextEdits. So I would say we should keep that for now, and if it turns out that this bug regularly happens in practice, we could maybe think about implementing a custom patched version of sublime.expand_variables.
Supersedes #2426
Example:
snippetTextEdit.mp4
Here the inserted SnippetTextEdit has 3 tab stops, two of them with a placeholder text and the last one moving the caret to the end of the inserted text (actually that one is implicitly added, because the snippet text doesn't contain
${0}).It can be tested with LSP-jdtls, and that is the only server I found which already supports SnippetTextEdit at the moment.
This requires additional setup:
Under
LSP/plugin/core/sessions.py
Line 528 in 9105fb5
you need to temporarily add the line
because otherwise jdtls doesn't want to emit edits in the SnippetTextEdit format.
Also you need to create an override for the
LSP-jdtls/modules/jdtls.pyfile, and adjust theinitializationOptions, because LSP-jdtls ignores the initialization options from its own settings file. Then you need to add the line"snippetEditSupport": True,into the"extendedClientCapabilities"at https://github.com/sublimelsp/LSP-jdtls/blob/3866f45806d452d81617830062ac7fbd43f82d8b/modules/jdtls.py#L178-L202 and also change some of the other values toTrue(in case of the code example from above it is"generateConstructorsPromptSupport": True).Edit: Oh and I forgot to mention that LSP-jdtls is quite broken in general. To make it work with a recent JDK version you need to change the downloaded server version in
LSP-jdtls.sublime-settings, like{ "enabled": true, "version": "1.58.0", "settings": { "java.jdt.ls.java.home": "C:\\Program Files\\Java\\jdk-26.0.1" }, }I think we should probably also remove the custom implementation for
process_placeholdersinLSP/plugin/edit.py
Line 99 in 9105fb5