feat(syntax_operations): add crate oxc_syntax_operations (#6202)

I intend to add constant folding and eval logic to this crate. There are downstream tools that require these functionalities alone.

It's also reasonable to move these traits out of the `ast` crate.
This commit is contained in:
Boshen 2024-10-07 05:39:59 +00:00
parent fa4d505b92
commit 9e62396803
30 changed files with 118 additions and 47 deletions

15
Cargo.lock generated
View file

@ -1612,6 +1612,7 @@ dependencies = [
"oxc_parser",
"oxc_span",
"oxc_syntax",
"oxc_syntax_operations",
"rustc-hash",
]
@ -1722,6 +1723,7 @@ dependencies = [
"oxc_semantic",
"oxc_span",
"oxc_syntax",
"oxc_syntax_operations",
"oxc_traverse",
"pico-args",
]
@ -1763,6 +1765,7 @@ dependencies = [
"oxc_ast",
"oxc_parser",
"oxc_span",
"oxc_syntax_operations",
]
[[package]]
@ -1781,6 +1784,7 @@ dependencies = [
"oxc_regular_expression",
"oxc_span",
"oxc_syntax",
"oxc_syntax_operations",
"pico-args",
"rustc-hash",
"seq-macro",
@ -1890,6 +1894,7 @@ dependencies = [
"oxc_parser",
"oxc_span",
"oxc_syntax",
"oxc_syntax_operations",
"phf 0.11.2",
"rustc-hash",
"serde",
@ -1946,6 +1951,14 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "oxc_syntax_operations"
version = "0.30.5"
dependencies = [
"oxc_ast",
"oxc_span",
]
[[package]]
name = "oxc_tasks_common"
version = "0.0.0"
@ -2013,6 +2026,7 @@ dependencies = [
"oxc_semantic",
"oxc_span",
"oxc_syntax",
"oxc_syntax_operations",
"oxc_traverse",
"pico-args",
"ropey",
@ -2035,6 +2049,7 @@ dependencies = [
"oxc_semantic",
"oxc_span",
"oxc_syntax",
"oxc_syntax_operations",
"rustc-hash",
]

View file

@ -95,6 +95,7 @@ oxc_semantic = { version = "0.30.5", path = "crates/oxc_semantic" }
oxc_sourcemap = { version = "0.30.5", path = "crates/oxc_sourcemap" }
oxc_span = { version = "0.30.5", path = "crates/oxc_span" }
oxc_syntax = { version = "0.30.5", path = "crates/oxc_syntax" }
oxc_syntax_operations = { version = "0.30.5", path = "crates/oxc_syntax_operations" }
oxc_transform_napi = { version = "0.30.5", path = "napi/transform" }
oxc_transformer = { version = "0.30.5", path = "crates/oxc_transformer" }
oxc_traverse = { version = "0.30.5", path = "crates/oxc_traverse" }

View file

@ -382,14 +382,6 @@ impl<'a> ArrayExpressionElement<'a> {
}
}
impl<'a> ObjectExpression<'a> {
/// Returns `true` if this object has a property named `__proto__`
pub fn has_proto(&self) -> bool {
use crate::syntax_directed_operations::PropName;
self.properties.iter().any(|p| p.prop_name().is_some_and(|name| name.0 == "__proto__"))
}
}
impl<'a> PropertyKey<'a> {
pub fn static_name(&self) -> Option<Cow<'a, str>> {
match self {

View file

@ -33,7 +33,6 @@ mod ast_builder_impl;
mod ast_impl;
mod ast_kind_impl;
pub mod precedence;
pub mod syntax_directed_operations;
mod trivia;
mod generated {

View file

@ -1,11 +0,0 @@
//! [ECMA262 Syntax-Directed Operations](https://tc39.es/ecma262/#sec-syntax-directed-operations)
mod bound_names;
mod is_simple_parameter_list;
mod private_bound_identifiers;
mod prop_name;
pub use self::{
bound_names::BoundNames, is_simple_parameter_list::IsSimpleParameterList,
private_bound_identifiers::PrivateBoundIdentifiers, prop_name::PropName,
};

View file

@ -29,6 +29,7 @@ oxc_ast = { workspace = true }
oxc_diagnostics = { workspace = true }
oxc_span = { workspace = true }
oxc_syntax = { workspace = true, features = ["to_js_string"] }
oxc_syntax_operations = { workspace = true }
bitflags = { workspace = true }
rustc-hash = { workspace = true }

View file

@ -6,9 +6,10 @@ use oxc_allocator::Vec;
#[allow(clippy::wildcard_imports)]
use oxc_ast::ast::*;
use oxc_ast::visit::walk_mut::walk_ts_signatures;
use oxc_ast::{syntax_directed_operations::BoundNames, Visit, VisitMut};
use oxc_ast::{Visit, VisitMut};
use oxc_span::{GetSpan, SPAN};
use oxc_syntax::scope::ScopeFlags;
use oxc_syntax_operations::BoundNames;
use crate::diagnostics::accessor_must_have_explicit_return_type;
use crate::{

View file

@ -29,6 +29,7 @@ oxc_parser = { workspace = true }
oxc_semantic = { workspace = true }
oxc_span = { workspace = true }
oxc_syntax = { workspace = true }
oxc_syntax_operations = { workspace = true }
oxc_traverse = { workspace = true }
cow-utils = { workspace = true }

View file

@ -1,5 +1,6 @@
use oxc_ast::{ast::*, syntax_directed_operations::BoundNames, AstBuilder, Visit, NONE};
use oxc_ast::{ast::*, AstBuilder, Visit, NONE};
use oxc_span::{Atom, Span, SPAN};
use oxc_syntax_operations::BoundNames;
pub struct KeepVar<'a> {
ast: AstBuilder<'a>,

View file

@ -23,6 +23,7 @@ doctest = false
[dependencies]
oxc_ast = { workspace = true }
oxc_span = { workspace = true }
oxc_syntax_operations = { workspace = true }
[dev-dependencies]
oxc_allocator = { workspace = true }

View file

@ -7,8 +7,9 @@ use oxc_ast::visit::walk::{
walk_import_expression, walk_meta_property, walk_module_declaration, walk_statement,
};
#[allow(clippy::wildcard_imports)]
use oxc_ast::{ast::*, syntax_directed_operations::BoundNames, Visit};
use oxc_ast::{ast::*, Visit};
use oxc_span::{Atom, GetSpan};
use oxc_syntax_operations::BoundNames;
#[derive(Debug, Clone)]
pub struct ImportSpecifier<'a> {

View file

@ -25,6 +25,7 @@ oxc_diagnostics = { workspace = true }
oxc_regular_expression = { workspace = true }
oxc_span = { workspace = true }
oxc_syntax = { workspace = true }
oxc_syntax_operations = { workspace = true }
assert-unchecked = { workspace = true }
bitflags = { workspace = true }

View file

@ -1,7 +1,8 @@
use oxc_allocator::{Box, Vec};
use oxc_ast::{ast::*, syntax_directed_operations::PropName};
use oxc_ast::ast::*;
use oxc_diagnostics::Result;
use oxc_span::{GetSpan, Span};
use oxc_syntax_operations::PropName;
use crate::{
diagnostics,

View file

@ -26,6 +26,7 @@ oxc_diagnostics = { workspace = true }
oxc_index = { workspace = true }
oxc_span = { workspace = true }
oxc_syntax = { workspace = true }
oxc_syntax_operations = { workspace = true }
assert-unchecked = { workspace = true }
indexmap = { workspace = true }

View file

@ -3,12 +3,9 @@
use std::{borrow::Cow, ptr};
#[allow(clippy::wildcard_imports)]
use oxc_ast::{
ast::*,
syntax_directed_operations::{BoundNames, IsSimpleParameterList},
AstKind,
};
use oxc_ast::{ast::*, AstKind};
use oxc_span::{GetSpan, SourceType};
use oxc_syntax_operations::{BoundNames, IsSimpleParameterList};
use crate::{
scope::{ScopeFlags, ScopeId},

View file

@ -2,11 +2,7 @@ use phf::{phf_set, Set};
use rustc_hash::FxHashMap;
#[allow(clippy::wildcard_imports)]
use oxc_ast::{
ast::*,
syntax_directed_operations::{IsSimpleParameterList, PropName},
AstKind,
};
use oxc_ast::{ast::*, AstKind};
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_span::{GetSpan, ModuleKind, Span};
use oxc_syntax::{
@ -14,6 +10,7 @@ use oxc_syntax::{
number::NumberBase,
operator::{AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator},
};
use oxc_syntax_operations::{IsSimpleParameterList, PropName};
use crate::{builder::SemanticBuilder, diagnostics::redeclaration, scope::ScopeFlags, AstNode};

View file

@ -3,13 +3,10 @@ use std::borrow::Cow;
use rustc_hash::FxHashMap;
#[allow(clippy::wildcard_imports)]
use oxc_ast::{
ast::*,
syntax_directed_operations::{BoundNames, PropName},
AstKind,
};
use oxc_ast::{ast::*, AstKind};
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{Atom, GetSpan, Span};
use oxc_syntax_operations::{BoundNames, PropName};
use crate::{builder::SemanticBuilder, diagnostics::redeclaration};

View file

@ -1,10 +1,11 @@
use std::path::PathBuf;
#[allow(clippy::wildcard_imports)]
use oxc_ast::{ast::*, syntax_directed_operations::BoundNames};
use oxc_ast::ast::*;
use oxc_span::{CompactStr, GetSpan, Span};
#[allow(clippy::wildcard_imports)]
use oxc_syntax::module_record::*;
use oxc_syntax_operations::BoundNames;
#[derive(Default)]
pub struct ModuleRecordBuilder {

View file

@ -0,0 +1,25 @@
[package]
name = "oxc_syntax_operations"
version = "0.30.5"
authors.workspace = true
categories.workspace = true
edition.workspace = true
homepage.workspace = true
include = ["/src"]
keywords.workspace = true
license.workspace = true
publish = true
repository.workspace = true
rust-version.workspace = true
description.workspace = true
[lints]
workspace = true
[lib]
test = false
doctest = false
[dependencies]
oxc_ast = { workspace = true }
oxc_span = { workspace = true }

View file

@ -1,4 +1,9 @@
use crate::ast::*;
use oxc_ast::ast::{
ArrayPattern, AssignmentPattern, BindingIdentifier, BindingPattern, BindingPatternKind,
BindingRestElement, Class, Declaration, ExportNamedDeclaration, FormalParameter,
FormalParameters, Function, ImportDeclaration, ImportDeclarationSpecifier, ModuleDeclaration,
ObjectPattern, VariableDeclaration,
};
/// [`BoundName`](https://tc39.es/ecma262/#sec-static-semantics-boundnames)
pub trait BoundName<'a> {

View file

@ -0,0 +1,14 @@
use oxc_ast::ast::ObjectExpression;
use crate::PropName;
pub trait HasProto {
/// Returns `true` if this object has a property named `__proto__`
fn has_proto(&self) -> bool;
}
impl<'a> HasProto for ObjectExpression<'a> {
fn has_proto(&self) -> bool {
self.properties.iter().any(|p| p.prop_name().is_some_and(|name| name.0 == "__proto__"))
}
}

View file

@ -1,4 +1,4 @@
use crate::ast::*;
use oxc_ast::ast::FormalParameters;
/// [`IsSimpleParameterList`](https://tc39.es/ecma262/#sec-static-semantics-issimpleparameterlist)
pub trait IsSimpleParameterList {

View file

@ -0,0 +1,20 @@
//! Traits for JavaScript syntax operations
//!
//! * BoundNames
//! * IsSimpleParameterList
//! * PrivateBoundIdentifiers
//! * PropName
//! * Constant Folding
//!
//! See [ECMA262 Syntax-Directed Operations](https://tc39.es/ecma262/#sec-syntax-directed-operations)
mod bound_names;
mod has_proto;
mod is_simple_parameter_list;
mod private_bound_identifiers;
mod prop_name;
pub use self::{
bound_names::BoundNames, has_proto::HasProto, is_simple_parameter_list::IsSimpleParameterList,
private_bound_identifiers::PrivateBoundIdentifiers, prop_name::PropName,
};

View file

@ -1,4 +1,7 @@
use crate::ast::*;
use oxc_ast::ast::{
AccessorProperty, ClassElement, MethodDefinition, PrivateIdentifier, PropertyDefinition,
PropertyKey,
};
/// [`PrivateBoundIdentifiers`](https://tc39.es/ecma262/#sec-static-semantics-privateboundidentifiers)
pub trait PrivateBoundIdentifiers {

View file

@ -1,7 +1,9 @@
use oxc_ast::ast::{
ClassElement, MethodDefinition, ObjectProperty, ObjectPropertyKind, PropertyDefinition,
PropertyKey, PropertyKind,
};
use oxc_span::Span;
use crate::ast::*;
/// [`PropName`](https://tc39.es/ecma262/#sec-static-semantics-propname)
pub trait PropName {
fn prop_name(&self) -> Option<(&str, Span)>;

View file

@ -35,6 +35,7 @@ oxc_regular_expression = { workspace = true }
oxc_semantic = { workspace = true }
oxc_span = { workspace = true }
oxc_syntax = { workspace = true, features = ["to_js_string"] }
oxc_syntax_operations = { workspace = true }
oxc_traverse = { workspace = true }
ropey = { workspace = true }
rustc-hash = { workspace = true }

View file

@ -97,6 +97,7 @@ use oxc_syntax::{
symbol::SymbolFlags,
xml_entities::XML_ENTITIES,
};
use oxc_syntax_operations::HasProto;
use oxc_traverse::{BoundIdentifier, Traverse, TraverseCtx};
use crate::{common::module_imports::NamedImport, TransformCtx};

View file

@ -1,12 +1,14 @@
use oxc_allocator::{Box, Vec};
use oxc_ast::{ast::*, syntax_directed_operations::BoundNames, NONE};
use oxc_ast::{ast::*, NONE};
use oxc_span::{Atom, CompactStr, SPAN};
use oxc_syntax::{
operator::{AssignmentOperator, LogicalOperator},
scope::{ScopeFlags, ScopeId},
symbol::SymbolFlags,
};
use oxc_syntax_operations::BoundNames;
use oxc_traverse::{Traverse, TraverseCtx};
use rustc_hash::FxHashSet;
use super::{

View file

@ -29,6 +29,7 @@ oxc_data_structures = { workspace = true }
oxc_semantic = { workspace = true }
oxc_span = { workspace = true }
oxc_syntax = { workspace = true }
oxc_syntax_operations = { workspace = true }
compact_str = { workspace = true }
itoa = { workspace = true }

View file

@ -6,7 +6,7 @@
#[allow(clippy::wildcard_imports)]
use oxc_ast::ast::*;
use oxc_ast::syntax_directed_operations::BoundNames;
use oxc_syntax_operations::BoundNames;
use super::to_identifier;