mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
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:
parent
fa4d505b92
commit
9e62396803
30 changed files with 118 additions and 47 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
|
@ -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",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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::{
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
25
crates/oxc_syntax_operations/Cargo.toml
Normal file
25
crates/oxc_syntax_operations/Cargo.toml
Normal 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 }
|
||||
|
|
@ -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> {
|
||||
14
crates/oxc_syntax_operations/src/has_proto.rs
Normal file
14
crates/oxc_syntax_operations/src/has_proto.rs
Normal 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__"))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::ast::*;
|
||||
use oxc_ast::ast::FormalParameters;
|
||||
|
||||
/// [`IsSimpleParameterList`](https://tc39.es/ecma262/#sec-static-semantics-issimpleparameterlist)
|
||||
pub trait IsSimpleParameterList {
|
||||
20
crates/oxc_syntax_operations/src/lib.rs
Normal file
20
crates/oxc_syntax_operations/src/lib.rs
Normal 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,
|
||||
};
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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)>;
|
||||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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::{
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue