From f928b6df918f07576d902c656e4534485a9164fc Mon Sep 17 00:00:00 2001 From: Victorien Elvinger Date: Thu, 11 Jul 2024 18:07:14 +0200 Subject: [PATCH] refactor(js_semantic): minor changes --- .../src/semantic_model/binding.rs | 24 ++++---- .../src/semantic_model/builder.rs | 56 +++++++----------- .../src/semantic_model/closure.rs | 16 ++--- .../src/semantic_model/model.rs | 59 +++++++++++-------- .../src/semantic_model/reference.rs | 16 ++--- .../src/semantic_model/scope.rs | 25 +++----- 6 files changed, 91 insertions(+), 105 deletions(-) diff --git a/crates/biome_js_semantic/src/semantic_model/binding.rs b/crates/biome_js_semantic/src/semantic_model/binding.rs index 3625d51a8a84..614c22db8ef1 100644 --- a/crates/biome_js_semantic/src/semantic_model/binding.rs +++ b/crates/biome_js_semantic/src/semantic_model/binding.rs @@ -4,7 +4,7 @@ use biome_js_syntax::{binding_ext::AnyJsIdentifierBinding, TextRange, TsTypePara /// Internal type with all the semantic data of a specific binding #[derive(Debug)] pub(crate) struct SemanticModelBindingData { - pub id: BindingIndex, + pub id: BindingId, pub range: TextRange, pub references: Vec, } @@ -18,7 +18,7 @@ pub(crate) enum SemanticModelReferenceType { /// Internal type with all the semantic data of a specific reference #[derive(Debug)] pub(crate) struct SemanticModelReference { - pub(crate) index: ReferenceIndex, + pub(crate) id: ReferenceId, pub(crate) range: TextRange, pub(crate) ty: SemanticModelReferenceType, } @@ -45,19 +45,19 @@ pub type AllBindingWriteReferencesIter = /// Provides access to all semantic data of a specific binding. pub struct Binding { pub(crate) data: Rc, - pub(crate) index: BindingIndex, + pub(crate) id: BindingId, } impl std::fmt::Debug for Binding { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Binding").field("id", &self.index).finish() + f.debug_struct("Binding").field("id", &self.id).finish() } } impl Binding { /// Returns the scope of this binding pub fn scope(&self) -> Scope { - let binding = self.data.binding(self.index); + let binding = self.data.binding(self.id); let id = self.data.scope(&binding.range); //TODO declaration can have its scope id Scope { data: self.data.clone(), @@ -67,7 +67,7 @@ impl Binding { /// Returns the syntax node associated with this binding. pub fn syntax(&self) -> &JsSyntaxNode { - let binding = self.data.binding(self.index); + let binding = self.data.binding(self.id); &self.data.binding_node_by_start[&binding.range.start()] } @@ -81,38 +81,38 @@ impl Binding { /// Returns an iterator to all references of this binding. pub fn all_references(&self) -> AllBindingReferencesIter { - let binding = self.data.binding(self.index); + let binding = self.data.binding(self.id); let first = binding.references.first().map(|reference| Reference { data: self.data.clone(), - index: reference.index, + index: reference.id, }); std::iter::successors(first, Reference::find_next) } /// Returns an iterator to all reads references of this binding. pub fn all_reads(&self) -> AllBindingReadReferencesIter { - let binding = self.data.binding(self.index); + let binding = self.data.binding(self.id); let first = binding .references .iter() .find(|x| x.is_read()) .map(|reference| Reference { data: self.data.clone(), - index: reference.index, + index: reference.id, }); std::iter::successors(first, Reference::find_next_read) } /// Returns an iterator to all write references of this binding. pub fn all_writes(&self) -> AllBindingWriteReferencesIter { - let binding = self.data.binding(self.index); + let binding = self.data.binding(self.id); let first = binding .references .iter() .find(|x| x.is_write()) .map(|reference| Reference { data: self.data.clone(), - index: reference.index, + index: reference.id, }); std::iter::successors(first, Reference::find_next_write) } diff --git a/crates/biome_js_semantic/src/semantic_model/builder.rs b/crates/biome_js_semantic/src/semantic_model/builder.rs index 7725b877f69a..502e279a0134 100644 --- a/crates/biome_js_semantic/src/semantic_model/builder.rs +++ b/crates/biome_js_semantic/src/semantic_model/builder.rs @@ -20,9 +20,9 @@ pub struct SemanticModelBuilder { scope_hoisted_to_by_range: FxHashMap, bindings: Vec, /// maps a binding range start to its index inside SemanticModelBuilder::bindings vec - bindings_by_start: FxHashMap, + bindings_by_start: FxHashMap, /// maps a reference range start to its bindings. u32 points to SemanticModelBuilder::bindings vec - declared_at_by_start: FxHashMap, + declared_at_by_start: FxHashMap, exported: FxHashSet, unresolved_references: Vec, } @@ -170,9 +170,9 @@ impl SemanticModelBuilder { // event extractor debug_assert!((binding_scope_id.index()) < self.scopes.len()); - let binding_id = self.bindings.len() as u32; + let binding_id = BindingId::new(self.bindings.len()); self.bindings.push(SemanticModelBindingData { - id: binding_id.into(), + id: binding_id, range, references: vec![], }); @@ -202,20 +202,16 @@ impl SemanticModelBuilder { scope_id, } => { let binding_id = self.bindings_by_start[&declaration_at]; - let binding = &mut self.bindings[binding_id as usize]; - let reference_index = binding.references.len() as u32; - + let binding = &mut self.bindings[binding_id.index()]; + let reference_id = ReferenceId::new(binding.id, binding.references.len()); binding.references.push(SemanticModelReference { - index: (binding.id, reference_index).into(), + id: reference_id, range, ty: SemanticModelReferenceType::Read { hoisted: false }, }); let scope = &mut self.scopes[scope_id.index()]; - scope.read_references.push(SemanticModelScopeReference { - binding_id, - reference_id: reference_index, - }); + scope.read_references.push(reference_id); self.declared_at_by_start.insert(range.start(), binding_id); } @@ -225,20 +221,16 @@ impl SemanticModelBuilder { scope_id, } => { let binding_id = self.bindings_by_start[&declaration_at]; - let binding = &mut self.bindings[binding_id as usize]; - let reference_index = binding.references.len() as u32; - + let binding = &mut self.bindings[binding_id.index()]; + let reference_id = ReferenceId::new(binding.id, binding.references.len()); binding.references.push(SemanticModelReference { - index: (binding.id, reference_index).into(), + id: reference_id, range, ty: SemanticModelReferenceType::Read { hoisted: true }, }); let scope = &mut self.scopes[scope_id.index()]; - scope.read_references.push(SemanticModelScopeReference { - binding_id, - reference_id: reference_index, - }); + scope.read_references.push(reference_id); self.declared_at_by_start.insert(range.start(), binding_id); } @@ -248,20 +240,16 @@ impl SemanticModelBuilder { scope_id, } => { let binding_id = self.bindings_by_start[&declaration_at]; - let binding = &mut self.bindings[binding_id as usize]; - - let reference_index = binding.references.len() as u32; + let binding = &mut self.bindings[binding_id.index()]; + let reference_id = ReferenceId::new(binding.id, binding.references.len()); binding.references.push(SemanticModelReference { - index: (binding.id, reference_index).into(), + id: reference_id, range, ty: SemanticModelReferenceType::Write { hoisted: false }, }); let scope = &mut self.scopes[scope_id.index()]; - scope.read_references.push(SemanticModelScopeReference { - binding_id, - reference_id: reference_index, - }); + scope.read_references.push(reference_id); self.declared_at_by_start.insert(range.start(), binding_id); } @@ -271,20 +259,16 @@ impl SemanticModelBuilder { scope_id, } => { let binding_id = self.bindings_by_start[&declaration_at]; - let binding = &mut self.bindings[binding_id as usize]; - - let reference_index = binding.references.len() as u32; + let binding = &mut self.bindings[binding_id.index()]; + let reference_id = ReferenceId::new(binding.id, binding.references.len()); binding.references.push(SemanticModelReference { - index: (binding.id, reference_index).into(), + id: reference_id, range, ty: SemanticModelReferenceType::Write { hoisted: true }, }); let scope = &mut self.scopes[scope_id.index()]; - scope.read_references.push(SemanticModelScopeReference { - binding_id, - reference_id: reference_index, - }); + scope.read_references.push(reference_id); self.declared_at_by_start.insert(range.start(), binding_id); } diff --git a/crates/biome_js_semantic/src/semantic_model/closure.rs b/crates/biome_js_semantic/src/semantic_model/closure.rs index e85ca05c1397..de7034c2f51f 100644 --- a/crates/biome_js_semantic/src/semantic_model/closure.rs +++ b/crates/biome_js_semantic/src/semantic_model/closure.rs @@ -83,7 +83,7 @@ pub struct Capture { data: Rc, ty: CaptureType, node: JsSyntaxNode, - binding_id: BindingIndex, + binding_id: BindingId, } impl Capture { @@ -101,7 +101,7 @@ impl Capture { pub fn binding(&self) -> Binding { Binding { data: self.data.clone(), - index: self.binding_id, + id: self.binding_id, } } @@ -121,7 +121,7 @@ pub struct AllCapturesIter { data: Rc, closure_range: TextRange, scopes: Vec, - references: Vec, + references: Vec, } impl Iterator for AllCapturesIter { @@ -130,9 +130,9 @@ impl Iterator for AllCapturesIter { fn next(&mut self) -> Option { 'references: loop { while let Some(reference) = self.references.pop() { - let binding = &self.data.bindings[reference.binding_id as usize]; + let binding = &self.data.bindings[reference.binding_id().index()]; if self.closure_range.intersect(binding.range).is_none() { - let reference = &binding.references[reference.reference_id as usize]; + let reference = &binding.references[reference.index()]; return Some(Capture { data: self.data.clone(), node: self.data.binding_node_by_start[&reference.range.start()].clone(), // TODO change node to store the range @@ -150,9 +150,9 @@ impl Iterator for AllCapturesIter { } self.references.clear(); self.references - .extend(scope.read_references.iter().cloned()); + .extend(scope.read_references.iter().copied()); self.references - .extend(scope.write_references.iter().cloned()); + .extend(scope.write_references.iter().copied()); self.scopes.extend(scope.children.iter()); continue 'references; } @@ -268,7 +268,7 @@ impl Closure { let scopes = scope.children.clone(); let mut references = scope.read_references.clone(); - references.extend(scope.write_references.iter().cloned()); + references.extend(scope.write_references.iter().copied()); AllCapturesIter { data: self.data.clone(), diff --git a/crates/biome_js_semantic/src/semantic_model/model.rs b/crates/biome_js_semantic/src/semantic_model/model.rs index 32f23a46fdae..2740d45a99ad 100644 --- a/crates/biome_js_semantic/src/semantic_model/model.rs +++ b/crates/biome_js_semantic/src/semantic_model/model.rs @@ -1,27 +1,38 @@ use super::*; use biome_js_syntax::{AnyJsFunction, AnyJsRoot}; -#[derive(Copy, Clone, Debug)] -pub(crate) struct BindingIndex(u32); +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +pub(crate) struct BindingId(u32); -impl From for BindingIndex { - fn from(v: u32) -> Self { - BindingIndex(v) +impl BindingId { + pub(crate) fn new(index: usize) -> Self { + // SAFETY: We didn't handle files execedding `u32::MAX` bytes. + // Thus, it isn't possible to execedd `u32::MAX` bindings. + Self(index as u32) + } + + pub(crate) fn index(self) -> usize { + self.0 as usize } } #[derive(Copy, Clone, Debug)] -pub(crate) struct ReferenceIndex(u32, u32); +pub(crate) struct ReferenceId(BindingId, u32); -impl ReferenceIndex { - pub(crate) fn binding(&self) -> BindingIndex { - BindingIndex(self.0) +impl ReferenceId { + pub(crate) fn new(binding_id: BindingId, index: usize) -> Self { + // SAFETY: We didn't handle files execedding `u32::MAX` bytes. + // Thus, it isn't possible to execedd `u32::MAX` refernces. + Self(binding_id, index as u32) + } + + // Points to [SemanticModel]::bindings vec + pub(crate) fn binding_id(&self) -> BindingId { + self.0 } -} -impl From<(BindingIndex, u32)> for ReferenceIndex { - fn from((binding_index, index): (BindingIndex, u32)) -> Self { - ReferenceIndex(binding_index.0, index) + pub(crate) fn index(self) -> usize { + self.1 as usize } } @@ -67,11 +78,11 @@ pub(crate) struct SemanticModelData { pub(crate) binding_node_by_start: FxHashMap, pub(crate) scope_node_by_range: FxHashMap, // Maps any range start in the code to its bindings (usize points to bindings vec) - pub(crate) declared_at_by_start: FxHashMap, + pub(crate) declared_at_by_start: FxHashMap, // List of all the declarations pub(crate) bindings: Vec, // Index bindings by range start - pub(crate) bindings_by_start: FxHashMap, + pub(crate) bindings_by_start: FxHashMap, // All bindings that were exported pub(crate) exported: FxHashSet, /// All references that could not be resolved @@ -81,17 +92,17 @@ pub(crate) struct SemanticModelData { } impl SemanticModelData { - pub(crate) fn binding(&self, index: BindingIndex) -> &SemanticModelBindingData { + pub(crate) fn binding(&self, index: BindingId) -> &SemanticModelBindingData { &self.bindings[index.0 as usize] } - pub(crate) fn reference(&self, index: ReferenceIndex) -> &SemanticModelReference { - let binding = &self.bindings[index.0 as usize]; + pub(crate) fn reference(&self, index: ReferenceId) -> &SemanticModelReference { + let binding = &self.bindings[index.0.index()]; &binding.references[index.1 as usize] } - pub(crate) fn next_reference(&self, index: ReferenceIndex) -> Option<&SemanticModelReference> { - let binding = &self.bindings[index.0 as usize]; + pub(crate) fn next_reference(&self, index: ReferenceId) -> Option<&SemanticModelReference> { + let binding = &self.bindings[index.0.index()]; binding.references.get(index.1 as usize + 1) } @@ -207,7 +218,7 @@ impl SemanticModel { pub fn all_bindings(&self) -> impl Iterator + '_ { self.data.bindings.iter().map(|x| Binding { data: self.data.clone(), - index: x.id, + id: x.id, }) } @@ -240,7 +251,7 @@ impl SemanticModel { let id = *self.data.declared_at_by_start.get(&range.start())?; Some(Binding { data: self.data.clone(), - index: (id).into(), + id, }) } @@ -358,10 +369,10 @@ impl SemanticModel { pub fn as_binding(&self, binding: &impl IsBindingAstNode) -> Binding { let range = binding.syntax().text_trimmed_range(); - let id = &self.data.bindings_by_start[&range.start()]; + let id = self.data.bindings_by_start[&range.start()]; Binding { data: self.data.clone(), - index: (*id).into(), + id, } } diff --git a/crates/biome_js_semantic/src/semantic_model/reference.rs b/crates/biome_js_semantic/src/semantic_model/reference.rs index 3ede034aed1c..03d183cc7592 100644 --- a/crates/biome_js_semantic/src/semantic_model/reference.rs +++ b/crates/biome_js_semantic/src/semantic_model/reference.rs @@ -7,7 +7,7 @@ use std::rc::Rc; #[derive(Debug)] pub struct Reference { pub(crate) data: Rc, - pub(crate) index: ReferenceIndex, + pub(crate) index: ReferenceId, } impl Reference { @@ -15,7 +15,7 @@ impl Reference { let reference = self.data.next_reference(self.index)?; Some(Reference { data: self.data.clone(), - index: reference.index, + index: reference.id, }) } @@ -26,10 +26,10 @@ impl Reference { if reference.is_read() { return Some(Reference { data: self.data.clone(), - index: reference.index, + index: reference.id, }); } else { - index = reference.index; + index = reference.id; } } @@ -43,10 +43,10 @@ impl Reference { if reference.is_write() { return Some(Reference { data: self.data.clone(), - index: reference.index, + index: reference.id, }); } else { - index = reference.index; + index = reference.id; } } @@ -77,7 +77,7 @@ impl Reference { pub fn binding(&self) -> Option { Some(Binding { data: self.data.clone(), - index: self.index.binding(), + id: self.index.binding_id(), }) } @@ -125,7 +125,7 @@ impl Reference { #[derive(Debug)] pub struct FunctionCall { pub(crate) data: Rc, - pub(crate) index: ReferenceIndex, + pub(crate) index: ReferenceId, } impl FunctionCall { diff --git a/crates/biome_js_semantic/src/semantic_model/scope.rs b/crates/biome_js_semantic/src/semantic_model/scope.rs index ff41014548f1..3dc1daa409f0 100644 --- a/crates/biome_js_semantic/src/semantic_model/scope.rs +++ b/crates/biome_js_semantic/src/semantic_model/scope.rs @@ -13,13 +13,13 @@ pub(crate) struct SemanticModelScopeData { // All children scope of this scope pub(crate) children: Vec, // All bindings of this scope (points to SemanticModelData::bindings) - pub(crate) bindings: Vec, + pub(crate) bindings: Vec, // Map pointing to the [bindings] vec of each bindings by its name - pub(crate) bindings_by_name: FxHashMap, + pub(crate) bindings_by_name: FxHashMap, // All read references of a scope - pub(crate) read_references: Vec, + pub(crate) read_references: Vec, // All write references of a scope - pub(crate) write_references: Vec, + pub(crate) write_references: Vec, // Identify if this scope is from a closure or not pub(crate) is_closure: bool, } @@ -88,11 +88,11 @@ impl Scope { let data = &self.data.scopes[self.id.index()]; let name = name.as_ref(); - let id = data.bindings_by_name.get(name)?; + let id = *data.bindings_by_name.get(name)?; Some(Binding { data: self.data.clone(), - index: (*id).into(), + id, }) } @@ -123,15 +123,6 @@ impl Scope { } } -/// Represents a reference inside a scope. -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub(crate) struct SemanticModelScopeReference { - // Points to [SemanticModel]::bindings vec - pub(crate) binding_id: u32, - // Points do [SemanticModelBinding]::references vec - pub(crate) reference_id: u32, -} - /// Iterate all descendents scopes of the specified scope in breadth-first order. pub struct ScopeDescendentsIter { data: Rc, @@ -174,7 +165,7 @@ impl Iterator for ScopeBindingsIter { // it was created by [Scope::bindings] method. debug_assert!((self.scope_id.index()) < self.data.scopes.len()); - let id = self.data.scopes[self.scope_id.index()] + let id = *self.data.scopes[self.scope_id.index()] .bindings .get(self.binding_index as usize)?; @@ -182,7 +173,7 @@ impl Iterator for ScopeBindingsIter { Some(Binding { data: self.data.clone(), - index: (*id).into(), + id, }) } }