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

refactor(transformer): pass in symbols and scopes #3978

Merged
merged 1 commit into from
Jun 30, 2024
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.

1 change: 1 addition & 0 deletions crates/oxc_transformer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ oxc_allocator = { workspace = true }
oxc_diagnostics = { workspace = true }
oxc_syntax = { workspace = true, features = ["to_js_string"] }
oxc_traverse = { workspace = true }
oxc_semantic = { workspace = true }

dashmap = { workspace = true }
indexmap = { workspace = true }
Expand Down
7 changes: 3 additions & 4 deletions crates/oxc_transformer/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{

use oxc_allocator::Allocator;
use oxc_ast::{AstBuilder, Trivias};
use oxc_diagnostics::{Error, OxcDiagnostic};
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::SourceType;

use crate::{helpers::module_imports::ModuleImports, TransformOptions};
Expand Down Expand Up @@ -65,9 +65,8 @@ impl<'a> TransformCtx<'a> {
}
}

pub fn take_errors(&self) -> Vec<Error> {
let errors: Vec<OxcDiagnostic> = mem::take(&mut self.errors.borrow_mut());
errors.into_iter().map(Error::from).collect()
pub fn take_errors(&self) -> Vec<OxcDiagnostic> {
mem::take(&mut self.errors.borrow_mut())
}

/// Add an Error
Expand Down
44 changes: 28 additions & 16 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ mod helpers {

use std::{path::Path, rc::Rc};

use es2015::ES2015;
use oxc_allocator::{Allocator, Vec};
use oxc_ast::{ast::*, AstBuilder, Trivias};
use oxc_diagnostics::Error;
use oxc_diagnostics::OxcDiagnostic;
use oxc_semantic::{ScopeTree, SemanticBuilder, SymbolTable};
use oxc_span::SourceType;
use oxc_traverse::{traverse_mut, Traverse, TraverseCtx};

Expand All @@ -42,10 +42,17 @@ pub use crate::{
};
use crate::{
context::{Ctx, TransformCtx},
es2015::ES2015,
react::React,
typescript::TypeScript,
};

pub struct TransformerReturn {
pub errors: std::vec::Vec<OxcDiagnostic>,
pub symbols: SymbolTable,
pub scopes: ScopeTree,
}

pub struct Transformer<'a> {
ctx: Ctx<'a>,
// NOTE: all callbacks must run in order.
Expand Down Expand Up @@ -79,20 +86,25 @@ impl<'a> Transformer<'a> {
}
}

/// # Errors
///
/// Returns `Vec<Error>` if any errors were collected during the transformation.
pub fn build(mut self, program: &mut Program<'a>) -> Result<(), std::vec::Vec<Error>> {
let TransformCtx { ast: AstBuilder { allocator }, source_text, source_type, .. } =
*self.ctx;
traverse_mut(&mut self, program, source_text, source_type, allocator);

let errors = self.ctx.take_errors();
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
pub fn build(mut self, program: &mut Program<'a>) -> TransformerReturn {
let (symbols, scopes) = SemanticBuilder::new(self.ctx.source_text, self.ctx.source_type)
.build(program)
.semantic
.into_symbol_table_and_scope_tree();
let TransformCtx { ast: AstBuilder { allocator }, .. } = *self.ctx;
let (symbols, scopes) = traverse_mut(&mut self, allocator, program, symbols, scopes);
TransformerReturn { errors: self.ctx.take_errors(), symbols, scopes }
}

pub fn build_with_symbols_and_scopes(
mut self,
symbols: SymbolTable,
scopes: ScopeTree,
program: &mut Program<'a>,
) -> TransformerReturn {
let TransformCtx { ast: AstBuilder { allocator }, .. } = *self.ctx;
let (symbols, scopes) = traverse_mut(&mut self, allocator, program, symbols, scopes);
TransformerReturn { errors: self.ctx.take_errors(), symbols, scopes }
}
}

Expand Down
4 changes: 4 additions & 0 deletions crates/oxc_traverse/src/context/scoping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ pub struct TraverseScoping {

// Public methods
impl TraverseScoping {
pub fn into_symbol_table_and_scope_tree(self) -> (SymbolTable, ScopeTree) {
(self.symbols, self.scopes)
}

/// Get current scope ID
#[inline]
pub fn current_scope_id(&self) -> ScopeId {
Expand Down
15 changes: 6 additions & 9 deletions crates/oxc_traverse/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@

use oxc_allocator::Allocator;
use oxc_ast::ast::Program;
use oxc_semantic::SemanticBuilder;
use oxc_span::SourceType;
use oxc_semantic::{ScopeTree, SymbolTable};

pub mod ancestor;
pub use ancestor::Ancestor;
Expand Down Expand Up @@ -140,16 +139,14 @@ mod walk;
#[allow(unsafe_code)]
pub fn traverse_mut<'a, Tr: Traverse<'a>>(
traverser: &mut Tr,
program: &mut Program<'a>,
source_text: &'a str,
source_type: SourceType,
allocator: &'a Allocator,
) {
let semantic = SemanticBuilder::new(source_text, source_type).build(program).semantic;
let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree();

program: &mut Program<'a>,
symbols: SymbolTable,
scopes: ScopeTree,
) -> (SymbolTable, ScopeTree) {
let mut ctx = TraverseCtx::new(scopes, symbols, allocator);
// SAFETY: Walk functions are constructed to avoid unsoundness
unsafe { walk::walk_program(traverser, program as *mut Program, &mut ctx) };
debug_assert!(ctx.ancestors_depth() == 1);
ctx.scoping.into_symbol_table_and_scope_tree()
}
5 changes: 3 additions & 2 deletions crates/oxc_wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,9 @@ impl Oxc {
options,
)
.build(program);
if let Err(errs) = result {
self.save_diagnostics(errs);
if !result.errors.is_empty() {
let errors = result.errors.into_iter().map(Error::from).collect::<Vec<_>>();
self.save_diagnostics(errors);
}
}

Expand Down
9 changes: 5 additions & 4 deletions napi/transform/src/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,18 @@ pub fn transform(

let mut program = parser_ret.program;
let transform_options = TransformOptions::from(options);
if let Err(e) = Transformer::new(
let ret = Transformer::new(
&allocator,
source_path,
source_type,
&source_text,
parser_ret.trivias.clone(),
transform_options,
)
.build(&mut program)
{
errors.extend(e.into_iter().map(|error| error.to_string()));
.build(&mut program);

if !ret.errors.is_empty() {
errors.extend(ret.errors.into_iter().map(|error| error.to_string()));
}

let mut codegen = CodeGenerator::new();
Expand Down
3 changes: 1 addition & 2 deletions tasks/benchmark/benches/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ fn bench_transformer(criterion: &mut Criterion) {
trivias,
transform_options,
)
.build(program)
.unwrap();
.build(program);
allocator
});
});
Expand Down
23 changes: 13 additions & 10 deletions tasks/transform_conformance/src/test_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,11 @@ pub trait TestCase {
false
}

fn transform(&self, path: &Path) -> Result<String, Vec<Error>> {
fn transform(&self, path: &Path) -> Result<String, Vec<OxcDiagnostic>> {
let transform_options = match self.transform_options() {
Ok(transform_options) => transform_options,
Err(json_err) => {
return Err(vec![OxcDiagnostic::error(format!("{json_err:?}")).into()]);
return Err(vec![OxcDiagnostic::error(format!("{json_err:?}"))]);
}
};

Expand Down Expand Up @@ -180,7 +180,11 @@ pub trait TestCase {
transform_options.clone(),
)
.build(&mut program);
result.map(|()| CodeGenerator::new().build(&program).source_text)
if result.errors.is_empty() {
Ok(CodeGenerator::new().build(&program).source_text)
} else {
Err(result.errors)
}
}
}

Expand Down Expand Up @@ -262,15 +266,14 @@ impl TestCase for ConformanceTestCase {
ret.trivias.clone(),
transform_options.clone(),
);
let result = transformer.build(&mut program);
if result.is_ok() {
let ret = transformer.build(&mut program);
if ret.errors.is_empty() {
transformed_code = CodeGenerator::new().build(&program).source_text;
} else {
let error = result
.err()
.unwrap()
.iter()
.map(ToString::to_string)
let error = ret
.errors
.into_iter()
.map(|e| Error::from(e).to_string())
.collect::<Vec<_>>()
.join("\n");
actual_errors = get_babel_error(&error);
Expand Down
Loading