简体   繁体   中英

Developing a Custom TypeScript language service plugin in VSCode

I am trying to develop a TSserver plugin in VSCode but I can not get the server to load my plugin

I have tried setting the path in tsconfig.json to be a local path and a path to node_modules

This is a very minimal project that I think should run the plugin https://github.com/Spensaur-K/minimal-tsserver-plugin

The server doesn't load the plugin. It doesn't log messages in the plugin or crash if I put an error in the plugin

The only way I have been able to make a custom plugin load in TS Server while being served from a file:

  1. Enable workspace configuration using local TypeScript:

npm i typescript

package.json :

{
  "dependencies": {
    "typescript": "^4.2.3"
  }
}

.vscode/settings.json

{
  "typescript.tsdk": "./node_modules/typescript/lib",
  // ~/.config/Code/logs/**/tsserver.log
  "typescript.tsserver.log": "verbose",
  "typescript.enablePromptUseWorkspaceTsdk": true
}

Using local TypeScript is important, because TypeScript will look for the plugin by package name in node_modules in the working directory of TS Server and up. If attempted to use global TypeScript ( /usr/local/lib/node_modules/typescript/lib ), the working directory of tsserver will be thereabout and your plugin will be nowhere near that path.

Using verbose seems optional, because all of the plugin-loading related messages in the TS Server seem to be info level, but I enabled it to make sure I don't miss absolutely anything as debugging this is contrived enough as it is: to view the logs, press Cmd+Shift+P when in a TS/JS file and Select TypeScript: Show Open TS Server Log.

Enabling the prompt for workplace TypeScript version is also optional, it helps to not forget to do it manually as you'd otherwise have to by going Cmd+Shift+P when in a TS/JS file and selecting TypeScript: Select TypeScript Version and switching that to the workspace version configured in .vscode/settings.json .

  1. Create your plugin in node_modules/plugin in your project directory

This is the suboptimal part, I hate to have the source code for the plugin in node_modules , but I have not found the way to move it out, because TS Server's working directory is now in node_modules of your project directory and the next directory up is the node_directory of the parent of your project directory and so on. I don't know how to make it so that your plugin code does not need to be in this chain.

node_modules/plugin/package.json :

{
  "name": "plugin"
}

node_modules/plugin/index.js :

module.exports = function init(modules) {
  function create(info) {
    const service = info.languageService;
    info.project.projectService.logger.info(
      "Started custom plugin"
    );
    return service;
  }

  return { create };
}

I don't think it is possible to author the plugin in TypeScript directly without having to transpile.

  1. Configure TS Server to use your plugin and restart it

tsconfig.json :

{
  "compilerOptions": {
    "plugins": [
      {
        "name": "plugin"
      }
    ]
  }
}

The name cannot be a file path ( https://github.com/microsoft/TypeScript/issues/18623 ) so we refer to the plugin by a Node package name here and thus all the shenanigans with placing the plugin source code within the node_modules chain leading up the to the TS Server working directory.

To restart TS Server, go to a TS/JS file and press Cmd+Shift+P and select TypeScript: Restart TS Server. Then press Cmd+Shift+P again and select TypeScript: Open TS Server Log.

You should see something like this then ( stands for your project directory):

Info 24   [09:59:19.919] Enabling plugin plugin from candidate paths: /…/node_modules/typescript/lib/tsserver.js/../../..,/Applications/Visual Studio Code.app/Contents/Resources/app/extensions/typescript-language-features
Info 25   [09:59:19.919] Loading plugin from /…/node_modules/typescript/lib/tsserver.js/../../.. (resolved to /…/node_modules/node_modules)
Info 26   [09:59:19.923] Started custom plugin
Info 27   [09:59:19.923] Plugin validation succeded

If anyone knows how to make the plugin load from your project directory directly and not from node_modules or how to use the global TypeScript install instead of a local one, I'm all ears!

Edit:

One improvement that can be made is to change node_modules/plugin/index.js to this:

module.exports = require('../../plugin.js');

And move the code that was there previously to plugin.js in your project directory. I'd prefer there was a way to do all this without any node_modules directory in my project directory, but alas.

I have opened a TypeScript bug repor for this: https://github.com/microsoft/TypeScript/issues/43124

TS Server plugins under node_modules are only loaded if you are using a workspace version of typescript and the plugin is listed in the tsconfig.json for your project. Using a relative path for the plugin may also not work .

To run the example:

  1. Install minimal-tsserver-plugin under node_modules
  2. Use the workspace version of typescript
  3. In your tsconfig, have:

     { "compilerOptions": { "plugins": [ { "name": "minimal-tsserver-plugin" } ] } }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM