ocaml-lsp icon indicating copy to clipboard operation
ocaml-lsp copied to clipboard

Incorrect completion range start position for polymorphic variants

Open TKristof09 opened this issue 10 months ago • 0 comments

When triggering completion just after the ` character of a polymorphic variant's name, the LSP returns completion items where the start and end positions are identical and equal to the position after the `. This causes the client to interpret the completion item as simply inserting text instead of also replacing the already typed ` character upon resolving the completion.

Example

Consider the following code:

type t = [ `T1 | `T2 ]

let x : t = `

Triggering autocomplete after the backtick character (at character 13) results in the wrong behaviour with the LSP returning completion items with ranges where start = end = 13. I would expect the returned items to have a start = 12 and end = 13 so that the completion client can correctly replace the ` character when resolving the completion edit.

If taking the same code, but triggering completion after having typed another character it works correctly.

type t = [ `T1 | `T2 ]

let x : t = `T

In this case triggering completion after the T character (character 14) the LSP returns completion items with ranges where start = 12 and end = 14 which leads to the client being able to correctly interpret the text edit required for resolving the autocomplete.

Ocaml-lsp version:

1.20.1

Logs:

LSP logs from my neovim for the incorrect example

It also returns a lot of irrelevant completion items (which makes the textdocument/completion response too long for github so I'll attach it in a file). However, all the returned completion items share the same incorrect range.

log_wrong.txt

[DEBUG][2024-12-18 18:10:42] ...m/lsp/client.lua:678	"LSP[ocamllsp]"	"client.request"	1	"textDocument/completion"	{  context = {    triggerKind = 1  },  position = {    character = 13,    line = 2  },  textDocument = {    uri = "file:///home/kristof/ocaml-test/main.ml"  }}	<function 1>	1

... (see file for response)

[DEBUG][2024-12-18 18:10:42] ...m/lsp/client.lua:678	"LSP[ocamllsp]"	"client.request"	1	"completionItem/resolve"	{  data = {    position = {      character = 13,      line = 2    },    textDocument = {      uri = "file:///home/kristof/ocaml-test/main.ml"    }  },  deprecated = false,  detail = "`T1",  kind = 20,  label = "`T1",  sortText = "0000",  textEdit = {    newText = "`T1",    range = {      ["end"] = {        character = 13,        line = 2      },      start = {        character = 13,        line = 2      }    }  }}	<function 1>	1
[DEBUG][2024-12-18 18:10:42] .../vim/lsp/rpc.lua:286	"rpc.send"	{  id = 12,  jsonrpc = "2.0",  method = "completionItem/resolve",  params = {    data = {      position = {        character = 13,        line = 2      },      textDocument = {        uri = "file:///home/kristof/ocaml-test/main.ml"      }    },    deprecated = false,    detail = "`T1",    kind = 20,    label = "`T1",    sortText = "0000",    textEdit = {      newText = "`T1",      range = {        ["end"] = {          character = 13,          line = 2        },        start = {          character = 13,          line = 2        }      }    }  }}
[DEBUG][2024-12-18 18:10:42] .../vim/lsp/rpc.lua:408	"rpc.receive"	{  id = 12,  jsonrpc = "2.0",  result = {    deprecated = false,    detail = "`T1",    kind = 20,    label = "`T1",    sortText = "0000",    textEdit = {      newText = "`T1",      range = {        ["end"] = {          character = 13,          line = 2        },        start = {          character = 13,          line = 2        }      }    }  }}

LSP logs for the correct (second) example:

[DEBUG][2024-12-18 18:08:38] .../vim/lsp/rpc.lua:286	"rpc.send"	{  id = 11,  jsonrpc = "2.0",  method = "textDocument/completion",  params = {    context = {      triggerKind = 1    },    position = {      character = 14,      line = 2    },    textDocument = {      uri = "file:///home/kristof/ocaml-test/main.ml"    }  }}
[DEBUG][2024-12-18 18:08:38] .../vim/lsp/rpc.lua:408	"rpc.receive"	{  id = 11,  jsonrpc = "2.0",  result = {    isIncomplete = false,    items = { {        data = {          position = {            character = 14,            line = 2          },          textDocument = {            uri = "file:///home/kristof/ocaml-test/main.ml"          }        },        deprecated = false,        detail = "`T1",        kind = 20,        label = "`T1",        sortText = "0000",        textEdit = {          newText = "`T1",          range = {            ["end"] = {              character = 14,              line = 2            },            start = {              character = 12,              line = 2            }          }        }      }, {        data = {          position = {            character = 14,            line = 2          },          textDocument = {            uri = "file:///home/kristof/ocaml-test/main.ml"          }        },        deprecated = false,        detail = "`T2",        kind = 20,        label = "`T2",        sortText = "0001",        textEdit = {          newText = "`T2",          range = {            ["end"] = {              character = 14,              line = 2            },            start = {              character = 12,              line = 2            }          }        }      } }  }}
[DEBUG][2024-12-18 18:08:38] ...m/lsp/client.lua:678	"LSP[ocamllsp]"	"client.request"	1	"completionItem/resolve"	{  data = {    position = {      character = 14,      line = 2    },    textDocument = {      uri = "file:///home/kristof/ocaml-test/main.ml"    }  },  deprecated = false,  detail = "`T1",  kind = 20,  label = "`T1",  sortText = "0000",  textEdit = {    newText = "`T1",    range = {      ["end"] = {        character = 14,        line = 2      },      start = {        character = 12,        line = 2      }    }  }}	<function 1>	1
[DEBUG][2024-12-18 18:08:38] .../vim/lsp/rpc.lua:286	"rpc.send"	{  id = 12,  jsonrpc = "2.0",  method = "completionItem/resolve",  params = {    data = {      position = {        character = 14,        line = 2      },      textDocument = {        uri = "file:///home/kristof/ocaml-test/main.ml"      }    },    deprecated = false,    detail = "`T1",    kind = 20,    label = "`T1",    sortText = "0000",    textEdit = {      newText = "`T1",      range = {        ["end"] = {          character = 14,          line = 2        },        start = {          character = 12,          line = 2        }      }    }  }}
[DEBUG][2024-12-18 18:08:38] .../vim/lsp/rpc.lua:408	"rpc.receive"	{  id = 12,  jsonrpc = "2.0",  result = {    deprecated = false,    detail = "`T1",    kind = 20,    label = "`T1",    sortText = "0000",    textEdit = {      newText = "`T1",      range = {        ["end"] = {          character = 14,          line = 2        },        start = {          character = 12,          line = 2        }      }    }  }}

TKristof09 avatar Dec 18 '24 17:12 TKristof09