In the LSP spec, `additionalTextEdits` on a `CompletionItem` are described as follows: ```ts /** * An optional array of additional text edits that are applied when * selecting this completion. Edits must not overlap (including the same * insert position) with the main edit nor with themselves. * * Additional text edits should be used to change text unrelated to the * current cursor position (for example adding an import statement at the * top of the file if the completion item will insert an unqualified type). */ ``` Yet I've encountered at least one scenario in which two text edits want to insert at the same position. Imagine this setup: ```ts // ./src/foo.ts export function avarice() { // TODO } export function brillig () { // TODO } export function brilliant () { // TODO } ``` ```ts // ./index.ts import { avarice } from './src/foo' function main () { avarice() // Type `bril` here and wait for a completion menu to appear. } ``` This scenario is designed to invoke [asResolvedCompletionItem](https://github.com/typescript-language-server/typescript-language-server/blob/0a034dae6c777733f4c2f6d5b151c5ef781fb662/src/completion.ts#L350) so that `additionalTextEdits` get populated on a `CompletionItem`. Once I do this, I see two edits that ought to be a single `TextEdit`: ```js { "label": "brillig", "kind": 3, // … "detail": "Auto import from './src/foo'\nfunction brillig(): void", "additionalTextEdits": [ { "range": { "start": { "line": 1, "character": 9 }, "end": { "line": 1, "character": 9 } }, "newText": "," }, { "range": { "start": { "line": 1, "character": 9 }, "end": { "line": 1, "character": 9 } }, "newText": "\n brillig" } ] } ``` Since both of these edits want to insert at the same position, the only thing for a consumer of this `CompletionItem` to do is try to interpret the meaning. In this case, it's safe to assume that the two edits can be merged — but not in the general case. I'm not familiar enough with the underlying logic that leads these two `additionalTextEdits` to be separate instead of combined, but it seems like the obvious solution here is to combine them on the server side before resolving the `CompletionItem`. This is occurring in [Pulsar](https://pulsar-edit.dev/) using [pulsar-ide-typescript](https://web.pulsar-edit.dev/packages/pulsar-ide-typescript), but I can't identify any part of this that could be explained by incorrect behavior on the part of the language client.