How WebStorm Works: Completion for JavaScript Libraries

One of the essential features of WebStorm’s editor is code completion. The way it is implemented in WebStorm is that it takes all JavaScript files in the project and goes through them, adding functions and methods to an internal index used for code completion suggestions. The index is automatically updated whenever existing files are changed or new files are added.

completion

JSDoc, used for documenting code, also plays an important role in making your coding experience better. It powers WebStorm autocompletion with additional details about parameters and their types.

jsdoc

But what if you have only minified files included, or if all the libraries are loaded dynamically? In this case it would be impossible for the IDE to statically analyse them and provide the necessary level of code completion when you press Ctrl+Space, or to resolve functions and methods you use.

This is where we introduce the concept (or mechanism) of External libraries that we use in WebStorm.

External libraries

External libraries are files explicitly added to project’s index to be used only in enhancing coding assistance (i.e. code completion, syntax highlighting, navigation, and documentation lookup). They are not to be edited in the scope of this project.

To make this concept clearer, let’s see how it works on a real project. Here is a simple project using the Famous framework for UI (same as on the screenshots above).

As we can see, some framework-specific methods are not resolved. This happens because the file famous.js is in not in the project, but is hosted on CDN.

notresolved

To make WebStorm aware of the functions and methods of the library without adding its source code to the project, we need to set it as an External JavaScript library.

There are several ways to do this:

  • Download the library from the CDN link

The quick-fix ‘Download library’ (call up with Alt+Enter) loads the file from the CDN link into the WebStorm cache (but not in your project).

downloadlib

You can go to Preferences | JavaScript | Libraries to load the list of all libraries that could power code completion for your project and enable specific aspects of code completion that you need.

listoflibs

  • Add file or folder

Another way to add libraries to this list is manually. This option is useful when the library is stored locally on your computer, but not in the project folder.

Select Preferences | JavaScript | Libraries and click Add. Enter the library name and the path to the library file or folder. If you select Global visibility level, you’ll be able to enable this library in your other projects.

addnewlib

Additionally, you can specify the path to library’s/framework’s documentation. This URL will be opened when you press Shift+F1 (Show external documentation) on methods from the library.

Important note: If your library files are in the project folder, it’s worth adding them to the list of JavaScript libraries as described above: as a result, code inspections will be disabled for these files, and project-wide Code quality analysis will become faster.

Consider node_modules folder as an example. We would like to have code completion for the modules and keep them in the project, but there is no need for us to run inspections against these files. That is why this folder should be marked as a library. In fact, WebStorm does that automatically.

nodemodules

Node.js Core modules as External library

Node.js core modules (like http or fs) are another example where External libraries are used. WebStorm suggests downloading the sources and marks them as Global libraries.

nodecore

Once you’ve downloaded the sources, you can enable coding assistance for functions and methods from Node.js core modules in any of your projects. To do that, go to Preferences | JavaScript | Libraries and select the checkbox:

nodecoreenable

Using TypeScript community stubs (TypeScript definition files)

WebStorm provides one more workaround for adding coding assistance for some popular libraries, frameworks and modules when you don’t have the source code available in your project. It allows you to download DefinitelyTyped stubs. These definition files for libraries and frameworks are added to the list of your project’s External libraries, thus enhancing code completion.

tsdef

Develop with pleasure!
JetBrains WebStorm Team

About Ekaterina Prigara

Ekaterina Prigara is WebStorm product marketing manager at JetBrains. She's passionate about new technologies, UX and coffee.
This entry was posted in Cool Feature, Tutorials and tagged , . Bookmark the permalink.

11 Responses to How WebStorm Works: Completion for JavaScript Libraries

  1. Sergey says:

    Very nice article! Couple of things to mention: 1) Webstorm will mark properties of unknown data structure as unresolved – that typically happen in ajax callbacks, so it might be a good idea to use @typefed or custom definition (*.d.ts) file to describe that structure 2) If you have a folder with minified sources it might be better to exclude this folder altogether from Directories dialog and then install library (or better community stubs).
    Community stubs are definitely better because they contain type information, while it is not guarantied that unminified javascript files have jsdoc comments. Why is it important to have type information? Well there is another amazing part about webstorm – if it can guess type it will provide you type validation support, just like your favorite IDE for strictly typed language. Why would you care about types in javascript when you’re so smart to know how they are converted internally? Because we are all human beings and can make an error, so why not to catch that error as soon as possible then debug all the way back through callstack? Sometimes type validation in webstorm might fail due to more complex type definition of nested jsdoc structure, so if you would like to have better support please vote for these issues:
    http://youtrack.jetbrains.com/issue/WEB-12553
    http://youtrack.jetbrains.com/issue/WEB-12554
    http://youtrack.jetbrains.com/issue/WEB-11553
    http://youtrack.jetbrains.com/issue/WEB-11760

    Thanks

  2. maros says:

    How did you achieve autocompletion like in first screenshot?

    My team uses AMD import, just like you do, but there is never any type information attached to the variables: the proposed autocompletions start with __defineGetter__, __proto__, etc.

    In order to get autocompletion like you do, I would need to explicitly add a comment like:
    /*Engine.prototype*/ Engine

    We do use typescript definition files, but they are nearly useless when combined with AMD. Any help would be most welcome

    • Konstantin Ulitin says:

      Hi, Maros.
      To get relevant completion of imported AMD module, WebStorm have to correctly resolve path to module corresponding to function parameter. That path is now considered as file path, I’ve created issue WEB-12622 for this.
      Completion in Ekaterina’s example is working because we have heuristics to add type from parameter name matching to AMD module, and luckily the internal definition of Engine has such a name too.
      By the way, WebStorm understands that /*Engine.prototype.constructor*/ notation specifies that a symbol has a constuctor type (to get static methods completion). Please see WEB-10214.

      • maros says:

        It would be nice to know some basic rules in order to utilize them in our project.

        I have noticed that underscore.js gets proper autocompletion when imported through AMD, JQuery doesn’t. In fact, the autocompletion for JQuery imported through AMD strongly proposes methods of type HTMLElement.prototype.

        If I try to use $ as a variable outside of AMD, the type gets resolved perfectly well.

        Similarly, when I tried to add a Typescript file with this content:

        Then importing the module doesn’t offer any autocompletion.

        At the moment the type resolution works like a black box, sometimes it does, sometimes it doesn’t, without any clue as to what might be wrong. Revealing a few basic tips on how to get it up and rolling would be great.

  3. Pipo says:

    It would be great to use .d.ts files for better auto-completion, but use .jsdocs from original .js file and use the original .js fiel for “go to declaration” instead of jumping into the .d.ts.

    • Pipo says:

      Better example:

      Say I use “angular.module” in my source file.
      - Without any library I have just bad or no auto-completion for if I type “angular”. I can’t use “go to declaration” on “angular” (not found) and wrong “go to declaration” on “module” (Node.js globals).
      - With angular.js as a library I get better auto-completion if I type “angular”. I can use “go to declaration” on “angular” and wrong “go to declaration” on “module” (Node.js globals and angular.js).
      - With angular.d.ts as a library I get the best auto-completion if I type “angular”. The “go to declaration” on “angular” is wrong (2 places in the angular.d.ts itself) and the “go to declaration” on “module” is wrong (angular.d.ts). (Wrong in the sense that I want the real declaration in the source code, not the interface.)
      - With angular.d.ts and angular.js as a library it behaves just like only with the .d.ts. But it would be great if it would mix the best out of both worlds.

    • Konstantin Ulitin says:

      Good suggestion! Could you please create a feature request in our tracker?

  4. Daniel says:

    I’ve noticed with libraries like q, it doesn’t show the code complete suggestions, and the ones that are used show as “Unresolved function or method”, do you know why that is?

    • Ekaterina Prigara says:

      Some libraries are implemented in a very dynamic manner, so it’s very complicated for WebStorm to provide coding assistance for them. Downloading TypeScript community stubs for these libraries solve the problem.

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">