In-Depth Linting of Your TypeScript While Coding
Last year we started development on SonarTS, a static code analyser for TypeScript. So far it has only been available in 2 flavors: as a SonarQube language plugin and as a TSLint extension. Since last week, I’m happy to say, there is another way to consume SonarTS: SonarLint. SonarLint is a peer product for SonarQube which enables analysis in IDEs. That means that code with a bug or code smell will be highlighted in the IDE as soon you type it!
You might say
Ok, and now what? What’s so special about it?
Let me explain that in couple of words
It is type-aware and it’s quick
If that’s not enough, let’s dive deeper.
In the TSLint documentation we described our SonarTS extension as follows
Bug-finding rules based on advanced code models to spot hard to find errors in TypeScript
What do we mean by advanced code models? One part of that is type information, which we use, for instance, to understand that the condition stack.length ≥ 0 makes no sense if stack has an Array type. You can’t be sure of that without type information, which you get for free when using the TypeScript API.
In fact, when I said that you get the type information for free, I fired from the hip. In order to have type information, the full project compilation should be performed, which takes time, as you might imagine. In your IDE it’s most probably the TypeScript server (aka tsserver) which is responsible for doing that in the background. That’s how you get nice tooltips about variable type and function signature. The TypeScript server encapsulates the TypeScript compiler and language services, allowing incremental (thus quick) recompilation.
So when we started adding support of TypeScript analysis to SonarLint we were sure that we had to have type information. But how to get it quickly?
Visual Studio Code Architecture
The first IDE we decided to support was VS Code. VS Code already runs tsserver to provide support for your TypeScript projects out of the box. It’s a separate node process using the JSON protocol to communicate with VS Code. What’s even nicer is that you can plug into this process to enrich the diagnostics produced by the native tsserver.
If you want to know more about it you can have a look at this talk at DotJS conference on how to write such plugins or at the official documentation from Microsoft. Note that in order to enable a plugin you need to mention it in your project’s tsconfig.json file.
SonarLint + SonarTS
Brainstorming about the solution architecture we kept several things in mind. It should:
- be fast
- easily extend to other IDEs
- not edit user files
Every time you launch SonarQube analysis of your TypeScript project the entire project is compiled from scratch. Obviously full recompilation would be unacceptably slow when triggered for every change in a file. So we quickly rejected the option of keeping the same approach inside the IDE.
We also considered writing a plugin for tsserver (see the section above). But that would imply in order SonarLint to work, the user should mention our plugin in his tsconfig.json, which we want to avoid. Further that would mean every future IDE we want to support should run tsserver under the hood, which we can’t guarantee.
So finally we ended up having our own instance of the TypeScript Language Service inside SonarTS. Now every time there is a change in a file we pass a new content to the language service instance. Then when the analyser (SonarTS) requests the type information, the language service incrementally recompiles the project to quickly provide up-to-date data about your code. Because this data is available almost instantly, you see the analysis results in VS Code at you type.
Is it the end?
Yep, it’s the end for this article :) but for sure it’s not for SonarLint and SonarTS. We are always happy to receive feedback from the users, so don’t hesitate to give them a try:
And to provide feedback you can send email to the Google Group for SonarLint email@example.com.
Thanks for reading!