Type-Aware JavaScript Code Intelligence

Article by: Peter Farland

Type-Aware JavaScript Code Intelligence

[A guest post from the LCVM team.] Howdy everyone! The LCVM team is a group of engineers at Adobe with expertise in designing languages, compilers and virtual machines. We’ve been closely following the Brackets project and were quite interested to discover Sprint 21 introduced JavaScript code hinting. This implementation does a good job of proposing code completions by tracking the identifiers and members in each scope. These hints can make coding more productive once a code base is established and the developer is reasonably familiar with the source.

When starting on a new JavaScript project, we believe type-aware code hints add additional value since the proposals focus on a type’s API and aid in the exploration of unfamiliar libraries. A few of us were looking at JavaScript type inference and thought that type-aware code intelligence could be used to improve the JavaScript code intelligence in Brackets.

So where do we find JavaScript type information? There are a number of methods to determine this information:

We can infer types by tracking assignments and doing some flow analysis:

function getLabel() {
    var label = "Brackets";
    return label;
var s = getLabel(); // s should be seen as a String

We can observe .prototype population:

function Product() {};
Product.prototype.clone = function() {};
var p = new Product();
p.  // we should hint clone() as a member of a Product

We can leverage AMD patterns like RequireJS which describe the API exported by a module:

var module = require("someModule");
module. // hint the exported members

We can analyze type annotations in JSDoc comments (such as those used by the Google Closure Compiler):

* Add two numbers.
* @param {number} a
* @param {number} b
* @return {number}
function sum(a, b) {}

Finally, we can hard-code pre-defined APIs of the language itself or from the execution environment (e.g. a particular browser or Node.JS).

We can do a lot once we have reasonable type information about a project. Our plan is to add better completion proposals for nested member expressions, function calls, an outline view, go-to-definition, and possibly limited or guided renaming.

These features are even more compelling once they work across multiple web languages. For example, once you know you are writing a JQuery selector you may decide to use DOM information from potential HTML consumers of your script, allowing you to hint relevant selectors.


While implementing the core JavaScript code intelligence logic we noticed Tern.JS, a new project from Marijn Haverbeke the creator of CodeMirror. We really like what Marijn has built and are exploring the possibility of using it as the basis of our JavaScript code intelligence engine. By contributing to a common code intelligence library, we hope to increase quality and get new features and extensions online sooner.

We welcome help from the Brackets community and would love to hear what other ideas you have for code intelligence! We are currently working in a fork of Brackets in github under the adobe-research organization. We’re still ironing out some issues but you can start playing with the feature now. We’re excited to be involved with the project and you can expect to see our first contributions land in Brackets Sprint 24.

Try it Out!

If you are the type who loves living on the bleeding edge, you can try out this new code intelligence in Brackets today.
Simply download our fork from GitHub:

  1. git clone https://github.com/adobe-research/brackets.git brackets-research
  2. cd brackets-research
  3. git submodule update --init

Then point the Brackets Sprint 23 shell at the new source code by holding SHIFT when you launch Brackets. You will be prompted to define a new location. Just locate the src/index.html and Brackets will load from there.

You can file issues at http://github.com/adobe-research/brackets/issues and provide feedback on our mailing list.

Leave a Reply

Your email address will not be published. Required fields are marked *