Skip to content

Deprecate process_placeholders argument for apply_text_edits function - #2941

Merged
jwortmann merged 2 commits into
sublimelsp:mainfrom
jwortmann:deprecate-process_placeholders
May 31, 2026
Merged

jwortmann merged 2 commits into
sublimelsp:mainfrom
jwortmann:deprecate-process_placeholders

Conversation

@jwortmann

Copy link
Copy Markdown
Member

Users of this function (LSP-rust-analyzer ?) can convert the TextEdit with placeholder(s) into a SnippetTextEdit instead, which is part of the LSP 3.18 specs. It's pretty simple; just copy the newText into snippet['value'] and also add snippet['kind'] = "snippet" - for an example see sublimelsp/LSP-Tinymist@70e6a50

Then we can remove the LspApplyDocumentEditCommand.

@rchl

rchl commented May 30, 2026 •

Copy link
Copy Markdown
Member

Note that the spec-compliant implementation doesn't work as well because it only processes topmost edit as a snippet. In rust-analyzer case the edits are for example:

[
  {
    "range": {
      "start": {
        "line": 0,
        "character": 3
      },
      "end": {
        "line": 0,
        "character": 6
      }
    },
    "snippet": {
      "kind": "snippet",
      "value": "main"
    }
  },
  {
    "range": {
      "start": {
        "line": 1,
        "character": 13
      },
      "end": {
        "line": 1,
        "character": 29
      }
    },
    "snippet": {
      "kind": "snippet",
      "value": "\"Hello, world!\""
    }
  },
  {
    "range": {
      "start": {
        "line": 4,
        "character": 0
      },
      "end": {
        "line": 6,
        "character": 1
      }
    },
    "snippet": {
      "kind": "snippet",
      "value": "fn two$0() {\n    println!(\"Hello, world1!\");\n}"
    }
  }
]

in practice only the last one is a snippet but I guess that doesn't really matter that other are also snippets for this issue.

The effect of that is that the cursor location is not updated the way it should be.

@rchl

rchl commented May 30, 2026

Copy link
Copy Markdown
Member

Spec says:

For the active file, only one snippet can specify a cursor position. In case there are multiple snippets defining a cursor position for a given URI, it is up to the client to decide the end position of the cursor.

So it doesn't say to only process the topmost one.

I've even worked around RA saying that all edits are snippets (it uses insertTextFormat for that) and ended up with just a single snippet but it's still not processed:

[
  {
    "range": {
      "start": {
        "line": 0,
        "character": 3
      },
      "end": {
        "line": 0,
        "character": 6
      }
    },
    "newText": "main",
    "insertTextFormat": 2
  },
  {
    "range": {
      "start": {
        "line": 1,
        "character": 13
      },
      "end": {
        "line": 1,
        "character": 29
      }
    },
    "newText": "\"Hello, world!\"",
    "insertTextFormat": 2
  },
  {
    "range": {
      "start": {
        "line": 4,
        "character": 0
      },
      "end": {
        "line": 6,
        "character": 1
      }
    },
    "snippet": {
      "kind": "snippet",
      "value": "fn tw$0o() {\n    println!(\"Hello, world1!\");\n}"
    }
  }
]

@jwortmann

Copy link
Copy Markdown
Member Author

I'll think about how we could handle that. Currently we only process the "last" (i.e. topmost) edit as snippet because that is an easy way to ensure that there is only one snippet. Also we need to check that it still works correctly if we first insert a snippet via insert_snippet command, and after that do additional edits to the view (for other TextEdits if the snippet is not the topmost edit).

@jwortmann

Copy link
Copy Markdown
Member Author

I created PR #2944, could you check whether that fixes the case from rust-analyzer?

@jwortmann
jwortmann merged commit 1a67628 into sublimelsp:main May 31, 2026
8 checks passed
@jwortmann
jwortmann deleted the deprecate-process_placeholders branch May 31, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants