mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
135 lines
4.2 KiB
Rust
135 lines
4.2 KiB
Rust
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
use std::cell::{Cell, RefCell};
|
|
use std::collections::HashMap;
|
|
use std::rc::Rc;
|
|
|
|
use react_estree::ESTreeNode;
|
|
use react_semantic_analysis::{DeclarationId, ScopeManager, ScopeView};
|
|
|
|
use crate::{
|
|
BlockId, Features, Identifier, IdentifierData, IdentifierId, MutableRange, Registry, Type,
|
|
TypeVarId,
|
|
};
|
|
|
|
/// Stores all the contextual information about the top-level React function being
|
|
/// compiled. Environments may not be reused between React functions, but *are*
|
|
/// shared between each React function and all its nested function expressions.
|
|
#[derive(Debug)]
|
|
pub struct Environment {
|
|
/// The set of enabled compiler features
|
|
pub features: Features,
|
|
|
|
/// Definitions for functions, hooks, and types which are used to compile more
|
|
/// precisely
|
|
#[allow(dead_code)]
|
|
registry: Registry,
|
|
|
|
/// The next available block index
|
|
next_block_id: Cell<BlockId>,
|
|
|
|
/// The next available identifier id
|
|
next_identifier_id: Cell<IdentifierId>,
|
|
|
|
analysis: ScopeManager,
|
|
|
|
next_type_var_id: Cell<TypeVarId>,
|
|
|
|
bindings: Rc<RefCell<HashMap<DeclarationId, Identifier>>>,
|
|
}
|
|
|
|
impl Environment {
|
|
pub fn new(features: Features, registry: Registry, analysis: ScopeManager) -> Self {
|
|
Self {
|
|
features,
|
|
registry,
|
|
analysis,
|
|
next_block_id: Cell::new(BlockId(0)),
|
|
next_identifier_id: Cell::new(IdentifierId(0)),
|
|
next_type_var_id: Cell::new(TypeVarId(0)),
|
|
bindings: Default::default(),
|
|
}
|
|
}
|
|
|
|
/// Get the next available block id
|
|
pub fn next_block_id(&self) -> BlockId {
|
|
let id = self.next_block_id.get();
|
|
self.next_block_id.set(id.next());
|
|
id
|
|
}
|
|
|
|
/// Get the next available identifier id
|
|
pub fn next_identifier_id(&self) -> IdentifierId {
|
|
let id = self.next_identifier_id.get();
|
|
self.next_identifier_id.set(id.next());
|
|
id
|
|
}
|
|
|
|
/// Get the next available type var
|
|
pub fn next_type_var_id(&self) -> TypeVarId {
|
|
let id = self.next_type_var_id.get();
|
|
self.next_type_var_id.set(id.next());
|
|
id
|
|
}
|
|
|
|
pub fn resolve_variable_declaration<T: ESTreeNode>(
|
|
&self,
|
|
node: &T,
|
|
name: &str,
|
|
) -> Option<Identifier> {
|
|
let declaration = self.analysis.node_declaration(node)?;
|
|
let mut bindings = self.bindings.borrow_mut();
|
|
if let Some(identifier) = bindings.get(&declaration.id) {
|
|
Some(identifier.clone())
|
|
} else {
|
|
let id = self.next_identifier_id();
|
|
let identifier = Identifier {
|
|
id,
|
|
name: Some(name.to_string()),
|
|
data: Rc::new(RefCell::new(IdentifierData {
|
|
mutable_range: Default::default(),
|
|
scope: None,
|
|
type_: Type::Var(self.next_type_var_id()),
|
|
})),
|
|
};
|
|
bindings.insert(declaration.id, identifier.clone());
|
|
Some(identifier)
|
|
}
|
|
}
|
|
|
|
pub fn resolve_variable_reference<T: ESTreeNode>(&self, node: &T) -> Option<Identifier> {
|
|
let reference = self.analysis.node_reference(node)?;
|
|
let bindings = self.bindings.borrow();
|
|
let declaration = self.analysis.declaration(reference.declaration);
|
|
let identifier = bindings.get(&declaration.id)?;
|
|
Some(identifier.clone())
|
|
}
|
|
|
|
pub fn resolve_declaration_id(&self, id: DeclarationId) -> Option<Identifier> {
|
|
let bindings = self.bindings.borrow();
|
|
let identifier = bindings.get(&id)?;
|
|
Some(identifier.clone())
|
|
}
|
|
|
|
pub fn scope<T: ESTreeNode>(&self, node: &T) -> Option<ScopeView<'_>> {
|
|
self.analysis.node_scope_view(node)
|
|
}
|
|
|
|
pub fn new_temporary(&self) -> Identifier {
|
|
Identifier {
|
|
id: self.next_identifier_id(),
|
|
name: None,
|
|
data: Rc::new(RefCell::new(IdentifierData {
|
|
mutable_range: MutableRange::new(),
|
|
scope: None,
|
|
type_: Type::Var(self.next_type_var_id()),
|
|
})),
|
|
}
|
|
}
|
|
}
|