mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
refactor(isolated-declarations): decouple codegen (#3715)
This commit is contained in:
parent
87c3282deb
commit
815260ed2f
6 changed files with 37 additions and 42 deletions
|
|
@ -19,7 +19,7 @@ pub fn get_leading_annotate_comment<const MINIFY: bool>(
|
||||||
CommentKind::SingleLine => comment.end,
|
CommentKind::SingleLine => comment.end,
|
||||||
CommentKind::MultiLine => comment.end + 2,
|
CommentKind::MultiLine => comment.end + 2,
|
||||||
};
|
};
|
||||||
let source_code = codegen.source_code;
|
let source_code = codegen.source_text;
|
||||||
let content_between = &source_code[real_end as usize..node_start as usize];
|
let content_between = &source_code[real_end as usize..node_start as usize];
|
||||||
// Used for VariableDeclaration (Rollup only respects "const" and only for the first one)
|
// Used for VariableDeclaration (Rollup only respects "const" and only for the first one)
|
||||||
if content_between.chars().all(|ch| ch.is_ascii_whitespace()) {
|
if content_between.chars().all(|ch| ch.is_ascii_whitespace()) {
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ impl<'a, const MINIFY: bool> From<Codegen<'a, MINIFY>> for Cow<'a, str> {
|
||||||
pub struct Codegen<'a, const MINIFY: bool> {
|
pub struct Codegen<'a, const MINIFY: bool> {
|
||||||
options: CodegenOptions,
|
options: CodegenOptions,
|
||||||
|
|
||||||
source_code: &'a str,
|
source_text: &'a str,
|
||||||
|
|
||||||
trivias: Trivias,
|
trivias: Trivias,
|
||||||
|
|
||||||
|
|
@ -116,24 +116,24 @@ pub enum Separator {
|
||||||
impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
|
impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
source_name: &str,
|
source_name: &str,
|
||||||
source_code: &'a str,
|
source_text: &'a str,
|
||||||
trivias: Trivias,
|
trivias: Trivias,
|
||||||
options: CodegenOptions,
|
options: CodegenOptions,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// Initialize the output code buffer to reduce memory reallocation.
|
// Initialize the output code buffer to reduce memory reallocation.
|
||||||
// Minification will reduce by at least half of the original size.
|
// Minification will reduce by at least half of the original size.
|
||||||
let source_len = source_code.len();
|
let source_len = source_text.len();
|
||||||
let capacity = if MINIFY { source_len / 2 } else { source_len };
|
let capacity = if MINIFY { source_len / 2 } else { source_len };
|
||||||
|
|
||||||
let sourcemap_builder = options.enable_source_map.then(|| {
|
let sourcemap_builder = options.enable_source_map.then(|| {
|
||||||
let mut sourcemap_builder = SourcemapBuilder::default();
|
let mut sourcemap_builder = SourcemapBuilder::default();
|
||||||
sourcemap_builder.with_name_and_source(source_name, source_code);
|
sourcemap_builder.with_name_and_source(source_name, source_text);
|
||||||
sourcemap_builder
|
sourcemap_builder
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
options,
|
options,
|
||||||
source_code,
|
source_text,
|
||||||
trivias,
|
trivias,
|
||||||
// mangler: None,
|
// mangler: None,
|
||||||
code: Vec::with_capacity(capacity),
|
code: Vec::with_capacity(capacity),
|
||||||
|
|
@ -192,7 +192,7 @@ impl<'a, const MINIFY: bool> Codegen<'a, MINIFY> {
|
||||||
/// Since if you want to print a range of source code, you need to borrow the source code
|
/// Since if you want to print a range of source code, you need to borrow the source code
|
||||||
/// immutable first, and call the [Self::print_str] which is a mutable borrow.
|
/// immutable first, and call the [Self::print_str] which is a mutable borrow.
|
||||||
pub fn print_range_of_source_code(&mut self, range: Range<usize>) {
|
pub fn print_range_of_source_code(&mut self, range: Range<usize>) {
|
||||||
self.code.extend_from_slice(self.source_code[range].as_bytes());
|
self.code.extend_from_slice(self.source_text[range].as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In some scenario, we want to move the comment that should be codegened to another position.
|
/// In some scenario, we want to move the comment that should be codegened to another position.
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ workspace = true
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
oxc_codegen = { workspace = true }
|
|
||||||
oxc_ast = { workspace = true }
|
oxc_ast = { workspace = true }
|
||||||
oxc_span = { workspace = true }
|
oxc_span = { workspace = true }
|
||||||
oxc_allocator = { workspace = true }
|
oxc_allocator = { workspace = true }
|
||||||
|
|
@ -30,7 +29,5 @@ oxc_syntax = { workspace = true, features = ["to_js_string"] }
|
||||||
rustc-hash = { workspace = true }
|
rustc-hash = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
oxc_parser = { workspace = true }
|
oxc_parser = { workspace = true }
|
||||||
|
oxc_codegen = { workspace = true }
|
||||||
[features]
|
|
||||||
default = []
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
use std::{env, path::Path};
|
use std::{env, path::Path};
|
||||||
|
|
||||||
use oxc_allocator::Allocator;
|
use oxc_allocator::Allocator;
|
||||||
|
use oxc_ast::Trivias;
|
||||||
|
use oxc_codegen::{Codegen, CodegenOptions};
|
||||||
use oxc_isolated_declarations::TransformerDts;
|
use oxc_isolated_declarations::TransformerDts;
|
||||||
use oxc_parser::Parser;
|
use oxc_parser::Parser;
|
||||||
use oxc_span::SourceType;
|
use oxc_span::SourceType;
|
||||||
|
|
@ -31,11 +33,14 @@ fn main() {
|
||||||
println!("Original:\n");
|
println!("Original:\n");
|
||||||
println!("{source_text}\n");
|
println!("{source_text}\n");
|
||||||
|
|
||||||
let program = ret.program;
|
let ret = TransformerDts::new(&allocator).build(&ret.program);
|
||||||
let ret = TransformerDts::new(&allocator, path, &source_text, ret.trivias).build(&program);
|
let printed =
|
||||||
|
Codegen::<false>::new("", &source_text, Trivias::default(), CodegenOptions::default())
|
||||||
|
.build(&ret.program)
|
||||||
|
.source_text;
|
||||||
|
|
||||||
println!("Transformed dts:\n");
|
println!("Dts Emit:\n");
|
||||||
println!("{}\n", ret.source_text);
|
println!("{printed}\n");
|
||||||
|
|
||||||
if !ret.errors.is_empty() {
|
if !ret.errors.is_empty() {
|
||||||
println!("Transformed dts failed:\n");
|
println!("Transformed dts failed:\n");
|
||||||
|
|
|
||||||
|
|
@ -17,20 +17,18 @@ mod return_type;
|
||||||
mod scope;
|
mod scope;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
use std::{collections::VecDeque, path::Path, rc::Rc};
|
use std::{collections::VecDeque, rc::Rc};
|
||||||
|
|
||||||
use context::{Ctx, TransformDtsCtx};
|
use context::{Ctx, TransformDtsCtx};
|
||||||
use oxc_allocator::Allocator;
|
use oxc_allocator::Allocator;
|
||||||
use oxc_ast::Trivias;
|
|
||||||
#[allow(clippy::wildcard_imports)]
|
#[allow(clippy::wildcard_imports)]
|
||||||
use oxc_ast::{ast::*, Visit};
|
use oxc_ast::{ast::*, Visit};
|
||||||
use oxc_codegen::{Codegen, CodegenOptions};
|
|
||||||
use oxc_diagnostics::OxcDiagnostic;
|
use oxc_diagnostics::OxcDiagnostic;
|
||||||
use oxc_span::{SourceType, SPAN};
|
use oxc_span::{SourceType, SPAN};
|
||||||
use scope::ScopeTree;
|
use scope::ScopeTree;
|
||||||
|
|
||||||
pub struct TransformerDtsReturn {
|
pub struct TransformerDtsReturn<'a> {
|
||||||
pub source_text: String,
|
pub program: Program<'a>,
|
||||||
pub errors: Vec<OxcDiagnostic>,
|
pub errors: Vec<OxcDiagnostic>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,13 +38,7 @@ pub struct TransformerDts<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TransformerDts<'a> {
|
impl<'a> TransformerDts<'a> {
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
pub fn new(allocator: &'a Allocator) -> Self {
|
||||||
pub fn new(
|
|
||||||
allocator: &'a Allocator,
|
|
||||||
_source_path: &Path,
|
|
||||||
_source_text: &'a str,
|
|
||||||
_trivias: Trivias,
|
|
||||||
) -> Self {
|
|
||||||
let ctx = Rc::new(TransformDtsCtx::new(allocator));
|
let ctx = Rc::new(TransformDtsCtx::new(allocator));
|
||||||
Self { ctx, scope: ScopeTree::new(allocator) }
|
Self { ctx, scope: ScopeTree::new(allocator) }
|
||||||
}
|
}
|
||||||
|
|
@ -54,17 +46,12 @@ impl<'a> TransformerDts<'a> {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// Returns `Vec<Error>` if any errors were collected during the transformation.
|
/// Returns `Vec<Error>` if any errors were collected during the transformation.
|
||||||
pub fn build(mut self, program: &Program<'a>) -> TransformerDtsReturn {
|
pub fn build(mut self, program: &Program<'a>) -> TransformerDtsReturn<'a> {
|
||||||
let source_type = SourceType::default().with_module(true).with_typescript_definition(true);
|
let source_type = SourceType::default().with_module(true).with_typescript_definition(true);
|
||||||
let directives = self.ctx.ast.new_vec();
|
let directives = self.ctx.ast.new_vec();
|
||||||
let stmts = self.transform_program(program);
|
let stmts = self.transform_program(program);
|
||||||
let program = self.ctx.ast.program(SPAN, source_type, directives, None, stmts);
|
let program = self.ctx.ast.program(SPAN, source_type, directives, None, stmts);
|
||||||
let source_text =
|
TransformerDtsReturn { program, errors: self.ctx.take_errors() }
|
||||||
Codegen::<false>::new("", "", Trivias::default(), CodegenOptions::default())
|
|
||||||
.build(&program)
|
|
||||||
.source_text;
|
|
||||||
|
|
||||||
TransformerDtsReturn { source_text, errors: self.ctx.take_errors() }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use oxc_allocator::Allocator;
|
use oxc_allocator::Allocator;
|
||||||
use oxc_isolated_declarations::{TransformerDts, TransformerDtsReturn};
|
use oxc_ast::Trivias;
|
||||||
|
use oxc_codegen::{Codegen, CodegenOptions};
|
||||||
|
use oxc_diagnostics::OxcDiagnostic;
|
||||||
|
use oxc_isolated_declarations::TransformerDts;
|
||||||
use oxc_parser::Parser;
|
use oxc_parser::Parser;
|
||||||
use oxc_span::SourceType;
|
use oxc_span::SourceType;
|
||||||
|
|
||||||
|
|
@ -137,13 +140,12 @@ impl TypeScriptTranspileCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
for unit in &self.units {
|
for unit in &self.units {
|
||||||
let ret = transpile(&self.path, &unit.content);
|
let (source_text, errors) = transpile(&self.path, &unit.content);
|
||||||
let baseline = Baseline {
|
let baseline = Baseline {
|
||||||
name: change_extension(&unit.name),
|
name: change_extension(&unit.name),
|
||||||
original: unit.content.clone(),
|
original: unit.content.clone(),
|
||||||
oxc_printed: ret.source_text,
|
oxc_printed: source_text,
|
||||||
diagnostic: ret
|
diagnostic: errors
|
||||||
.errors
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|e| e.message.clone())
|
.map(|e| e.message.clone())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
|
|
@ -160,9 +162,13 @@ fn change_extension(name: &str) -> String {
|
||||||
Path::new(name).with_extension("").with_extension("d.ts").to_str().unwrap().to_string()
|
Path::new(name).with_extension("").with_extension("d.ts").to_str().unwrap().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transpile(path: &Path, source_text: &str) -> TransformerDtsReturn {
|
fn transpile(path: &Path, source_text: &str) -> (String, Vec<OxcDiagnostic>) {
|
||||||
let allocator = Allocator::default();
|
let allocator = Allocator::default();
|
||||||
let source_type = SourceType::from_path(path).unwrap();
|
let source_type = SourceType::from_path(path).unwrap();
|
||||||
let ret = Parser::new(&allocator, source_text, source_type).parse();
|
let ret = Parser::new(&allocator, source_text, source_type).parse();
|
||||||
TransformerDts::new(&allocator, path, source_text, ret.trivias).build(&ret.program)
|
let ret = TransformerDts::new(&allocator).build(&ret.program);
|
||||||
|
let printed = Codegen::<false>::new("", "", Trivias::default(), CodegenOptions::default())
|
||||||
|
.build(&ret.program)
|
||||||
|
.source_text;
|
||||||
|
(printed, ret.errors)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue