Skip to content
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 22 additions & 22 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,29 +92,18 @@ pub enum Expression<'a> {
impl<'a> Expression<'a> {
/// `PrimaryExpression`
/// [tc39/ecma262#prod-PrimaryExpression](https://tc39.es/ecma262/#prod-PrimaryExpression)
#[rustfmt::skip]
pub fn is_primary_expression(&self) -> bool {
self.is_literal_expression()
|| matches!(
self,
Self::Identifier(_)
| Self::ThisExpression(_)
| Self::FunctionExpression(_)
| Self::ClassExpression(_)
| Self::ParenthesizedExpression(_)
| Self::ArrayExpression(_)
| Self::ObjectExpression(_)
)
}

pub fn is_literal_expression(&self) -> bool {
matches!(
self,
Self::BooleanLiteral(_)
| Self::NullLiteral(_)
| Self::NumberLiteral(_)
| Self::BigintLiteral(_)
| Self::RegExpLiteral(_)
| Self::StringLiteral(_) // TemplateLiteral is not `Literal` type per oxc_ast
self.is_literal() || matches!(self, Self::Identifier(_) | Self::ThisExpression(_) | Self::FunctionExpression(_)
| Self::ClassExpression(_) | Self::ParenthesizedExpression(_)
| Self::ArrayExpression(_) | Self::ObjectExpression(_))
}

#[rustfmt::skip]
pub fn is_literal(&self) -> bool {
// Note: TemplateLiteral is not `Literal`
matches!(self, Self::BooleanLiteral(_) | Self::NullLiteral(_) | Self::NumberLiteral(_)
| Self::BigintLiteral(_) | Self::RegExpLiteral(_) | Self::StringLiteral(_)
)
}

Expand Down Expand Up @@ -540,6 +529,10 @@ pub enum MemberExpression<'a> {
}

impl<'a> MemberExpression<'a> {
pub fn is_computed(&self) -> bool {
matches!(self, MemberExpression::ComputedMemberExpression(_))
}

pub fn optional(&self) -> bool {
match self {
MemberExpression::ComputedMemberExpression(expr) => expr.optional,
Expand Down Expand Up @@ -814,6 +807,13 @@ impl<'a> AssignmentTarget<'a> {
pub fn is_destructuring_pattern(&self) -> bool {
matches!(self, Self::AssignmentTargetPattern(_))
}

pub fn is_identifier(&self) -> bool {
matches!(
self,
Self::SimpleAssignmentTarget(SimpleAssignmentTarget::AssignmentTargetIdentifier(_))
)
}
}

#[derive(Debug, Hash)]
Expand Down
4 changes: 4 additions & 0 deletions crates/oxc_ast/src/ast/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ pub struct StringLiteral {
}

impl StringLiteral {
pub fn new(span: Span, value: Atom) -> Self {
Self { span, value }
}

/// Static Semantics: `IsStringWellFormedUnicode`
/// test for \uD800-\uDFFF
pub fn is_string_well_formed_unicode(&self) -> bool {
Expand Down
58 changes: 47 additions & 11 deletions crates/oxc_ast/src/ast_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ impl<'a> AstBuilder<'a> {
mem::replace(stmts, self.new_vec())
}

pub fn move_assignment_target(
&self,
target: &mut AssignmentTarget<'a>,
) -> AssignmentTarget<'a> {
let ident = IdentifierReference::new(Span::default(), "".into());
let dummy = self.simple_assignment_target_identifier(ident);
let dummy = AssignmentTarget::SimpleAssignmentTarget(dummy);
mem::replace(target, dummy)
}

pub fn program(
&self,
span: Span,
Expand All @@ -90,10 +100,6 @@ impl<'a> AstBuilder<'a> {

/* ---------- Literals ---------- */

pub fn string_literal(&self, span: Span, value: Atom) -> StringLiteral {
StringLiteral { span, value }
}

pub fn number_literal(
&self,
span: Span,
Expand Down Expand Up @@ -415,6 +421,13 @@ impl<'a> AstBuilder<'a> {
SimpleAssignmentTarget::AssignmentTargetIdentifier(self.alloc(ident))
}

pub fn simple_assignment_target_member_expression(
&self,
expr: MemberExpression<'a>,
) -> SimpleAssignmentTarget<'a> {
SimpleAssignmentTarget::MemberAssignmentTarget(self.alloc(expr))
}

pub fn await_expression(&self, span: Span, argument: Expression<'a>) -> Expression<'a> {
Expression::AwaitExpression(self.alloc(AwaitExpression { span, argument }))
}
Expand Down Expand Up @@ -496,31 +509,54 @@ impl<'a> AstBuilder<'a> {
Expression::MemberExpression(self.alloc(expr))
}

pub fn computed_member(
&self,
span: Span,
object: Expression<'a>,
expression: Expression<'a>,
optional: bool, // for optional chaining
) -> MemberExpression<'a> {
MemberExpression::ComputedMemberExpression(ComputedMemberExpression {
span,
object,
expression,
optional,
})
}

pub fn computed_member_expression(
&self,
span: Span,
object: Expression<'a>,
expression: Expression<'a>,
optional: bool, // for optional chaining
) -> Expression<'a> {
self.member_expression(MemberExpression::ComputedMemberExpression(
ComputedMemberExpression { span, object, expression, optional },
))
self.member_expression(self.computed_member(span, object, expression, optional))
}

pub fn static_member_expression(
pub fn static_member(
&self,
span: Span,
object: Expression<'a>,
property: IdentifierName,
optional: bool, // for optional chaining
) -> Expression<'a> {
self.member_expression(MemberExpression::StaticMemberExpression(StaticMemberExpression {
) -> MemberExpression<'a> {
MemberExpression::StaticMemberExpression(StaticMemberExpression {
span,
object,
property,
optional,
}))
})
}

pub fn static_member_expression(
&self,
span: Span,
object: Expression<'a>,
property: IdentifierName,
optional: bool, // for optional chaining
) -> Expression<'a> {
self.member_expression(self.static_member(span, object, property, optional))
}

pub fn private_field_expression(
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/ast_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn is_static_boolean<'a>(expr: &Expression<'a>, ctx: &LintContext<'a>) -> bo
/// Checks if a branch node of `LogicalExpression` short circuits the whole condition
fn is_logical_identity(op: LogicalOperator, expr: &Expression) -> bool {
match expr {
expr if expr.is_literal_expression() => {
expr if expr.is_literal() => {
let boolean_value = expr.get_boolean_value();
(op == LogicalOperator::Or && boolean_value == Some(true))
|| (op == LogicalOperator::And && boolean_value == Some(false))
Expand Down Expand Up @@ -142,7 +142,7 @@ impl<'a, 'b> IsConstant<'a, 'b> for Expression<'a> {
Self::Identifier(ident) => {
ident.name == "undefined" && ctx.semantic().is_reference_to_global_variable(ident)
}
_ if self.is_literal_expression() => true,
_ if self.is_literal() => true,
_ => false,
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl NoConstantBinaryExpression {
| Expression::UpdateExpression(_)
| Expression::BinaryExpression(_)
| Expression::UnaryExpression(_) => true,
expr if expr.is_literal_expression() => true,
expr if expr.is_literal() => true,
Expression::CallExpression(call_expr) => {
if let Expression::Identifier(ident) = &call_expr.callee {
return ["Boolean", "String", "Number"].contains(&ident.name.as_str())
Expand Down Expand Up @@ -267,7 +267,7 @@ impl NoConstantBinaryExpression {
Expression::ParenthesizedExpression(paren_expr) => {
Self::has_constant_loose_boolean_comparison(&paren_expr.expression, ctx)
}
expr if expr.is_literal_expression() => true,
expr if expr.is_literal() => true,
expr if expr.evaluate_to_undefined() => true,
_ => false,
}
Expand All @@ -288,7 +288,7 @@ impl NoConstantBinaryExpression {
| Expression::NewExpression(_)
| Expression::TemplateLiteral(_)
| Expression::UpdateExpression(_) => true,
expr if expr.is_literal_expression() => true,
expr if expr.is_literal() => true,
Expression::BinaryExpression(binary_expr) => {
binary_expr.operator.is_numeric_or_string_binary_operator()
}
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_minifier/src/compressor/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ impl<'a> Compressor<'a> {
let right_string = get_string_value(right)?;
// let value = left_string.to_owned().
let value = left_string + right_string;
let string_literal = self.ast.string_literal(span, Atom::from(value));
let string_literal = StringLiteral::new(span, Atom::from(value));
Some(self.ast.literal_string_expression(string_literal))
},

Expand Down Expand Up @@ -587,7 +587,7 @@ impl<'a> Compressor<'a> {
};

if let Some(type_name) = type_name {
let string_literal = self.ast.string_literal(span, Atom::from(type_name));
let string_literal = StringLiteral::new(span, Atom::from(type_name));
return Some(self.ast.literal_string_expression(string_literal));
}
}
Expand Down
4 changes: 4 additions & 0 deletions crates/oxc_semantic/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ impl SymbolTable {
&self.references[reference_id]
}

pub fn has_binding(&self, reference_id: ReferenceId) -> bool {
self.references[reference_id].symbol_id().is_some()
}

pub fn is_global_reference(&self, reference_id: ReferenceId) -> bool {
self.references[reference_id].symbol_id().is_none()
}
Expand Down
10 changes: 7 additions & 3 deletions crates/oxc_transformer/examples/transformer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{env, path::Path};
use std::{cell::RefCell, env, path::Path, rc::Rc};

use oxc_allocator::Allocator;
use oxc_codegen::{Codegen, CodegenOptions};
Expand Down Expand Up @@ -34,12 +34,16 @@ fn main() {
println!("{printed}");

let program = allocator.alloc(ret.program);
let _ = SemanticBuilder::new(&source_text, source_type).build(program);

let semantic = SemanticBuilder::new(&source_text, source_type).build(program).semantic;
let (symbols, _scope_tree) = semantic.into_symbol_table_and_scope_tree();
let symbols = Rc::new(RefCell::new(symbols));

let transform_options = TransformOptions {
target: TransformTarget::ES2015,
react: Some(TransformReactOptions::default()),
};
Transformer::new(&allocator, source_type, transform_options).build(program);
Transformer::new(&allocator, source_type, &symbols, transform_options).build(program);
let printed = Codegen::<false>::new(source_text.len(), codegen_options).build(program);
println!("Transformed:\n");
println!("{printed}");
Expand Down
Loading