Skip to content

Scope Directed Navigation And Scope Highlighting

Gabriel Tan edited this page May 3, 2020 · 3 revisions

Scope Directed Navigation & Scope Highlighting

Overview

This documents two features:

  1. Scope-directed navigation from any occurrence of an identifier to its declaration within the program.
  2. Scope-highlighting which highlights the scope in which the identifier is accessible in

Implementation

Scope-Directed Navigation

Implementing scope-directed navigation, the abstract syntax tree (AST) has to be traversed. This can be achieved easily by using the acorn-walk library, which allows us to:

  1. Find the declaration nodes we are interested in
  2. Perform a test on the node and add it to the list of results if it passes the test

The following outlines the steps taken to implement this feature:

  1. Parse the code
    • Using the existing parse method in js-slang to parse the code into the AST
    • Fallback to loose parsing if the code is syntactically incorrect
  2. Find the occurrence node object
    • This refers to the node that holds the occurrence of the declaration
    • Found by walking the tree and using the line and column where the user pressed the hotkey as a test
  3. Find the ancestors of the occurrence node
    • By traversing the AST from the start to the occurrence node
    • Reverse this list of nodes to start traversal from the nearest ancestor
  4. Find the declaration node in the ancestor node list
    • Traverse the reversed ancestor list and find all declarations that match this occurrence
    • Return the first match

Scope Highlighting and Scope Refactoring

This uses a simplified AST based on acorn-walk by introducing two new nodes:

  1. DefinitionNode
    • Represents any form of const, let or function definition
  2. BlockFrame
    • Normal blocks: everything within the curly braces
    • Conditionals, loops, and functions: include the related stuff outside of the curly braces.

This new tree offers a proper scoped view of the program. All the DefinitionNode objects within a BlockStatement are the variables that are declared in the scope of that block. These declarations will remain visible to all child blocks, unless the child block contains a DefinitionNode with the same name.

The following outlines the steps taken to implement this feature:

  1. Parse and generate simplified AST
  2. Find the Ancestor of the node, also called Parent Block. This is implemented using the API exposed by the scope to navigation team.
  3. Find inner blocks with overriding declarations. This is done via depth first search of the new tree.
  4. Exclude overriding blocks and compile list of ranges. This ranges will be used to highlight and refactor all the declarations at one go.

An option to enable acorn loose parsing is also available. This will enable us to generate the AST even when there are errors in the program, though this is not 100% foolproof.

Lastly, the scope highlighting and refactoring is run everytime the user stops typing, in order to enable the highlighting.

User Interaction Flow

Scope-Directed Navigation

Refactoring

refactoring

Scope Highlighting