This project contains the source code for an IDE for navigating the algorithms in the JavaScript Specification, also known as ECMA-262. The IDE is based on JetBrains MPS.
Download the IDE binaries (see releases) and execute the nav262 application.
As an alternative to running the standalone IDE, you can build the project and run it from an MPS instance.
System requirements:
- JetBrains MPS 2024.3.1
Setup instructions:
- Clone this repository and open it inside MPS.
- Build both languages
ECMAScriptSpecificationLanguageandSpecNavigator. - Then, build
ImporterPlugin.
Depending on your operating systems, the shortcuts differ. For an updated list of shortcuts refer to the MPS documentation: https://www.jetbrains.com/help/mps/mastering-keyboard-shortcuts.html.
Prerequisite:
- You have obtained a version of ECMA-262 in the importable format, either:
- downloading pre-generated importable specs provided by us (see releases)
- or generating them yourself by using nav262-utils
Instructions:
- Open nav262 and create a new empty project
- Create a new solution in the project (you can choose any valid name)
- Click on the newly created solution to make sure it's the currently selected one
- Select Navigate > Go to Action > Import ECMA-262 specification from XML
- Select the folder containing the importable XML version of ECMA-262 generated by nav262-utils
Expected output:
-
The IDE displays a progress bar while importing the algorithms.
-
Once completed, the Logical View of your newly created solution should look as follows:
Once a version of ECMA-262 has been imported, you can browse the pseudocode of its algorithms. Using the MPS Logical View, expand the treeview up to an algorithm node (eg., ToInt32):
Besides common IDE functionality (eg., syntax colouring, renaming, highlighting, find usages), the section identifier of an algorithm (sec-toint32 in the example) can be Ctrl+clicked to open the original definition in the ECMA-262 specification webpage.
Inside an editor, place your cursor on different elements to access navigation-aware intentions.
Currently, the following intentions are supported:
- Algorithm Invocations:
- Toggle Inline: the body of the callee is projected under its invocation. It can be applied recursively to the body of the inlined algorithm. Inlinings are persisted between closing and reopening the IDE.
- Steps:
- Toggle Highlighting: highlights a step number.
- Hide/Unhide: it replaces a step, and all its substeps, with a grey line.
- Use verbose notation for ReturnIfAbrupt: turns
?shorthands toReturnIfAbruptcalls inside algorithmic steps - Toggle square brackets in record fields: turns fields like
[[field]]tofieldand vice versa
MPS Editor Hints documentation: https://www.jetbrains.com/help/mps/editor-hints.html
Currently, two custom inspectors are supported:
- For algorithms: shows the list of remarks associated to the algorithm.
- For steps: shows tags and remarks associated to the step. For hidden steps, the unhidden version of the step is also shown here.
MPS Inspector documentation: https://www.jetbrains.com/help/mps/mps-inspector.html
Here are some notable features provided out-of-the-box by MPS:
- Diff two root nodes by selecting them in the Logical View
- Show the Abstract Syntax Tree of a node inside the editor (known as "Reflective Editor")
A navigation task always takes an input specification document and produces an output copy, in which some structural units may have been removed, refactored, or decorated. A navigation task may also trigger IDE actions that will be applied to the output document. Lastly, it may also compute reports/statistics about the specification document.
-
Create an MPS model for navigation tasks: after importing an ECMA-262 version, create a new model named "navigations" under the same solution. For example, if you have just imported
es2025.spec, the navigations model fully qualified name would bees2025.navigations -
Right click on the navigations model, and select New > SpecNavigator > NavigationTask
Here is an example navigation task:
Heading:
- name: a name to identify the navigation task
- input-document: the name of an existing MPS model containing the input specification document to be navigated
- output-document: the name for the copy of the specification document that will be the output of the navigation task
The various blocks that can appear in a navigation are defined in the following sections.
When hitting the "Run" button, a navigation task performs the following operations in this order:
- Copy the input specification. From now on, all the transformations will be applied to this copy
- Filter algorithms based on composition of filtering templates in conjunctive normal form. Filtering templates can specify a condition over the heading of an algorithm, or a "matching" criterion between a step in the algorithm's body and a "pattern"
- Mark the algorithmic steps that match the patterns specified specified in the filtering templates (this operation is implicitly executed in the "filter" block)
- Decorate filtered algorithms and marked steps
- Execute code editor actions over the IDE and the output specification document
- report the results in tabular format, along with statistics computed on the output specification document
At the end of a navigation, an output model will be created, containing the resulting algorithms.
Note: a navigation task will also invalidate some of the references if the corresponding algorithms get filtered out by a navigation task. The IDE will signal these missing references with red underlined text.
A filter block accepts a boolean formula in conjunctive normal form. For example, the following SpecNavigation formula:
filter:
* A
* not B
* either
C
or
D
is equivalent to the boolean expression (A && !B && (C || D)).
A formula can contain disjunctions (either) and negations (not) of filtering templates.
To negate a condition, use the "Toggle Negation" intention.
The body-contains filtering template is the most complex and powerful filter. It allows to insert chunks of the ECMA-262 specification (steps, expressions, conditions, etc.) inside a navigation task. These chunks form a pattern that is tested again the body of an algorithm. The condition evaluates to true if any of the steps in the algorithm matches the pattern.
A pattern can contain wildcards for children, properties, and references. The following are valid wildcards:
- empty (abstract) nodes
- empty lists of nodes
- null references
- null string properties
- false boolean properties
Note: when defining a navigation task, the editor will interpret as errors the patterns that contain wildcards. However, navigation tasks will be able to correctly interpret the wilcards.
For example, the pattern
Let <null name> be Foo(<Expression>)
matches the step
Let x be Foo(bar)
and, more generally, every Let step containing a call to Foo with exactly 1 argument on the right hand side.
An optionally empty where clause can be used to define variables that can then be referenced by the pattern.
-
name-like: matches a regular expression against the algorithm name -
parameter-name-like: matches a regular expression against one or more of the algorithm parameters -
parameter-cardinality: matches the number of parameters of an algorithm
-
section-id-like: matches a regular expression against the ecmarkup section identifier of an algorithm -
section-number-like: matches a regular expression against the section number of an algorithm -
section-title-like: matches a regular expression against the enclosing section of an algorithm
-
has-hidden-step: returns true if any of the algorithm's steps is hidden -
has-highlighted-step: returns true if any of the algorithm's steps is highlighted with a given color -
has-remark/bookmark: matches a regular expression against the remarks/bookmarks of an algorithm
The optional decoration block accepts a list of transformations that will be applied sequentially to each algorithm received from the filtering.
-
add-bookmark/remark(-to-steps): add the given bookmark/remark to an algorithm, or to every marked step in the body of an algorithm -
remove-bookmark/remark(-from-steps): remove all bookmarks/remarks matching a given regular expression -
highlight/remove-highlighting: toggles highlighting all the marked steps -
hide: hides all the unmarked steps -
unhide: unhides all the steps, regardless whether they are marked or not
-
inline-algorithm-calls: executes an inlining of all the function calls in the output specification -
open-tabs: opens the given amountNote: opening a huge number of editor tabs in a short amount of time might freeze the UI
-
put-into-folder: rearranges the algorithms in the Logical View -
remove-unmatching-steps: removes every unmarked step from an algorithm -
rename-algorithm: applies a rename refactoring to an algorithm
The optional report block will generate an interactive read-only table linked both to the ECMA-262 webpage and to the output document generated by the navigation task:
- Ctrl+Click on a "Section ID" to open the definition in the ECMA-262 webpage
- Ctrl+Click on a "Function Name" to open the algorithm definition in the output specification within the IDE