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
5 changes: 2 additions & 3 deletions crates/oxc/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ pub trait CompilerInterface {

/* Semantic */

let mut semantic_return = self.semantic(&program, source_path);
let mut semantic_return = self.semantic(&program);
if !semantic_return.errors.is_empty() {
self.handle_errors(semantic_return.errors);
return;
Expand Down Expand Up @@ -231,7 +231,7 @@ pub trait CompilerInterface {
Parser::new(allocator, source_text, source_type).with_options(self.parse_options()).parse()
}

fn semantic<'a>(&self, program: &Program<'a>, source_path: &Path) -> SemanticBuilderReturn<'a> {
fn semantic<'a>(&self, program: &Program<'a>) -> SemanticBuilderReturn<'a> {
let mut builder = SemanticBuilder::new();

if self.transform_options().is_some() {
Expand All @@ -242,7 +242,6 @@ pub trait CompilerInterface {
builder
.with_check_syntax_error(self.check_semantic_error())
.with_scope_tree_child_ids(self.semantic_child_scope_ids())
.build_module_record(source_path, program)
.build(program)
}

Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/frameworks.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{hash, path::Path};

use bitflags::bitflags;
use oxc_semantic::ModuleRecord;
use oxc_syntax::module_record::ModuleRecord;

bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down
5 changes: 3 additions & 2 deletions crates/oxc_linter/src/rules/import/export.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::path::PathBuf;

use rustc_hash::{FxHashMap, FxHashSet};

use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_macros::declare_oxc_lint;
use oxc_semantic::ModuleRecord;
use oxc_span::{CompactStr, Span};
use rustc_hash::{FxHashMap, FxHashSet};
use oxc_syntax::module_record::ModuleRecord;

use crate::{context::LintContext, rule::Rule};

Expand Down
6 changes: 4 additions & 2 deletions crates/oxc_linter/src/rules/import/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ use oxc_ast::{
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::{AstNode, ModuleRecord};
use oxc_semantic::AstNode;
use oxc_span::{GetSpan, Span};
use oxc_syntax::module_record::{ExportExportName, ExportImportName, ImportImportName};
use oxc_syntax::module_record::{
ExportExportName, ExportImportName, ImportImportName, ModuleRecord,
};

use crate::{context::LintContext, rule::Rule};

Expand Down
6 changes: 4 additions & 2 deletions crates/oxc_linter/src/rules/oxc/no_barrel_file.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
use oxc_macros::declare_oxc_lint;
use oxc_semantic::ModuleRecord;
use oxc_syntax::module_graph_visitor::{ModuleGraphVisitorBuilder, VisitFoldWhile};
use oxc_syntax::{
module_graph_visitor::{ModuleGraphVisitorBuilder, VisitFoldWhile},
module_record::ModuleRecord,
};

use crate::{context::LintContext, rule::Rule};

Expand Down
5 changes: 3 additions & 2 deletions crates/oxc_linter/src/service/module_cache.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::{
num::NonZeroUsize,
path::Path,
sync::{Arc, Condvar, Mutex},
};

use dashmap::{mapref::one::Ref, DashMap};
use oxc_semantic::ModuleRecord;
use rustc_hash::{FxBuildHasher, FxHashMap};
use std::num::NonZeroUsize;

use oxc_syntax::module_record::ModuleRecord;

type FxDashMap<K, V> = DashMap<K, V, FxBuildHasher>;

Expand Down
12 changes: 8 additions & 4 deletions crates/oxc_linter/src/service/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ use oxc_allocator::Allocator;
use oxc_diagnostics::{DiagnosticSender, DiagnosticService, Error, OxcDiagnostic};
use oxc_parser::{ParseOptions, Parser};
use oxc_resolver::Resolver;
use oxc_semantic::{ModuleRecord, SemanticBuilder};
use oxc_semantic::SemanticBuilder;
use oxc_span::{SourceType, VALID_EXTENSIONS};
use oxc_syntax::module_record::ModuleRecord;
use rayon::{iter::ParallelBridge, prelude::ParallelIterator};
use rustc_hash::FxHashSet;

Expand Down Expand Up @@ -215,9 +216,11 @@ impl Runtime {
.with_cfg(true)
.with_scope_tree_child_ids(true)
.with_build_jsdoc(true)
.with_check_syntax_error(check_syntax_errors)
.build_module_record(path, &ret.program);
let module_record = semantic_builder.module_record();
.with_check_syntax_error(check_syntax_errors);

let mut module_record = ret.module_record;
module_record.resolved_absolute_path = path.to_path_buf();
let module_record = Arc::new(module_record);

if self.resolver.is_some() {
self.modules.add_resolved_module(path, Arc::clone(&module_record));
Expand Down Expand Up @@ -294,6 +297,7 @@ impl Runtime {
};

let mut semantic = semantic_ret.semantic;
semantic.set_module_record(&module_record);
semantic.set_irregular_whitespaces(ret.irregular_whitespaces);
self.linter.run(path, Rc::new(semantic))
}
Expand Down
1 change: 0 additions & 1 deletion crates/oxc_module_lexer/tests/integration/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ pub fn parse(source: &str) -> ModuleLexer {
let allocator = Allocator::default();
let source_type = SourceType::mjs();
let ret = Parser::new(&allocator, source, source_type).parse();
assert!(ret.errors.is_empty(), "{source} should not produce errors.\n{:?}", ret.errors);
let module_lexer = oxc_module_lexer::ModuleLexer::new().build(&ret.program);
// Copy data over because `ModuleLexer<'a>` can't be returned
ModuleLexer {
Expand Down
8 changes: 8 additions & 0 deletions crates/oxc_parser/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,14 @@ pub fn cover_initialized_name(span: Span) -> OxcDiagnostic {
.with_label(span)
}

#[cold]
pub fn duplicate_export(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic {
OxcDiagnostic::error(format!("Duplicated export '{x0}'")).with_labels([
span1.label("Export has already been declared here"),
span2.label("It cannot be redeclared here"),
])
}

// ================================= MODIFIERS =================================

#[cold]
Expand Down
7 changes: 5 additions & 2 deletions crates/oxc_parser/src/js/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ impl<'a> ParserImpl<'a> {
}
let stmt = self.parse_statement_list_item(StatementContext::StatementList)?;

if is_top_level && stmt.is_module_declaration() {
self.set_source_type_to_module_if_unambiguous();
if is_top_level {
if let Some(module_decl) = stmt.as_module_declaration() {
self.set_source_type_to_module_if_unambiguous();
self.module_record_builder.visit_module_declaration(module_decl);
}
}

// Section 11.2.1 Directive Prologue
Expand Down
27 changes: 25 additions & 2 deletions crates/oxc_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
mod context;
mod cursor;
mod modifiers;
mod module_record;
mod state;

mod js;
Expand All @@ -84,17 +85,19 @@ mod lexer;
#[doc(hidden)]
pub mod lexer;

use context::{Context, StatementContext};
use oxc_allocator::{Allocator, Box as ArenaBox};
use oxc_ast::{
ast::{Expression, Program},
AstBuilder,
};
use oxc_diagnostics::{OxcDiagnostic, Result};
use oxc_span::{ModuleKind, SourceType, Span};
use oxc_syntax::module_record::ModuleRecord;

use crate::{
context::{Context, StatementContext},
lexer::{Kind, Lexer, Token},
module_record::ModuleRecordBuilder,
state::ParserState,
};

Expand Down Expand Up @@ -150,6 +153,9 @@ pub struct ParserReturn<'a> {
/// semantic analysis with syntax error checking enabled.
pub program: Program<'a>,

/// See <https://tc39.es/ecma262/#sec-abstract-module-records>
pub module_record: ModuleRecord,

/// Syntax errors encountered while parsing.
///
/// This list is not comprehensive. Oxc offloads more-expensive checks to [semantic
Expand Down Expand Up @@ -363,6 +369,9 @@ struct ParserImpl<'a> {
/// Ast builder for creating AST nodes
ast: AstBuilder<'a>,

/// Module Record Builder
module_record_builder: ModuleRecordBuilder,

/// Precomputed typescript detection
is_ts: bool,
}
Expand All @@ -380,6 +389,8 @@ impl<'a> ParserImpl<'a> {
options: ParseOptions,
unique: UniquePromise,
) -> Self {
let mut module_record_builder = ModuleRecordBuilder::default();
module_record_builder.module_record.not_esm = true;
Self {
options,
lexer: Lexer::new(allocator, source_text, source_type, unique),
Expand All @@ -391,6 +402,7 @@ impl<'a> ParserImpl<'a> {
state: ParserState::default(),
ctx: Self::default_context(source_type, options),
ast: AstBuilder::new(allocator),
module_record_builder,
is_ts: source_type.is_typescript(),
}
}
Expand Down Expand Up @@ -432,10 +444,21 @@ impl<'a> ParserImpl<'a> {
errors.reserve(self.lexer.errors.len() + self.errors.len());
errors.extend(self.lexer.errors);
errors.extend(self.errors);
// Skip checking for exports in TypeScript {
if !self.source_type.is_typescript() {
errors.extend(self.module_record_builder.errors());
}
}
let irregular_whitespaces =
self.lexer.trivia_builder.irregular_whitespaces.into_boxed_slice();
ParserReturn { program, errors, irregular_whitespaces, panicked, is_flow_language }
ParserReturn {
program,
module_record: self.module_record_builder.build(),
errors,
irregular_whitespaces,
panicked,
is_flow_language,
}
}

pub fn parse_expression(mut self) -> std::result::Result<Expression<'a>, Vec<OxcDiagnostic>> {
Expand Down
Loading