mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
refactor(semantic)!: remove source_type argument from SemanticBuilder::new (#5553)
Realized we can get the source type from the AST. The next PR will introduce `unambiguous` to `SourceType` and directly set `Program::source_type` to either `script` or `module`.
This commit is contained in:
parent
d62defb42d
commit
b06052501a
25 changed files with 31 additions and 36 deletions
|
|
@ -117,7 +117,7 @@ pub trait CompilerInterface {
|
||||||
let mut program = parser_return.program;
|
let mut program = parser_return.program;
|
||||||
let trivias = parser_return.trivias;
|
let trivias = parser_return.trivias;
|
||||||
|
|
||||||
let mut semantic_return = self.semantic(&program, source_text, source_type, source_path);
|
let mut semantic_return = self.semantic(&program, source_text, source_path);
|
||||||
if !semantic_return.errors.is_empty() {
|
if !semantic_return.errors.is_empty() {
|
||||||
self.handle_errors(semantic_return.errors);
|
self.handle_errors(semantic_return.errors);
|
||||||
return;
|
return;
|
||||||
|
|
@ -184,10 +184,9 @@ pub trait CompilerInterface {
|
||||||
&self,
|
&self,
|
||||||
program: &Program<'a>,
|
program: &Program<'a>,
|
||||||
source_text: &'a str,
|
source_text: &'a str,
|
||||||
source_type: SourceType,
|
|
||||||
source_path: &Path,
|
source_path: &Path,
|
||||||
) -> SemanticBuilderReturn<'a> {
|
) -> SemanticBuilderReturn<'a> {
|
||||||
SemanticBuilder::new(source_text, source_type)
|
SemanticBuilder::new(source_text)
|
||||||
.with_check_syntax_error(self.check_semantic_error())
|
.with_check_syntax_error(self.check_semantic_error())
|
||||||
.with_scope_tree_child_ids(self.semantic_child_scope_ids())
|
.with_scope_tree_child_ids(self.semantic_child_scope_ids())
|
||||||
.build_module_record(source_path, program)
|
.build_module_record(source_path, program)
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,7 @@ impl IsolatedLintHandler {
|
||||||
};
|
};
|
||||||
|
|
||||||
let program = allocator.alloc(ret.program);
|
let program = allocator.alloc(ret.program);
|
||||||
let semantic_ret = SemanticBuilder::new(javascript_source_text, source_type)
|
let semantic_ret = SemanticBuilder::new(javascript_source_text)
|
||||||
.with_cfg(true)
|
.with_cfg(true)
|
||||||
.with_trivias(ret.trivias)
|
.with_trivias(ret.trivias)
|
||||||
.with_check_syntax_error(true)
|
.with_check_syntax_error(true)
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,7 @@ fn main() -> std::io::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let program = allocator.alloc(ret.program);
|
let program = allocator.alloc(ret.program);
|
||||||
let semantic_ret =
|
let semantic_ret = SemanticBuilder::new(&source_text).with_trivias(ret.trivias).build(program);
|
||||||
SemanticBuilder::new(&source_text, source_type).with_trivias(ret.trivias).build(program);
|
|
||||||
|
|
||||||
let mut errors: Vec<OxcDiagnostic> = vec![];
|
let mut errors: Vec<OxcDiagnostic> = vec![];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -272,7 +272,7 @@ impl Runtime {
|
||||||
|
|
||||||
// Build the module record to unblock other threads from waiting for too long.
|
// Build the module record to unblock other threads from waiting for too long.
|
||||||
// The semantic model is not built at this stage.
|
// The semantic model is not built at this stage.
|
||||||
let semantic_builder = SemanticBuilder::new(source_text, source_type)
|
let semantic_builder = SemanticBuilder::new(source_text)
|
||||||
.with_cfg(true)
|
.with_cfg(true)
|
||||||
.with_build_jsdoc(true)
|
.with_build_jsdoc(true)
|
||||||
.with_trivias(trivias)
|
.with_trivias(trivias)
|
||||||
|
|
|
||||||
|
|
@ -317,8 +317,7 @@ mod test {
|
||||||
let source_type = SourceType::default();
|
let source_type = SourceType::default();
|
||||||
let parser_ret = Parser::new(&allocator, "", source_type).parse();
|
let parser_ret = Parser::new(&allocator, "", source_type).parse();
|
||||||
let program = allocator.alloc(parser_ret.program);
|
let program = allocator.alloc(parser_ret.program);
|
||||||
let semantic_ret =
|
let semantic_ret = SemanticBuilder::new("").with_cfg(true).build(program).semantic;
|
||||||
SemanticBuilder::new("", source_type).with_cfg(true).build(program).semantic;
|
|
||||||
let semantic_ret = Rc::new(semantic_ret);
|
let semantic_ret = Rc::new(semantic_ret);
|
||||||
|
|
||||||
let path = Path::new("foo.js");
|
let path = Path::new("foo.js");
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ impl Mangler {
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn build<'a>(mut self, program: &'a Program<'a>) -> Mangler {
|
pub fn build<'a>(mut self, program: &'a Program<'a>) -> Mangler {
|
||||||
let semantic = SemanticBuilder::new("", program.source_type).build(program).semantic;
|
let semantic = SemanticBuilder::new("").build(program).semantic;
|
||||||
|
|
||||||
// Mangle the symbol table by computing slots from the scope tree.
|
// Mangle the symbol table by computing slots from the scope tree.
|
||||||
// A slot is the occurrence index of a binding identifier inside a scope.
|
// A slot is the occurrence index of a binding identifier inside a scope.
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,8 @@ impl<'a> Compressor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self, program: &mut Program<'a>) {
|
pub fn build(self, program: &mut Program<'a>) {
|
||||||
let (symbols, scopes) = SemanticBuilder::new("", program.source_type)
|
let (symbols, scopes) =
|
||||||
.build(program)
|
SemanticBuilder::new("").build(program).semantic.into_symbol_table_and_scope_tree();
|
||||||
.semantic
|
|
||||||
.into_symbol_table_and_scope_tree();
|
|
||||||
self.build_with_symbols_and_scopes(symbols, scopes, program);
|
self.build_with_symbols_and_scopes(symbols, scopes, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ pub(crate) fn test(source_text: &str, expected: &str, config: InjectGlobalVariab
|
||||||
let allocator = Allocator::default();
|
let allocator = Allocator::default();
|
||||||
let ret = Parser::new(&allocator, source_text, source_type).parse();
|
let ret = Parser::new(&allocator, source_text, source_type).parse();
|
||||||
let program = allocator.alloc(ret.program);
|
let program = allocator.alloc(ret.program);
|
||||||
let (mut symbols, mut scopes) = SemanticBuilder::new(source_text, source_type)
|
let (mut symbols, mut scopes) = SemanticBuilder::new(source_text)
|
||||||
.build(program)
|
.build(program)
|
||||||
.semantic
|
.semantic
|
||||||
.into_symbol_table_and_scope_tree();
|
.into_symbol_table_and_scope_tree();
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ fn main() -> std::io::Result<()> {
|
||||||
std::fs::write(ast_file_path, format!("{:#?}", &program))?;
|
std::fs::write(ast_file_path, format!("{:#?}", &program))?;
|
||||||
println!("Wrote AST to: {}", &ast_file_name);
|
println!("Wrote AST to: {}", &ast_file_name);
|
||||||
|
|
||||||
let semantic = SemanticBuilder::new(&source_text, source_type)
|
let semantic = SemanticBuilder::new(&source_text)
|
||||||
.with_check_syntax_error(true)
|
.with_check_syntax_error(true)
|
||||||
.with_trivias(parser_ret.trivias)
|
.with_trivias(parser_ret.trivias)
|
||||||
.with_cfg(true)
|
.with_cfg(true)
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ fn main() -> std::io::Result<()> {
|
||||||
|
|
||||||
let program = allocator.alloc(parser_ret.program);
|
let program = allocator.alloc(parser_ret.program);
|
||||||
|
|
||||||
let semantic = SemanticBuilder::new(&source_text, source_type)
|
let semantic = SemanticBuilder::new(&source_text)
|
||||||
.build_module_record(path, program)
|
.build_module_record(path, program)
|
||||||
// Enable additional syntax checks not performed by the parser
|
// Enable additional syntax checks not performed by the parser
|
||||||
.with_check_syntax_error(true)
|
.with_check_syntax_error(true)
|
||||||
|
|
|
||||||
|
|
@ -117,14 +117,14 @@ pub struct SemanticBuilderReturn<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SemanticBuilder<'a> {
|
impl<'a> SemanticBuilder<'a> {
|
||||||
pub fn new(source_text: &'a str, source_type: SourceType) -> Self {
|
pub fn new(source_text: &'a str) -> Self {
|
||||||
let scope = ScopeTree::default();
|
let scope = ScopeTree::default();
|
||||||
let current_scope_id = scope.root_scope_id();
|
let current_scope_id = scope.root_scope_id();
|
||||||
|
|
||||||
let trivias = Trivias::default();
|
let trivias = Trivias::default();
|
||||||
Self {
|
Self {
|
||||||
source_text,
|
source_text,
|
||||||
source_type,
|
source_type: SourceType::default(),
|
||||||
trivias: trivias.clone(),
|
trivias: trivias.clone(),
|
||||||
errors: RefCell::new(vec![]),
|
errors: RefCell::new(vec![]),
|
||||||
current_node_id: AstNodeId::new(0),
|
current_node_id: AstNodeId::new(0),
|
||||||
|
|
@ -215,6 +215,7 @@ impl<'a> SemanticBuilder<'a> {
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
pub fn build(mut self, program: &Program<'a>) -> SemanticBuilderReturn<'a> {
|
pub fn build(mut self, program: &Program<'a>) -> SemanticBuilderReturn<'a> {
|
||||||
|
self.source_type = program.source_type;
|
||||||
if self.source_type.is_typescript_definition() {
|
if self.source_type.is_typescript_definition() {
|
||||||
let scope_id = self.scope.add_scope(None, AstNodeId::DUMMY, ScopeFlags::Top);
|
let scope_id = self.scope.add_scope(None, AstNodeId::DUMMY, ScopeFlags::Top);
|
||||||
program.scope_id.set(Some(scope_id));
|
program.scope_id.set(Some(scope_id));
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,7 @@ mod test {
|
||||||
let source_type = source_type.unwrap_or_default();
|
let source_type = source_type.unwrap_or_default();
|
||||||
let ret = Parser::new(allocator, source_text, source_type).parse();
|
let ret = Parser::new(allocator, source_text, source_type).parse();
|
||||||
let program = allocator.alloc(ret.program);
|
let program = allocator.alloc(ret.program);
|
||||||
let semantic = SemanticBuilder::new(source_text, source_type)
|
let semantic = SemanticBuilder::new(source_text)
|
||||||
.with_trivias(ret.trivias)
|
.with_trivias(ret.trivias)
|
||||||
.with_build_jsdoc(true)
|
.with_build_jsdoc(true)
|
||||||
.build(program)
|
.build(program)
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ mod test {
|
||||||
let source_type = SourceType::default();
|
let source_type = SourceType::default();
|
||||||
let ret = Parser::new(allocator, source_text, source_type).parse();
|
let ret = Parser::new(allocator, source_text, source_type).parse();
|
||||||
let program = allocator.alloc(ret.program);
|
let program = allocator.alloc(ret.program);
|
||||||
let semantic = SemanticBuilder::new(source_text, source_type)
|
let semantic = SemanticBuilder::new(source_text)
|
||||||
.with_trivias(ret.trivias)
|
.with_trivias(ret.trivias)
|
||||||
.with_build_jsdoc(true)
|
.with_build_jsdoc(true)
|
||||||
.build(program)
|
.build(program)
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,7 @@ mod test {
|
||||||
let source_type = SourceType::default();
|
let source_type = SourceType::default();
|
||||||
let ret = Parser::new(allocator, source_text, source_type).parse();
|
let ret = Parser::new(allocator, source_text, source_type).parse();
|
||||||
let program = allocator.alloc(ret.program);
|
let program = allocator.alloc(ret.program);
|
||||||
let semantic = SemanticBuilder::new(source_text, source_type)
|
let semantic = SemanticBuilder::new(source_text)
|
||||||
.with_trivias(ret.trivias)
|
.with_trivias(ret.trivias)
|
||||||
.with_build_jsdoc(true)
|
.with_build_jsdoc(true)
|
||||||
.build(program)
|
.build(program)
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ mod tests {
|
||||||
let parse = oxc_parser::Parser::new(allocator, source, source_type).parse();
|
let parse = oxc_parser::Parser::new(allocator, source, source_type).parse();
|
||||||
assert!(parse.errors.is_empty());
|
assert!(parse.errors.is_empty());
|
||||||
let program = allocator.alloc(parse.program);
|
let program = allocator.alloc(parse.program);
|
||||||
let semantic = SemanticBuilder::new(source, source_type).build(program);
|
let semantic = SemanticBuilder::new(source).build(program);
|
||||||
assert!(semantic.errors.is_empty(), "Parse error: {}", semantic.errors[0]);
|
assert!(semantic.errors.is_empty(), "Parse error: {}", semantic.errors[0]);
|
||||||
semantic.semantic
|
semantic.semantic
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ mod module_record_tests {
|
||||||
let allocator = Allocator::default();
|
let allocator = Allocator::default();
|
||||||
let ret = Parser::new(&allocator, source_text, source_type).parse();
|
let ret = Parser::new(&allocator, source_text, source_type).parse();
|
||||||
let program = allocator.alloc(ret.program);
|
let program = allocator.alloc(ret.program);
|
||||||
let semantic_ret = SemanticBuilder::new(source_text, source_type)
|
let semantic_ret = SemanticBuilder::new(source_text)
|
||||||
.with_trivias(ret.trivias)
|
.with_trivias(ret.trivias)
|
||||||
.build_module_record(Path::new(""), program)
|
.build_module_record(Path::new(""), program)
|
||||||
.build(program);
|
.build(program);
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ pub fn check_semantic_after_transform(
|
||||||
// so the cloned AST will be "clean" of all semantic data, as if it had come fresh from the parser.
|
// so the cloned AST will be "clean" of all semantic data, as if it had come fresh from the parser.
|
||||||
let allocator = Allocator::default();
|
let allocator = Allocator::default();
|
||||||
let program = program.clone_in(&allocator);
|
let program = program.clone_in(&allocator);
|
||||||
let (symbols_rebuilt, scopes_rebuilt) = SemanticBuilder::new("", program.source_type)
|
let (symbols_rebuilt, scopes_rebuilt) = SemanticBuilder::new("")
|
||||||
.with_scope_tree_child_ids(scopes_after_transform.has_child_ids())
|
.with_scope_tree_child_ids(scopes_after_transform.has_child_ids())
|
||||||
.build(&program)
|
.build(&program)
|
||||||
.semantic
|
.semantic
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ impl<'a> SemanticTester<'a> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let program = self.allocator.alloc(parse.program);
|
let program = self.allocator.alloc(parse.program);
|
||||||
SemanticBuilder::new(self.source_text, self.source_type)
|
SemanticBuilder::new(self.source_text)
|
||||||
.with_check_syntax_error(true)
|
.with_check_syntax_error(true)
|
||||||
.with_trivias(parse.trivias)
|
.with_trivias(parse.trivias)
|
||||||
.with_cfg(self.cfg)
|
.with_cfg(self.cfg)
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ fn analyze(path: &Path, source_text: &str) -> String {
|
||||||
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();
|
||||||
let semantic = SemanticBuilder::new(source_text, source_type).build(&ret.program).semantic;
|
let semantic = SemanticBuilder::new(source_text).build(&ret.program).semantic;
|
||||||
|
|
||||||
let scopes = get_scope_snapshot(&semantic, vec![semantic.scopes().root_scope_id()].into_iter());
|
let scopes = get_scope_snapshot(&semantic, vec![semantic.scopes().root_scope_id()].into_iter());
|
||||||
let value: serde_json::Value = serde_json::from_str(scopes.as_str()).unwrap();
|
let value: serde_json::Value = serde_json::from_str(scopes.as_str()).unwrap();
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ fn main() {
|
||||||
|
|
||||||
let mut program = ret.program;
|
let mut program = ret.program;
|
||||||
|
|
||||||
let (symbols, scopes) = SemanticBuilder::new(&source_text, source_type)
|
let (symbols, scopes) = SemanticBuilder::new(&source_text)
|
||||||
.build(&program)
|
.build(&program)
|
||||||
.semantic
|
.semantic
|
||||||
.into_symbol_table_and_scope_tree();
|
.into_symbol_table_and_scope_tree();
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ impl Oxc {
|
||||||
self.ir = format!("{:#?}", program.body);
|
self.ir = format!("{:#?}", program.body);
|
||||||
self.ast = program.serialize(&self.serializer)?;
|
self.ast = program.serialize(&self.serializer)?;
|
||||||
|
|
||||||
let semantic_ret = SemanticBuilder::new(source_text, source_type)
|
let semantic_ret = SemanticBuilder::new(source_text)
|
||||||
.with_trivias(trivias.clone())
|
.with_trivias(trivias.clone())
|
||||||
.with_check_syntax_error(true)
|
.with_check_syntax_error(true)
|
||||||
.build_module_record(&path, &program)
|
.build_module_record(&path, &program)
|
||||||
|
|
@ -201,7 +201,7 @@ impl Oxc {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.run_linter(&run_options, source_text, source_type, &path, &trivias, &program);
|
self.run_linter(&run_options, source_text, &path, &trivias, &program);
|
||||||
|
|
||||||
self.run_prettier(&run_options, source_text, source_type);
|
self.run_prettier(&run_options, source_text, source_type);
|
||||||
|
|
||||||
|
|
@ -280,14 +280,13 @@ impl Oxc {
|
||||||
&mut self,
|
&mut self,
|
||||||
run_options: &OxcRunOptions,
|
run_options: &OxcRunOptions,
|
||||||
source_text: &str,
|
source_text: &str,
|
||||||
source_type: SourceType,
|
|
||||||
path: &Path,
|
path: &Path,
|
||||||
trivias: &Trivias,
|
trivias: &Trivias,
|
||||||
program: &Program,
|
program: &Program,
|
||||||
) {
|
) {
|
||||||
// Only lint if there are no syntax errors
|
// Only lint if there are no syntax errors
|
||||||
if run_options.lint.unwrap_or_default() && self.diagnostics.borrow().is_empty() {
|
if run_options.lint.unwrap_or_default() && self.diagnostics.borrow().is_empty() {
|
||||||
let semantic_ret = SemanticBuilder::new(source_text, source_type)
|
let semantic_ret = SemanticBuilder::new(source_text)
|
||||||
.with_cfg(true)
|
.with_cfg(true)
|
||||||
.with_trivias(trivias.clone())
|
.with_trivias(trivias.clone())
|
||||||
.build_module_record(path, program)
|
.build_module_record(path, program)
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ pub fn transform(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transpile(ctx: &TransformContext<'_>) -> CodegenReturn {
|
fn transpile(ctx: &TransformContext<'_>) -> CodegenReturn {
|
||||||
let (symbols, scopes) = SemanticBuilder::new(ctx.source_text(), ctx.source_type())
|
let (symbols, scopes) = SemanticBuilder::new(ctx.source_text())
|
||||||
.build(&ctx.program())
|
.build(&ctx.program())
|
||||||
.semantic
|
.semantic
|
||||||
.into_symbol_table_and_scope_tree();
|
.into_symbol_table_and_scope_tree();
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ fn bench_linter(criterion: &mut Criterion) {
|
||||||
let allocator = Allocator::default();
|
let allocator = Allocator::default();
|
||||||
let ret = Parser::new(&allocator, source_text, source_type).parse();
|
let ret = Parser::new(&allocator, source_text, source_type).parse();
|
||||||
let program = allocator.alloc(ret.program);
|
let program = allocator.alloc(ret.program);
|
||||||
let semantic_ret = SemanticBuilder::new(source_text, source_type)
|
let semantic_ret = SemanticBuilder::new(source_text)
|
||||||
.with_trivias(ret.trivias)
|
.with_trivias(ret.trivias)
|
||||||
.with_cfg(true)
|
.with_cfg(true)
|
||||||
.build_module_record(Path::new(""), program)
|
.build_module_record(Path::new(""), program)
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ fn bench_semantic(criterion: &mut Criterion) {
|
||||||
// We return `error`s to be dropped outside of the measured section, as usually
|
// We return `error`s to be dropped outside of the measured section, as usually
|
||||||
// code would have no errors. One of our benchmarks `cal.com.tsx` has a lot of errors,
|
// code would have no errors. One of our benchmarks `cal.com.tsx` has a lot of errors,
|
||||||
// but that's atypical, so don't want to include it in benchmark time.
|
// but that's atypical, so don't want to include it in benchmark time.
|
||||||
let ret = SemanticBuilder::new(source_text, source_type)
|
let ret = SemanticBuilder::new(source_text)
|
||||||
.with_trivias(ret.trivias.clone())
|
.with_trivias(ret.trivias.clone())
|
||||||
.with_build_jsdoc(true)
|
.with_build_jsdoc(true)
|
||||||
.build_module_record(Path::new(""), program)
|
.build_module_record(Path::new(""), program)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ fn bench_transformer(criterion: &mut Criterion) {
|
||||||
let ParserReturn { trivias, program, .. } =
|
let ParserReturn { trivias, program, .. } =
|
||||||
Parser::new(&allocator, source_text, source_type).parse();
|
Parser::new(&allocator, source_text, source_type).parse();
|
||||||
let program = allocator.alloc(program);
|
let program = allocator.alloc(program);
|
||||||
let (symbols, scopes) = SemanticBuilder::new(source_text, source_type)
|
let (symbols, scopes) = SemanticBuilder::new(source_text)
|
||||||
.build(program)
|
.build(program)
|
||||||
.semantic
|
.semantic
|
||||||
.into_symbol_table_and_scope_tree();
|
.into_symbol_table_and_scope_tree();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue