-
Notifications
You must be signed in to change notification settings - Fork 168
Scope Directed Navigation And Scope Highlighting
This documents two features:
- Scope-directed navigation from any occurrence of an identifier to its declaration within the program.
- Scope-highlighting which highlights the scope in which the identifier is accessible in
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:
- Find the declaration nodes we are interested in
- 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:
- 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
- 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
- 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
- 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
This uses a simplified AST based on acorn-walk by introducing two new nodes:
- DefinitionNode
- Represents any form of const, let or function definition
- 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:
- Parse and generate simplified AST
- Find the Ancestor of the node, also called Parent Block. This is implemented using the API exposed by the scope to navigation team.
- Find inner blocks with overriding declarations. This is done via depth first search of the new tree.
- 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.