Developer's Bumper

How I started to write JsThis, a Visual Studio Code extension

February 25, 2016

One day I read a story about how Microsoft open-sourced a great editor based on JavaScript. If you don’t know what’s going on, I’m talking about Visual Studio Code. It’s something what, at least at first glance, looks like another Sublime Text based clone. But it’s from Microsoft :) And because there is a lack of really good JavaScript editor at the market, I decided to give it a chance. It has a JS debugger, IntelliSense and everything what you need for JS development.

It has a support for other languages as well! Look at the overview.

First impression, first disappointment

I started it, opened a project (folder)…and…it looked quite cool. Simple, clean and what was the biggest surprise, it was quite fast.

Then I started to code…and the first and the biggest problem occured. Even though JS IntelliSense (Code Completion) works well for simple functions, variables, etc., it doesn’t work for this keyword at all. And it was the biggest problem for me, because the project I work on is prototype based. We use RequireJs modules and inside it we use this ES3 object pattern:

var MyConstructor = function () {
    this._myProperty = 'my property value';
};

MyConstructor.prototype.doSomething = function () {
    // do something
    console.log(this._myProperty);
};

return new MyConstructor();

So code completion for this._myProperty in doSomething(); method doesn’t work. I looked at the Extension Market Place whether there is some extension which could enable such IntelliSense, but unfortunatelly there is no such extension.

So I decided to write my own…and call it JsThis.

After few days I found a mention about a support of prototype style in version 0.10.8 notes, but suprisingly it didn’t mean, that it should work in 0.10.8 by default. One must enable it manually. It was clarified in a issue I filled.

Extension implementation process

First steps

It is very easy to start. Just look at the Extension web and follow both of prepared examples. There is one simple Hello World extension and one a bit more complex Word Count extension. They will guide you through the extension creation process and will show you some basics.

After reading these examples I was able to implement a basic CompletionItemProvider which was called in .js files when one invoked IntelliSense. I played with the API a bit and after few hours I had a prototype of my custom extension which collected this usages and suggested them in proper places.

IntelliSense - Code Completion

Why it swallows an errors?

What really annoyed me during the whole implementation was the fact that VSCode swallowed all the errors and exceptions which occured e.g. in third party libraries! Errors were just caught somewhere and the code execution continued like nothing happened. It wasn’t even logged to console! Why? Really don’t know…

Yes, there is a possibility to set the debugger to stop on Uncaught exceptions and All exceptions, but…you know. I don’t wanna stop. I just want to know that something went wrong. I want VSCode to just log it for me.

Didn’t find a suitable solution.

Travis integration should be simple, documentation says…

I wanted to try how difficult would it be to enable running tests on Travis. I followed the documentation and it seemed that it will be pretty simple. But actually it wasn’t.

Even though I followed the documentation properly and properly did everything what was described there, my jobs were failing. The problem was, that my project was not written in TypeScript, but in plain JavaScript.

The instructions assume, that the extension is written in TypeScript and that your code will be compiled before the test run. It automatically sets some paths to “compilation output folder” and it really can’t work. Plain JS code will not magically appear in that “output folder”, so then the test run fail.

What I had to do was to remove - npm run vscode:prepublish section from .travis.yml. That was the part which did the compilation and it ended up with a “Missing TypeScript” error.

The second thing I had to do was to add this part to .travis.yml:

env:
  - CODE_TESTS_PATH="$TRAVIS_BUILD_DIR/test"

which says where your test files are. Otherwise VSCode appends /test/out instead of just /test.

I filled an issue because I thing that it really needs to be documented somewhere.

The another problem was with defined VSCode engine version. That’s the version of API which is downloaded before tests start. The documentation says that you should use ^0.10.7. But I couldn’t. Why? To be honest, I really don’t know. When I set it then Travis started to complain and builds failed.

So I looked at some alredy existing extensions (written by Microsoft itself) and…they use 0.10.x! Ok, so I tried it…and it worked. Ok, it worked, but only on a Linux machine. Even though the documentation says that you can use:

os:
  - osx
  - linux

it didn’t work for me on OS X. So I temporarily commented that out and filled another issue. And, yes, it worked locally on my Mac ;)

After these changes tests were passing on Travis in Linux.

Conclusion

Here I described what I bumped into when I tried to work with and on the Visual Studo Code editor. I don’t think that it’s the best solution what you can find on Internet, it’s just in beta, but it’s definitely worth trying. It’s still under heavy developement, if you look at its GitHub issues, you can see how devs are working on it.

And what about my extension? I will keep working on it. Yes, it can happen that VSCode will have a native support for such features (I don’t know anything about this support, but prototype should work in 0.10.10), but at least I will learn something new :)

Thanks for reading!


Ondrej Brejla

"What I bumped into in my developer's life", by Ondrej Brejla