Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

feature(rome_js_semantic): semantic model built from semantic events #2776

Merged
merged 12 commits into from
Jun 28, 2022

Conversation

xunilrj
Copy link
Contributor

@xunilrj xunilrj commented Jun 24, 2022

This PR creates the semantic model and allows navigation and querying the model.

The idea is to enable rules from #2743 to be implemented.

This is the code example:

function f(){let a = arguments[0]; let b = a + 1;}

The interesting part are:

scope navigation

let block_scope = arguments_reference.scope(&model);
let func_scope = block_scope.parent().unwrap();
let global_scope = func_scope.parent().unwrap();

assert!(global_scope.parent().is_none());

iterate scope bindings

let mut bindings = block_scope.bindings();

let binding0 = bindings.next().unwrap();
assert_eq!("a", binding0.syntax().text_trimmed());

let binding1 = bindings.next().unwrap();
assert_eq!("b", binding1.syntax().text_trimmed());

assert!(bindings.next().is_none());

get scope binding by name

let binding = block_scope.get_binding("arguments");
assert!(binding.is_none());

let binding = block_scope.get_binding("a").unwrap();
assert_eq!("a", binding.syntax().text_trimmed());

get declaration of a reference

let arguments_declaration = arguments_reference.declaration(&model);
assert!(arguments_declaration.is_none());

let a_declaration = a_reference.declaration(&model).unwrap();
assert_eq!("a", a_declaration.syntax().text_trimmed());

bindings

We do not allocate when saving bindings names, which is fine. But to enable this the event now needs to carry the SyntaxTokenText, which brings a green node with it.

This was not my initial idea.

I am fine with this for now, but if in the end no other solution appear, I will change SemanticEvents to return SyntaxNode, SynaxtToken instead.

SemanticModelData

The "heart" of the semantic model is inside the struct SemanticModelData. This struct lives behind an Arc that is shared with all semantic structs.



                             ┌───────────────────────┐
 ┌─────────────┐             │                       │
 │SemanticModel├──────┐      │   SemanticModelData   │
 └─────────────┘      │      │                       │
                      │      └─────────────▲─────────┘
 ┌─────┐              │                    │
 │Scope├────────┐     │      ┌──────┐      │
 └─────┘        │     │      │      │      │
                └─────┼──────► Arc  ├──────┘
 ┌───────┐            │      │      │
 │Binding├────────────┘      └──────┘
 └───────┘

rust-lapper

To allow any node/token to have a scope function, I am using interval trees (https://en.wikipedia.org/wiki/Interval_tree). In this case, using the crate https://github.com/sstadick/rust-lapper.

@xunilrj xunilrj temporarily deployed to aws June 24, 2022 14:01 Inactive
@github-actions
Copy link

github-actions bot commented Jun 24, 2022

@cloudflare-pages
Copy link

cloudflare-pages bot commented Jun 24, 2022

Deploying with  Cloudflare Pages  Cloudflare Pages

Latest commit: 31720fa
Status: ✅  Deploy successful!
Preview URL: https://6a0fe0d0.tools-8rn.pages.dev
Branch Preview URL: https://feature-semantic-model.tools-8rn.pages.dev

View logs

@xunilrj xunilrj temporarily deployed to aws June 24, 2022 15:07 Inactive
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 12:34 Inactive
@github-actions
Copy link

Parser conformance results on ubuntu-latest

js/262

Test result main count This PR count Difference
Total 45878 45878 0
Passed 44938 44938 0
Failed 940 940 0
Panics 0 0 0
Coverage 97.95% 97.95% 0.00%

jsx/babel

Test result main count This PR count Difference
Total 39 39 0
Passed 36 36 0
Failed 3 3 0
Panics 0 0 0
Coverage 92.31% 92.31% 0.00%

symbols/microsoft

Test result main count This PR count Difference
Total 5946 5946 0
Passed 388 388 0
Failed 5558 5558 0
Panics 0 0 0
Coverage 6.53% 6.53% 0.00%

ts/babel

Test result main count This PR count Difference
Total 588 588 0
Passed 519 519 0
Failed 69 69 0
Panics 0 0 0
Coverage 88.27% 88.27% 0.00%

ts/microsoft

Test result main count This PR count Difference
Total 16257 16257 0
Passed 12393 12393 0
Failed 3864 3864 0
Panics 0 0 0
Coverage 76.23% 76.23% 0.00%

@xunilrj xunilrj marked this pull request as ready for review June 27, 2022 12:51
crates/rome_js_semantic/Cargo.toml Show resolved Hide resolved
crates/rome_js_semantic/src/model.rs Outdated Show resolved Hide resolved
Comment on lines 102 to 104
pub struct SemanticModel {
data: Arc<SemanticModelData>,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should document this public object and explain the contents of data, because SemanticModelData is private at the moment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

crates/rome_js_semantic/src/model.rs Outdated Show resolved Hide resolved
type Item = Binding;

fn next(&mut self) -> Option<Self::Item> {
debug_assert!(self.id < self.data.scopes.len());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a string that explains the reason of this debug assertion?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

crates/rome_js_semantic/src/model.rs Outdated Show resolved Hide resolved
crates/rome_js_semantic/src/model.rs Outdated Show resolved Hide resolved
fn next(&mut self) -> Option<Self::Item> {
debug_assert!(self.id < self.data.scopes.len());

let result = match self.data.scopes[self.id].bindings.get(self.binding_index) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The debug assertion will disappear in production, but self.data.scopes[self.id] will stay. Is this operation safe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I pushed an explanation of why.

crates/rome_js_semantic/src/model.rs Outdated Show resolved Hide resolved
crates/rome_js_semantic/src/model.rs Outdated Show resolved Hide resolved
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 15:44 Inactive
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 16:26 Inactive
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 16:32 Inactive
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 16:34 Inactive
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 16:40 Inactive
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 16:43 Inactive
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 17:50 Inactive
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 17:53 Inactive
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 18:02 Inactive
@xunilrj xunilrj temporarily deployed to aws June 27, 2022 18:08 Inactive
}

/// Provides all information regarding a specific scope.
/// Allows navigation to parent and children scope and binding information.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Allows navigation to parent and children scope and binding information.
/// Allows navigation to parent and children scopes and binding information.

}

impl Scope {
/// Return this scope parent.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Return this scope parent.
/// Return the parent this scope.

}
}

/// Provides all information regarding to a specific binding.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Provides all information regarding to a specific binding.
/// Provides information of a specific binding.

@xunilrj xunilrj merged commit b9b4454 into main Jun 28, 2022
@xunilrj xunilrj deleted the feature/semantic-model branch June 28, 2022 08:46
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants