Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ast): add SymbolId and ReferenceId #755

Merged
merged 12 commits into from
Aug 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 39 additions & 5 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use std::fmt;
use std::{cell::Cell, fmt, hash::Hash};

use oxc_allocator::{Box, Vec};
use oxc_span::{Atom, SourceType, Span};
use oxc_syntax::operator::{
AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator, UpdateOperator,
use oxc_syntax::{
operator::{
AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator, UpdateOperator,
},
reference::ReferenceId,
symbol::SymbolId,
};
#[cfg(feature = "serde")]
use serde::Serialize;
Expand Down Expand Up @@ -254,21 +258,51 @@ pub struct IdentifierName {
}

/// Identifier Reference
#[derive(Debug, Clone, Hash)]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
pub struct IdentifierReference {
#[cfg_attr(feature = "serde", serde(flatten))]
pub span: Span,
pub name: Atom,
#[cfg_attr(feature = "serde", serde(skip))]
pub reference_id: Cell<Option<ReferenceId>>,
}

impl Hash for IdentifierReference {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.span.hash(state);
self.name.hash(state);
}
}

impl IdentifierReference {
pub fn new(name: Atom, span: Span) -> Self {
Self { name, span, reference_id: Cell::default() }
}
}

/// Binding Identifier
#[derive(Debug, Clone, Hash)]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
pub struct BindingIdentifier {
#[cfg_attr(feature = "serde", serde(flatten))]
pub span: Span,
pub name: Atom,
#[cfg_attr(feature = "serde", serde(skip))]
pub symbol_id: Cell<Option<SymbolId>>,
}

impl Hash for BindingIdentifier {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.span.hash(state);
self.name.hash(state);
}
}

impl BindingIdentifier {
pub fn new(name: Atom, span: Span) -> Self {
Self { name, span, symbol_id: Cell::default() }
}
}

/// Label Identifier
Expand Down
7 changes: 4 additions & 3 deletions crates/oxc_ast_lower/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ impl<'a> AstLower<'a> {
self.hir.with_statement(stmt.span, object, body)
}

#[allow(clippy::too_many_lines)]
fn lower_expression(&mut self, expr: &ast::Expression<'a>) -> hir::Expression<'a> {
ensure_sufficient_stack(|| {
match expr {
Expand Down Expand Up @@ -444,15 +445,15 @@ impl<'a> AstLower<'a> {
ast::Expression::JSXElement(elem) => {
// TODO: implement JSX
let ident = self.lower_identifier_reference(
&ast::IdentifierReference { span: elem.span, name: "undefined".into() },
&ast::IdentifierReference::new("undefined".into(), elem.span),
ReferenceFlag::Read,
);
self.hir.identifier_reference_expression(ident)
}
ast::Expression::JSXFragment(elem) => {
// TODO: implement JSX
let ident = self.lower_identifier_reference(
&ast::IdentifierReference { span: elem.span, name: "undefined".into() },
&ast::IdentifierReference::new("undefined".into(), elem.span),
ReferenceFlag::Read,
);
self.hir.identifier_reference_expression(ident)
Expand Down Expand Up @@ -850,7 +851,7 @@ impl<'a> AstLower<'a> {
expr => {
// return undefined because this is invalid syntax
let ident = self.lower_identifier_reference(
&ast::IdentifierReference { span: expr.span(), name: "undefined".into() },
&ast::IdentifierReference::new("undefined".into(), expr.span()),
ReferenceFlag::Write,
);
self.hir.assignment_target_identifier(ident)
Expand Down
3 changes: 1 addition & 2 deletions crates/oxc_parser/src/js/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ impl<'a> Parser<'a> {
// ^ BindingIdentifier
if let PropertyKey::Identifier(ident) = &key {
shorthand = true;
let binding_identifier =
BindingIdentifier { span: ident.span, name: ident.name.clone() };
let binding_identifier = BindingIdentifier::new(ident.name.clone(), ident.span);
let identifier = self.ast.binding_identifier(binding_identifier);
let left = self.ast.binding_pattern(identifier, None, false);
self.parse_initializer(span, left)?
Expand Down
6 changes: 4 additions & 2 deletions crates/oxc_parser/src/js/expression.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::cell::Cell;

use oxc_allocator::Box;
use oxc_ast::ast::*;
use oxc_diagnostics::Result;
Expand Down Expand Up @@ -55,7 +57,7 @@ impl<'a> Parser<'a> {
}
let (span, name) = self.parse_identifier_kind(Kind::Ident);
self.check_identifier(span, &name);
Ok(IdentifierReference { span, name })
Ok(IdentifierReference { span, name, reference_id: Cell::default() })
}

/// `BindingIdentifier` : Identifier
Expand All @@ -65,7 +67,7 @@ impl<'a> Parser<'a> {
}
let (span, name) = self.parse_identifier_kind(Kind::Ident);
self.check_identifier(span, &name);
Ok(BindingIdentifier { span, name })
Ok(BindingIdentifier { span, name, symbol_id: Cell::default() })
}

pub(crate) fn parse_label_identifier(&mut self) -> Result<LabelIdentifier> {
Expand Down
4 changes: 3 additions & 1 deletion crates/oxc_parser/src/js/function.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::cell::Cell;

use oxc_allocator::Box;
use oxc_ast::{ast::*, AstBuilder};
use oxc_diagnostics::Result;
Expand Down Expand Up @@ -332,7 +334,7 @@ impl<'a> Parser<'a> {
let id = self.cur_kind().is_binding_identifier().then(|| {
let (span, name) = self.parse_identifier_kind(Kind::Ident);
self.check_identifier(span, &name);
BindingIdentifier { span, name }
BindingIdentifier { span, name, symbol_id: Cell::default() }
});
self.ctx = ctx;

Expand Down
3 changes: 2 additions & 1 deletion crates/oxc_parser/src/js/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ impl<'a> CoverGrammar<'a, ObjectProperty<'a>> for AssignmentTargetProperty<'a> {
if property.shorthand {
let binding = match property.key {
PropertyKey::Identifier(ident) => {
IdentifierReference { span: ident.span, name: ident.unbox().name }
let ident = ident.unbox();
IdentifierReference::new(ident.name, ident.span)
}
_ => return Err(p.unexpected()),
};
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_parser/src/ts/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ impl<'a> Parser<'a> {
let span = self.start_span();
let (ident_span, name) = self.parse_identifier_kind(Kind::This);
let type_annotation = self.parse_ts_type_annotation()?;
let kind = self.ast.binding_identifier(BindingIdentifier { span: ident_span, name });
let kind = self.ast.binding_identifier(BindingIdentifier::new(name, ident_span));
let binding = self.ast.binding_pattern(kind, type_annotation, /* optional */ false);
Ok(self.ast.formal_parameter(
self.end_span(span),
Expand Down
36 changes: 26 additions & 10 deletions crates/oxc_semantic/src/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ impl<'a> Binder for VariableDeclarator<'a> {
};
self.id.bound_names(&mut |ident| {
let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes);
ident.symbol_id.set(Some(symbol_id));
if self.kind == VariableDeclarationKind::Var
&& !builder.scope.get_flags(current_scope_id).is_var()
{
Expand Down Expand Up @@ -59,12 +60,13 @@ impl<'a> Binder for Class<'a> {
fn bind(&self, builder: &mut SemanticBuilder) {
let Some(ident) = &self.id else { return };
if !self.modifiers.contains(ModifierKind::Declare) {
builder.declare_symbol(
let symbol_id = builder.declare_symbol(
ident.span,
&ident.name,
SymbolFlags::Class,
SymbolFlags::ClassExcludes,
);
ident.symbol_id.set(Some(symbol_id));
}
}
}
Expand Down Expand Up @@ -108,13 +110,14 @@ impl<'a> Binder for Function<'a> {
)
};

builder.declare_symbol_on_scope(
let symbol_id = builder.declare_symbol_on_scope(
ident.span,
&ident.name,
parent_scope_id,
includes,
excludes,
);
ident.symbol_id.set(Some(symbol_id));
}
}

Expand Down Expand Up @@ -152,7 +155,8 @@ impl<'a> Binder for FormalParameters<'a> {
let is_signature = self.kind == FormalParameterKind::Signature;
self.bound_names(&mut |ident| {
if !is_signature {
builder.declare_symbol(ident.span, &ident.name, includes, excludes);
let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes);
ident.symbol_id.set(Some(symbol_id));
}
});
}
Expand All @@ -167,15 +171,22 @@ impl<'a> Binder for CatchClause<'a> {
// unless CatchParameter is CatchParameter : BindingIdentifier
if let BindingPatternKind::BindingIdentifier(ident) = &param.kind {
let includes = SymbolFlags::FunctionScopedVariable | SymbolFlags::CatchVariable;
builder.declare_shadow_symbol(&ident.name, ident.span, current_scope_id, includes);
let symbol_id = builder.declare_shadow_symbol(
&ident.name,
ident.span,
current_scope_id,
includes,
);
ident.symbol_id.set(Some(symbol_id));
} else {
param.bound_names(&mut |ident| {
builder.declare_symbol(
let symbol_id = builder.declare_symbol(
ident.span,
&ident.name,
SymbolFlags::BlockScopedVariable | SymbolFlags::CatchVariable,
SymbolFlags::BlockScopedVariableExcludes,
);
ident.symbol_id.set(Some(symbol_id));
});
}
}
Expand All @@ -185,35 +196,38 @@ impl<'a> Binder for CatchClause<'a> {
impl<'a> Binder for ModuleDeclaration<'a> {
fn bind(&self, builder: &mut SemanticBuilder) {
self.bound_names(&mut |ident| {
builder.declare_symbol(
let symbol_id = builder.declare_symbol(
ident.span,
&ident.name,
SymbolFlags::ImportBinding,
SymbolFlags::ImportBindingExcludes,
);
ident.symbol_id.set(Some(symbol_id));
});
}
}

impl<'a> Binder for TSTypeAliasDeclaration<'a> {
fn bind(&self, builder: &mut SemanticBuilder) {
builder.declare_symbol(
let symbol_id = builder.declare_symbol(
self.id.span,
&self.id.name,
SymbolFlags::TypeAlias,
SymbolFlags::TypeAliasExcludes,
);
self.id.symbol_id.set(Some(symbol_id));
}
}

impl<'a> Binder for TSInterfaceDeclaration<'a> {
fn bind(&self, builder: &mut SemanticBuilder) {
builder.declare_symbol(
let symbol_id = builder.declare_symbol(
self.id.span,
&self.id.name,
SymbolFlags::Interface,
SymbolFlags::InterfaceExcludes,
);
self.id.symbol_id.set(Some(symbol_id));
}
}

Expand All @@ -226,7 +240,8 @@ impl<'a> Binder for TSEnumDeclaration<'a> {
} else {
SymbolFlags::RegularEnumExcludes
};
builder.declare_symbol(self.id.span, &self.id.name, includes, excludes);
let symbol_id = builder.declare_symbol(self.id.span, &self.id.name, includes, excludes);
self.id.symbol_id.set(Some(symbol_id));
}
}

Expand Down Expand Up @@ -271,11 +286,12 @@ impl<'a> Binder for TSModuleDeclaration<'a> {

impl<'a> Binder for TSTypeParameter<'a> {
fn bind(&self, builder: &mut SemanticBuilder) {
builder.declare_symbol(
let symbol_id = builder.declare_symbol(
self.name.span,
&self.name.name,
SymbolFlags::TypeParameter,
SymbolFlags::TypeParameterExcludes,
);
self.name.symbol_id.set(Some(symbol_id));
}
}
3 changes: 2 additions & 1 deletion crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,8 @@ impl<'a> SemanticBuilder<'a> {
fn reference_identifier(&mut self, ident: &IdentifierReference) {
let flag = self.resolve_reference_usages();
let reference = Reference::new(ident.span, ident.name.clone(), self.current_node_id, flag);
self.declare_reference(reference);
let reference_id = self.declare_reference(reference);
ident.reference_id.set(Some(reference_id));
}

/// Resolve reference flags for the current ast node.
Expand Down
5 changes: 1 addition & 4 deletions crates/oxc_semantic/src/reference.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use bitflags::bitflags;
use oxc_index::define_index_type;
use oxc_span::{Atom, Span};

use crate::{symbol::SymbolId, AstNodeId};

define_index_type! {
pub struct ReferenceId = u32;
}
pub use oxc_syntax::reference::ReferenceId;

#[derive(Debug, Clone)]
pub struct Reference {
Expand Down
1 change: 1 addition & 0 deletions crates/oxc_syntax/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod identifier;
pub mod module_record;
pub mod operator;
pub mod precedence;
pub mod reference;
pub mod scope;
pub mod symbol;

Expand Down
5 changes: 5 additions & 0 deletions crates/oxc_syntax/src/reference.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use oxc_index::define_index_type;

define_index_type! {
pub struct ReferenceId = u32;
}
7 changes: 7 additions & 0 deletions tasks/coverage/src/suite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ pub trait Case: Sized + Sync + Send + UnwindSafe {
.with_module_record_builder(true)
.with_check_syntax_error(true)
.build(program);
if let Some(res) = self.check_semantic(&semantic_ret.semantic) {
return res;
}
let errors = parser_ret.errors.into_iter().chain(semantic_ret.errors).collect::<Vec<_>>();

let result = if errors.is_empty() {
Expand Down Expand Up @@ -356,4 +359,8 @@ pub trait Case: Sized + Sync + Send + UnwindSafe {
}
Ok(())
}

fn check_semantic(&self, _semantic: &oxc_semantic::Semantic<'_>) -> Option<TestResult> {
None
}
}
Loading