Hack WebStorm to Introspect Quasar Framework Components

in #quasarframework5 years ago (edited)

TL;DR: Follow these instructions and you will get autocomplete, quick-doc and snippets for Quasar 1.0 in IntelliJ IDE's like Webstorm

by Matyáš Racek
repo: https://github.com/panstromek/quasar-ide-helper

Before

After

For a while, Quasar integration into WebStorm or any other IDEA editor hasn't been ideal. Quasar is an amazing framework but it's setup is just "too smart" for IDEA to handle correctly. You get a lot of unknown HTML tag errors all over the templates, missing autocomplete for components and a lot of false-positive warnings.

This is a story about my journey to solve this problem.

Introduction

I'm really passionate about IDEs. I am part of the new generation of developers, who grew up on superior IDE support. I started coding in Java, and if you use IntelliJ, you know how good the developer experience is for coding Java in it. It's that kind of work where you half-type, half-generate. IDEA can do a whole lot of code transformations for you, and moreover, it can guarantee that those transformations are valid. This is very useful when you are learning, because you often don't remember the correct syntax - if you are clever with autocomplete and intentions, IDEA will generate the correct syntax for you.

Being used to all of this, it was a harsh realization when I transitioned into web development. JavaScript is not a good language for static analysis, so IDEA is often lost when trying to help you. JavaScript is just too dynamic. There is so much stuff that could potentially happen at runtime, that if you ask for autocomplete, IDEA will often give up and just offer you Everything (or nothing).

Quasar

Quasar is no exception to that. It is an amazing framework that made my life easier in many ways, but it has pretty complex build pipeline and is based on Vue, which doesn't have ideal support in IDEA, yet. It's pretty good, it keeps getting better, but we are still not quite there.

Now you might think that the right thing to do would be to create an IntelliJ plugin for Quasar. And you are right, some Vue frameworks already went this route. But this is not as easy as it sounds. I already tried to do something with Vue.js plugin (it's open source), but I couldn't even set up a build. The IntelliJ platform is pretty complex on its own, there are not that many tutorials or even really documentation. Writing a plugin requires understanding of the internal structure of the IDE. When I started a new plugin project, I just got empty folder with few config files and I didn't even know where to start.

Early Scripting

I took a different route. I hacked. When I started working with Quasar, I tried to setup the IDE somehow, but I didn't succeed. There is an old feature request for IntelliJ support in Quasar repo, where @jpgilchrist describes how to trick IntelliJ with fake webpack config. It would autocomplete at least tags, but the issue stayed open. I just moved on and forgot about this, mostly accepting the situation until recently.

Quasar switched to a new documentation system for v1.0. Part of it is API documentation, which is actually generated from JSON files that are stored alongside the source code. I immediately recognized an opportunity of this system, but I haven't really seen an easy option until I found an older forum post where @hwb noted that IntelliJ will autocomplete components if you register them with Vue.component call. So if you create a fake javascript file where you import and register all Quasar components, IDEA will pick them up and autocomplete. @hwb even provided a bash script to do this automatically. I was sad that I hadn't found this post earlier.

The Hack

I immediately rushed to try it and it worked - I quickly found out how to generate bunch of definitions for Quasar components using API JSON files. Furthermore, I could include comments with JSDoc annotations for parameters and descriptions - all from JSON api files. The original approach from the post worked well, but It wouldn't correctly recognize mixins, so IDE would sometimes hint you incorrectly. With new Quasar API, I could make it correct and also provide quick documentation lookup.

You can also use ctrl+b or ctrl+click to go to definition. It will take you to the generated file wit h all documented props.

But there was a catch. There always is. I generated the file with bunch of inline calls like this: Vue.prototype('QBtn', {...}). Immediately after I generated the file, IDEA picked it up and provided autocomplete for component names, but it didn't work for their props. And now the twist - it started working when I edited the generated file.

This took me a great amount of time to troubleshoot until I finally submitted bug on IntelliJ issues. I tried to find if this was about line endings, or some encoding... nothing worked. I tried to invalidate caches, restart. I tried edit the generated output, copypasting it. Didn't work. The problem kept reappearing again and again so I had to edit the generated file every time I opened a project.

After submitting the bug, I found out that if I split the component declaration and registration, it will work correctly, but it was pretty frustrating experience. You can vote for the issue here.

Prototype injections

After I found out how to resolve components, I started to explore if I could do more. JSON API files are there even for Quasar plugins, so I could also generate a fake JavaScript file that injects them into Vue prototype. That would make them easily visible for IDE.

Vue.prototype.$q = {
    fullscreen :{
     // fullscreen methods
    }
}

This kinda works, but there is a catch. IDEA doesn't recognize this very well, so if you type this.$q. in Vue component, it will give you that classic "Everything" autocomplete.

This is probably because IDEA can't tell that this code will be evaluated in the context of Vue instance. It's just an Object in the end. This is where I spent few days trying to find out which combination of jsdoc comments, typescript definition and component code will work the best.

This seems like it should work, right?

/**
 * @type {Vue}
 */
export default {

}

... and no, it doesn't.

So I tried this:

/**
 * @type {Vue}
 */
const c = {

}
export default const c

This make the autocomplete work! Yeey!
... but it will break autocomplete for this component. It will also disable Vue snippets and other Vue related Features in IDE.

Same goes for this construct:

export default Vue.extend({

})

Then I found out about @this JSDoc annotation. It will annotate what this is in the context of next function. Which means that the next code will work well:

export default {
    methods: {
        /** @this {Vue} */
        method() {
            this.$q. // Here you get autocomplete correct!
        }
    }
}

I tried to add @this before component definition but it doesn't help either. Seems like this is the best option for now. But it's pretty wordy, so it's good just if you want to find out what you can use. I am still trying to find out if there is a better way.

You will also get all injections when you type Vue.$q., but that is not the correct usage.

How to get this into Quasar?

Here comes the interesting part. Quasar 1.0 comes with a brand new app-extension system. This allows you to extract common functionalities and use them in multiple projects, even publishing them for others to use. You can hook into a build process, extend webpack configuration at runtime, add dependencies into package.json, add folders, code and more.

The most powerful feature in my opinion is being able to add custom commands. So I wrapped my generators in a simple extension that adds two commands to Quasar CLI. Now you can add extension with

$ cd your-quasar-1-project
$ quasar ext --add ide-helper

and run

$ quasar run ide-helper generate

This will generate .quasar-ide-helper folder with component definitions that are easy for IDEA to index.

Conclusion

This was my journey about providing autocomplete for Quasar components and injections - but there is more. You will notice that ide-helper can also generate Snippets (Live Templates) and directives, but I want to save it for next time.

There are still a lot of features that can be unlocked by this kind of IDE hacking. I'm looking forward to provide even better development experience and let you enjoy Quasar as much as possible. If you want to help this effort, feel free to open an issue on github and contribute with your hack, too.

Proof of work done

This has been a guest post by Quasar Staff member Matyáš Racek.
https://github.com/panstromek

More information

If you need more information about Quasar, here are a few links that you can check out for your consideration:

Sort:  

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Chat with us on Discord.

[utopian-moderator]

Those aren't lines of "dead code" - it is actually the hack at work. :)

Thank you for your review, @helo! Keep up the good work!

Hi @quasarframework!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server


This project is being supported by @Fundition the next-generation, decentralized, peer-to-peer crowdfunding and collaboration platform, built on the Steem blockchain.

Read the full details of Fundition Fund program
Learn more about Fundition by reading our purplepaper
work_on_progess.gif

steemitf.pngtwitterf.pngyoutubef.pngfacebookf.pnginstaf.pngdiscordf.png
Join a community with heart based giving at its core
Fundition is a non profit project, by supporting it with delegation you are supporting 200+ projects.
50SP100SP200SP500SP1000SP2000SP5000SP10000SP

Hey, @quasarframework!

Thanks for contributing on Utopian.
Congratulations! Your contribution was Staff Picked to receive a maximum vote for the development category on Utopian for being of significant value to the project and the open source community.

We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Coin Marketplace

STEEM 0.26
TRX 0.11
JST 0.033
BTC 64383.21
ETH 3098.60
USDT 1.00
SBD 3.89