yioneko / vtsls

LSP wrapper for typescript extension of vscode
Other
374 stars 6 forks source link

vtsls does not return additionalTextEdits for auto imports #156

Closed mikebcbc closed 2 months ago

mikebcbc commented 2 months ago

Hi there! Ive been using vtsls and find it a fantastic alternative to tsserver. However, with completion plugins, vtsls does not return additionalTextEdits and therefore cannot auto import on completion. tsserver does.

I am using mini.completion and this is the following LSP response i am getting for both.

vtsls

-- textDocument/completion
{
  command = {
    arguments = { {
        cacheId = 1,
        index = 930,
        providerId = 2
      } },
    command = "_vtsls.completionCacheCommand",
    title = ""
  },
  commitCharacters = { ".", ",", ";", "(" },
  data = {
    cacheId = 1,
    index = 930,
    providerId = 2
  },
  insertTextFormat = 1,
  kind = 6,
  label = "getApi",
  labelDetails = {
    description = "./api"
  },
  sortText = "16",
  textEdit = {
    newText = "getApi",
    range = {
      ["end"] = {
        character = 3,
        line = 4
      },
      start = {
        character = 0,
        line = 4
      }
    }
  }
}

-- completionItem/resolve
{
  command = {
    arguments = { {
        cacheId = 1,
        index = 930,
        providerId = 2
      } },
    command = "_vtsls.completionCacheCommand",
    title = ""
  },
  commitCharacters = { ".", ",", ";", "(" },
  data = {
    cacheId = 1,
    index = 930,
    providerId = 2
  },
  detail = 'Add import from "./api"\n\nconst getApi: (req: Request, res: Response) => void',
  documentation = {
    kind = "markdown",
    value = "List of API examples.\n\n*@route* — GET /api"
  },
  insertTextFormat = 1,
  kind = 6,
  label = "getApi",
  labelDetails = {
    description = "./api"
  },
  sortText = "16",
  textEdit = {
    newText = "getApi",
    range = {
      ["end"] = {
        character = 1,
        line = 4
      },
      start = {
        character = 0,
        line = 4
      }
    }
  }
}

tsserver

-- textDocument/completion
{
  data = {
    cacheId = 926
  },
  detail = "./api",
  kind = 6,
  label = "getApi",
  sortText = "�16"
}

-- completionItem/resolve
{
  additionalTextEdits = { {
      newText = 'import { getApi } from "./api";\n',
      range = {
        ["end"] = {
          character = 0,
          line = 3
        },
        start = {
          character = 0,
          line = 3
        }
      }
    } },
  data = {
    entryNames = { {
        data = {
          exportMapKey = "6 1967 getApi ",
          exportName = "getApi",
          fileName = "/home/user/repos/TypeScript-Node-Starter/src/controllers/api.ts",
          moduleSpecifier = "./api"
        },
        name = "getApi",
        source = "./api"
      } },
    file = "/home/user/repos/TypeScript-Node-Starter/src/controllers/contact.ts",
    line = 5,
    offset = 2
  },
  detail = "Auto import from './api'\nconst getApi: (req: Request, res: Response) => void",
  documentation = {
    kind = "markdown",
    value = "List of API examples.\n\n*@route* — GET /api"
  },
  kind = 6,
  label = "getApi",
  sortText = "�16"
}

Any help would be appreciated! Thanks so much!

yioneko commented 2 months ago

The server triggers additionalTextEdits on server side by requiring client to execute the command _vtsls.completionCacheCommand after applying completion item and sending workspace/applyEdit request back to the client, so there is no content of additionalTextEdits in the completion response. https://github.com/microsoft/vscode/blob/73a2c100f6229b231d6b255e36d1789c25d92285/extensions/typescript-language-features/src/languageFeatures/completions.ts#L582-L595

Unfortunately, some clients like mini.completion and nvim builtin completion currently ignores the command field of completion item, making related features like auto-import not working on them.

A feasible approach here is to expose additionalTextEdits on server side by patching the vscode extension, also clients could fix this by corretly handle the command field in completion item.