vuejs / language-tools

⚡ High-performance Vue language tooling based-on Volar.js
https://marketplace.visualstudio.com/items?itemName=Vue.volar
MIT License
5.81k stars 394 forks source link

Support other JS preprocessors #3200

Closed phil294 closed 5 months ago

phil294 commented 1 year ago

Hi! This is a resurrection of #533 and a continuation of the conversation in #1687.

I am the author of CoffeeSense, the LSP/Extension for CoffeeScript. It would be great to support the usage of <script lang="coffee"> somehow.

I've read the blog post which contains this paragraph

If some of these language servers were based on Volar.js, we might have some way for them to decide to only activate one language server, and then share the features of the rest of the language servers to the activated one, so that in the end we would only need to run TypeScript Language Service in one language server instance instead of multiple language servers.

This is a good thought. It's a pretty ridiculous architecture to have every language server ship their own gigantic TS server... for example, CoffeeSense is actually a highly modified fork of Vetur, so it does exactly that right now.

However, I'm not sold on the approach that every supporting preprocessor needs to be completely reimplemented with volar technologies. So in 2021, I suggested

a LSP interface for custom preprocessors. Say, a configuration object

"preprocessors": {
  "coffee": {
    "lspPath": "/some/path"
  }
}

And now, whenever Volar encounters a unsupported lang type as <script lang="coffee">, it simply functions as a proxy between client and a spun-up third party lsp instance at /some/path.

Is this something you would consider supporting now? Using LSPs as the interface between Volar and a preprocessor instead of me having to rewrite the entire extension.

Still, if you insist on the latter, some guidance would be much appreciated! But I probably don't quite have the capacities to do this, as I am glad I even got CoffeeSense to work properly in the first place. Also, there will usually also be normal .coffee files in a coffee-based Vue project. So in the worst case scenario, we'll have FOUR tsservers running simultaneously...

As you also asked for a sample repro: Here is a working demo of Vue+coffee (vue-cli/webpack based). Start with yarn serve. App.vue contains some comments.

CoffeeSense language server is also available as a standalone module (just like Vetur), see https://github.com/phil294/coffeesense/blob/master/server/README.md

Edit: I now did the reverse, so it's possible to get coffee support in .vue files by setting "files.associations": { "*.vue": "coffeescript" }. CoffeeSense has its own "parser" for sfcs consisting of a single small regex. Pretty shitty solution though as this disables any other vue tooling like this one. Why only does VSCode not allow for multiple languages in the same file -_-

ofekd commented 6 months ago

I am interested in this as well. Is it easier to do now that v2 is out?

phil294 commented 6 months ago

I have no idea. But since it doesn't seem there is much going on here, at least in the case of Vue.js, I have now simply added bare-bones Vue support into my CoffeeScript extension instead of the other way round and it works fine for JS-exclusive stuff

ofekd commented 6 months ago

thanks @phil294 @johnsoncodehk could you give a few hints/point in the right direction?

so1ve commented 6 months ago

The current architecture doesn't allow us to do so. We heavily rely on TypeScript and its API to provide type-checking because we generate virtual TypeScript code from the template to make the syntax features work in templates.

ofekd commented 5 months ago

@so1ve Thank you for answering

johnsoncodehk commented 5 months ago

For this purpose, compileSFCScript hook has been added to the Plugin API. You can refer to https://github.com/vuejs/language-tools/blob/master/packages/language-plugin-pug/index.ts to implement the preprocessor for script block.

You need to convert coffee code to ts code, use ts.createSourceFile to create an AST and return a proxy object to return the mapped coffee code position when obtaining the pos/end attribute of the AST node.

Volar/Vue language tools v2 now does the opposite of what the blog mentioned. We integrate with tsserver through the TS plugin, allowing tsserver to take over the TS functions in the Vue file instead of the other way around.