Building the Dataform VS Code extension | Dataform

Building the Dataform VS Code extension

How we made our own extension for Visual Studio Code.

picture of author

George McGowan on September 22, 2020

Currently, our site contains the only IDE that helps you to write SQLX code, offering syntax highlighting and automatic code completion. We wanted to make sure that our open source community benefits from the same tools, and so today we're announcing the release of a SQLX extension for Visual Studio Code.


  • SQLX file syntax highlighting
  • Project compilation on save
  • Cmd + click inside a ref function to view the referenced file


  • Install the Dataform CLI locally: npm i -g @dataform/cli
  • Download our extension here
  • Open a project containing a SQLX file
  • You'll see project compilation notifications each time you save a file

Our process:

(If you’re not interested in the details of how I developed the extension, then there's no need to read further. Otherwise, read on!)

I decided to make this extension as part of a hackweek project, during which we dedicate a week towards something different from our normal day jobs. In reality, this ended up taking two hackweeks to be ready for launch. Here is the final source code.


Initially I just wanted to get syntax highlighting working. Fortunately we already had highlighting that worked out of the box, because we use the Monaco editor in our website IDE. So the main thing was to try to get an extension working in VS Code. For this, I largely followed the docs, which were pretty comprehensive.

One difference between us and the docs is that we use the Bazel build system instead of the standard webpack build. This just meant that I had to include some extra boilerplate to compile our typescript into javascript for the extension.

I simply created a folder containing the recommended start files (below) with some boilerplate code in extension.ts and ran code --extensionDevelopmentPath: ./vscode once I’d compiled my .ts files.

This got me the syntax highlighting straight away!


Later, I realised that we could go a little further than simple syntax highlighting. In our web IDE, we compile the code you write on the fly and show you any errors in real-time. And in the context of the extension, we have access to your whole project. So we should be able to compile the whole thing in the same way.

However, this would require a more complicated VS Code extension. As I understand it, extensions have a Client and a Server architecture. At the time, I was just using the Client, which is fine for simple things like syntax highlighting. However, if I wanted to do things like interface with the user’s file system or suggest definitions, then I would need to use a Language Server. The server and client would communicate with each other by subscribing to events such as onRequest(“compile). So I took some more boilerplate, added it to my server.ts, and managed to get some messages being sent between the client and server.

Then I was ready to implement the project compilation. There were two options I could’ve pursued. The first would be to rebuild a lot of what we already have inside our website backend and run the compilation step inside the language server. The second would be to run our open source CLI inside the language server as a simple terminal process, and save the result of that.

I chose the second option, as it was much easier to get started and I wouldn’t have to rebuild so much code. Fortunately, we already had code very similar to this elsewhere, so I was able to ~~copy~~ leverage much of the code from there. It ended up looking something like this:

  connection.onRequest("compile", async () => {
    const compileResult = await getProcessResult(exec("dataform compile --json"));
    if (compileResult?.compilationError) {
      connection.sendNotification("error", compilationError.message);
    } else {
      connection.sendNotification("success", "Project compiled successfully");


Once this was done, and I had compilation notifications popping up using VS Code’s notifications API, I realised that I could go further yet! Given the contents of a ref function, and a compiled project, I should be able to determine the file name that the ref was referring to.

This required me using the Definitions API, which essentially requires you to create an onDefinition handler in your server, and return a Definition object if the piece of code being requested has a valid definition. Once I ironed out a few bugs, the code looked roughly like this:

    (params): HandlerResult<Location, void> => {
      const linkedFileName = retrieveLinkedFileName(params.textDocument.uri);
      const fileString = `${WORKSPACE_ROOT_FOLDER}/${linkedFileName}`;
      return {
        uri: fileString,
        range: {
          start: { line: 0, character: 0 },
          end: { line: 1, character: 0 }
      } as Location;


Now I had syntax highlighting, compilation and jump-to-definition working and I decided to publish the first draft of the extension. Mostly this was as described in the docs. I used the vsce package to properly compile a .vsix file ready to be used. There was a bit of work to get the bazel build putting the compiled code in the correct place, but once that was worked out I was able to install the package itself in my VS code extension library and verify that it worked.

The final step was creating an account in Azure, and uploading our extension to the VS Code extension library. I was pleased to see that the vsce package command nicely cuts some details out of the package.json and adds it to the extension library site:

And as a bonus, VS Code automatically detects that .SQLX files have an extension now, and offers to show off our extension!


Hopefully I’ve given you a taste for VS Code extension development. If you’re interested in trying your own extension, I’d highly recommend it as being easy to get started and easy to distribute your code.

This extension is still in Alpha, and no doubt there will be various bugs. Please let us know if you find any and let us know what feature you’d like to see next!

More content from Dataform

Dataform is joining Google Cloud


Dataform is joining Google Cloud

Today we're excited to announce that we've joined Google Cloud. Over the course of the past several months, our partnership with Google Cloud has deepened and we believe that our new combined efforts can make our customers and partners even more successful.
Learn more
Using Javascript to Create an Acquisition Funnel Dataset illustration

Using Javascript to Create an Acquisition Funnel Dataset

How to use a combination of SQL and Javascript to create an acquisition funnel dataset.
Learn more
How to add a new warehouse adapter to Dataform illustration

How to add a new warehouse adapter to Dataform

I recently wrote a Presto adapter for Dataform during a week long quarterly hackathon. Here's a guide on how I'd do it again.
Learn more

Learn more about the Dataform data modeling platform

Dataform brings open source tooling, best practices, and software engineering inspired workflows to advanced data teams that are seeking to scale, enabling you to deliver reliable data to your entire organization.