mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
refactor(semantic)!: remove ModuleRecord from Semantic (#7548)
`ModuleRecord` will eventually be moved to be linter specific thing for cross module data sharing, which means we can add more data to it.
This commit is contained in:
parent
8a788b8f4b
commit
0be5233c84
18 changed files with 91 additions and 55 deletions
|
|
@ -290,9 +290,10 @@ impl IsolatedLintHandler {
|
||||||
return Some(Self::wrap_diagnostics(path, &source_text, reports, start));
|
return Some(Self::wrap_diagnostics(path, &source_text, reports, start));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let module_record = Arc::new(ret.module_record);
|
||||||
let mut semantic = semantic_ret.semantic;
|
let mut semantic = semantic_ret.semantic;
|
||||||
semantic.set_irregular_whitespaces(ret.irregular_whitespaces);
|
semantic.set_irregular_whitespaces(ret.irregular_whitespaces);
|
||||||
let result = self.linter.run(path, Rc::new(semantic));
|
let result = self.linter.run(path, Rc::new(semantic), module_record);
|
||||||
|
|
||||||
let reports = result
|
let reports = result
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
use std::{cell::RefCell, path::Path, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
use oxc_semantic::Semantic;
|
use oxc_semantic::Semantic;
|
||||||
use oxc_span::SourceType;
|
use oxc_span::SourceType;
|
||||||
use std::{cell::RefCell, path::Path, rc::Rc, sync::Arc};
|
use oxc_syntax::module_record::ModuleRecord;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{LintConfig, LintPlugins},
|
config::{LintConfig, LintPlugins},
|
||||||
|
|
@ -37,6 +39,8 @@ pub(crate) struct ContextHost<'a> {
|
||||||
/// Shared semantic information about the file being linted, which includes scopes, symbols
|
/// Shared semantic information about the file being linted, which includes scopes, symbols
|
||||||
/// and AST nodes. See [`Semantic`].
|
/// and AST nodes. See [`Semantic`].
|
||||||
pub(super) semantic: Rc<Semantic<'a>>,
|
pub(super) semantic: Rc<Semantic<'a>>,
|
||||||
|
/// Cross module information.
|
||||||
|
pub(super) module_record: Arc<ModuleRecord>,
|
||||||
/// Information about specific rules that should be disabled or enabled, via comment directives like
|
/// Information about specific rules that should be disabled or enabled, via comment directives like
|
||||||
/// `eslint-disable` or `eslint-disable-next-line`.
|
/// `eslint-disable` or `eslint-disable-next-line`.
|
||||||
pub(super) disable_directives: DisableDirectives<'a>,
|
pub(super) disable_directives: DisableDirectives<'a>,
|
||||||
|
|
@ -67,6 +71,7 @@ impl<'a> ContextHost<'a> {
|
||||||
pub fn new<P: AsRef<Path>>(
|
pub fn new<P: AsRef<Path>>(
|
||||||
file_path: P,
|
file_path: P,
|
||||||
semantic: Rc<Semantic<'a>>,
|
semantic: Rc<Semantic<'a>>,
|
||||||
|
module_record: Arc<ModuleRecord>,
|
||||||
options: LintOptions,
|
options: LintOptions,
|
||||||
config: Arc<LintConfig>,
|
config: Arc<LintConfig>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
@ -87,6 +92,7 @@ impl<'a> ContextHost<'a> {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
semantic,
|
semantic,
|
||||||
|
module_record,
|
||||||
disable_directives,
|
disable_directives,
|
||||||
diagnostics: RefCell::new(Vec::with_capacity(DIAGNOSTICS_INITIAL_CAPACITY)),
|
diagnostics: RefCell::new(Vec::with_capacity(DIAGNOSTICS_INITIAL_CAPACITY)),
|
||||||
fix: options.fix,
|
fix: options.fix,
|
||||||
|
|
@ -119,6 +125,12 @@ impl<'a> ContextHost<'a> {
|
||||||
&self.semantic
|
&self.semantic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shared reference to the [`ModuleRecord`] of the file.
|
||||||
|
#[inline]
|
||||||
|
pub fn module_record(&self) -> &ModuleRecord {
|
||||||
|
&self.module_record
|
||||||
|
}
|
||||||
|
|
||||||
/// Path to the file being linted.
|
/// Path to the file being linted.
|
||||||
///
|
///
|
||||||
/// When created from a [`LintService`](`crate::service::LintService`), this
|
/// When created from a [`LintService`](`crate::service::LintService`), this
|
||||||
|
|
@ -214,9 +226,9 @@ impl<'a> ContextHost<'a> {
|
||||||
if self.plugins.has_test() {
|
if self.plugins.has_test() {
|
||||||
// let mut test_flags = FrameworkFlags::empty();
|
// let mut test_flags = FrameworkFlags::empty();
|
||||||
|
|
||||||
let vitest_like = frameworks::has_vitest_imports(self.semantic.module_record());
|
let vitest_like = frameworks::has_vitest_imports(self.module_record());
|
||||||
let jest_like = frameworks::is_jestlike_file(&self.file_path)
|
let jest_like = frameworks::is_jestlike_file(&self.file_path)
|
||||||
|| frameworks::has_jest_imports(self.semantic.module_record());
|
|| frameworks::has_jest_imports(self.module_record());
|
||||||
|
|
||||||
self.frameworks.set(FrameworkFlags::Vitest, vitest_like);
|
self.frameworks.set(FrameworkFlags::Vitest, vitest_like);
|
||||||
self.frameworks.set(FrameworkFlags::Jest, jest_like);
|
self.frameworks.set(FrameworkFlags::Jest, jest_like);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use oxc_cfg::ControlFlowGraph;
|
||||||
use oxc_diagnostics::{OxcDiagnostic, Severity};
|
use oxc_diagnostics::{OxcDiagnostic, Severity};
|
||||||
use oxc_semantic::Semantic;
|
use oxc_semantic::Semantic;
|
||||||
use oxc_span::{GetSpan, Span};
|
use oxc_span::{GetSpan, Span};
|
||||||
|
use oxc_syntax::module_record::ModuleRecord;
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
use crate::rule::RuleFixMeta;
|
use crate::rule::RuleFixMeta;
|
||||||
|
|
@ -105,6 +106,11 @@ impl<'a> LintContext<'a> {
|
||||||
&self.parent.semantic
|
&self.parent.semantic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn module_record(&self) -> &ModuleRecord {
|
||||||
|
self.parent.module_record()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the control flow graph for the current program.
|
/// Get the control flow graph for the current program.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cfg(&self) -> &ControlFlowGraph {
|
pub fn cfg(&self) -> &ControlFlowGraph {
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,10 @@ mod utils;
|
||||||
pub mod loader;
|
pub mod loader;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
|
|
||||||
use crate::config::ResolvedLinterState;
|
|
||||||
use std::{io::Write, path::Path, rc::Rc, sync::Arc};
|
use std::{io::Write, path::Path, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
use config::{ConfigStore, LintConfig};
|
|
||||||
use context::ContextHost;
|
|
||||||
use options::LintOptions;
|
|
||||||
use oxc_semantic::{AstNode, Semantic};
|
use oxc_semantic::{AstNode, Semantic};
|
||||||
use utils::iter_possible_jest_call_node;
|
use oxc_syntax::module_record::ModuleRecord;
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
builder::{LinterBuilder, LinterBuilderError},
|
builder::{LinterBuilder, LinterBuilderError},
|
||||||
|
|
@ -41,10 +37,15 @@ pub use crate::{
|
||||||
service::{LintService, LintServiceOptions},
|
service::{LintService, LintServiceOptions},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{OxlintEnv, OxlintGlobals, OxlintSettings},
|
config::{
|
||||||
|
ConfigStore, LintConfig, OxlintEnv, OxlintGlobals, OxlintSettings, ResolvedLinterState,
|
||||||
|
},
|
||||||
|
context::ContextHost,
|
||||||
fixer::{Fixer, Message},
|
fixer::{Fixer, Message},
|
||||||
|
options::LintOptions,
|
||||||
rules::RuleEnum,
|
rules::RuleEnum,
|
||||||
table::RuleTable,
|
table::RuleTable,
|
||||||
|
utils::iter_possible_jest_call_node,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
|
@ -110,10 +111,16 @@ impl Linter {
|
||||||
self.config.rules()
|
self.config.rules()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run<'a>(&self, path: &Path, semantic: Rc<Semantic<'a>>) -> Vec<Message<'a>> {
|
pub fn run<'a>(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
semantic: Rc<Semantic<'a>>,
|
||||||
|
module_record: Arc<ModuleRecord>,
|
||||||
|
) -> Vec<Message<'a>> {
|
||||||
// Get config + rules for this file. Takes base rules and applies glob-based overrides.
|
// Get config + rules for this file. Takes base rules and applies glob-based overrides.
|
||||||
let ResolvedLinterState { rules, config } = self.config.resolve(path);
|
let ResolvedLinterState { rules, config } = self.config.resolve(path);
|
||||||
let ctx_host = Rc::new(ContextHost::new(path, semantic, self.options, config));
|
let ctx_host =
|
||||||
|
Rc::new(ContextHost::new(path, semantic, module_record, self.options, config));
|
||||||
|
|
||||||
let rules = rules
|
let rules = rules
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
//! consider variables ignored by name pattern, but by where they are declared.
|
//! consider variables ignored by name pattern, but by where they are declared.
|
||||||
use oxc_ast::{ast::*, AstKind};
|
use oxc_ast::{ast::*, AstKind};
|
||||||
use oxc_semantic::{NodeId, Semantic};
|
use oxc_semantic::{NodeId, Semantic};
|
||||||
|
use oxc_syntax::module_record::ModuleRecord;
|
||||||
|
|
||||||
use super::{options::ArgsOption, NoUnusedVars, Symbol};
|
use super::{options::ArgsOption, NoUnusedVars, Symbol};
|
||||||
use crate::rules::eslint::no_unused_vars::binding_pattern::{BindingContext, HasAnyUsedBinding};
|
use crate::rules::eslint::no_unused_vars::binding_pattern::{BindingContext, HasAnyUsedBinding};
|
||||||
|
|
@ -120,6 +121,7 @@ impl NoUnusedVars {
|
||||||
pub(super) fn is_allowed_argument<'a>(
|
pub(super) fn is_allowed_argument<'a>(
|
||||||
&self,
|
&self,
|
||||||
semantic: &Semantic<'a>,
|
semantic: &Semantic<'a>,
|
||||||
|
module_record: &ModuleRecord,
|
||||||
symbol: &Symbol<'_, 'a>,
|
symbol: &Symbol<'_, 'a>,
|
||||||
param: &FormalParameter<'a>,
|
param: &FormalParameter<'a>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
|
@ -178,7 +180,7 @@ impl NoUnusedVars {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ctx = BindingContext { options: self, semantic };
|
let ctx = BindingContext { options: self, semantic, module_record };
|
||||||
params
|
params
|
||||||
.items
|
.items
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use oxc_ast::ast::*;
|
use oxc_ast::ast::*;
|
||||||
use oxc_semantic::{Semantic, SymbolId};
|
use oxc_semantic::{Semantic, SymbolId};
|
||||||
|
use oxc_syntax::module_record::ModuleRecord;
|
||||||
|
|
||||||
use super::{symbol::Symbol, NoUnusedVars};
|
use super::{symbol::Symbol, NoUnusedVars};
|
||||||
|
|
||||||
|
|
@ -7,16 +8,18 @@ use super::{symbol::Symbol, NoUnusedVars};
|
||||||
pub(super) struct BindingContext<'s, 'a> {
|
pub(super) struct BindingContext<'s, 'a> {
|
||||||
pub options: &'s NoUnusedVars,
|
pub options: &'s NoUnusedVars,
|
||||||
pub semantic: &'s Semantic<'a>,
|
pub semantic: &'s Semantic<'a>,
|
||||||
|
pub module_record: &'s ModuleRecord,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s, 'a> BindingContext<'s, 'a> {
|
impl<'s, 'a> BindingContext<'s, 'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn symbol(&self, symbol_id: SymbolId) -> Symbol<'s, 'a> {
|
pub fn symbol(&self, module_record: &'s ModuleRecord, symbol_id: SymbolId) -> Symbol<'s, 'a> {
|
||||||
Symbol::new(self.semantic, symbol_id)
|
Symbol::new(self.semantic, module_record, symbol_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn has_usages(&self, symbol_id: SymbolId) -> bool {
|
pub fn has_usages(&self, symbol_id: SymbolId, module_record: &'s ModuleRecord) -> bool {
|
||||||
self.symbol(symbol_id).has_usages(self.options)
|
self.symbol(module_record, symbol_id).has_usages(self.options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +47,7 @@ impl<'a> HasAnyUsedBinding<'a> for BindingPatternKind<'a> {
|
||||||
|
|
||||||
impl<'a> HasAnyUsedBinding<'a> for BindingIdentifier<'a> {
|
impl<'a> HasAnyUsedBinding<'a> for BindingIdentifier<'a> {
|
||||||
fn has_any_used_binding(&self, ctx: BindingContext<'_, 'a>) -> bool {
|
fn has_any_used_binding(&self, ctx: BindingContext<'_, 'a>) -> bool {
|
||||||
ctx.has_usages(self.symbol_id())
|
ctx.has_usages(self.symbol_id(), ctx.module_record)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> HasAnyUsedBinding<'a> for ObjectPattern<'a> {
|
impl<'a> HasAnyUsedBinding<'a> for ObjectPattern<'a> {
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ impl Rule for NoUnusedVars {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_on_symbol(&self, symbol_id: SymbolId, ctx: &LintContext<'_>) {
|
fn run_on_symbol(&self, symbol_id: SymbolId, ctx: &LintContext<'_>) {
|
||||||
let symbol = Symbol::new(ctx.semantic().as_ref(), symbol_id);
|
let symbol = Symbol::new(ctx.semantic().as_ref(), ctx.module_record(), symbol_id);
|
||||||
if Self::should_skip_symbol(&symbol) {
|
if Self::should_skip_symbol(&symbol) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +294,12 @@ impl NoUnusedVars {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
AstKind::FormalParameter(param) => {
|
AstKind::FormalParameter(param) => {
|
||||||
if self.is_allowed_argument(ctx.semantic().as_ref(), symbol, param) {
|
if self.is_allowed_argument(
|
||||||
|
ctx.semantic().as_ref(),
|
||||||
|
ctx.module_record(),
|
||||||
|
symbol,
|
||||||
|
param,
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.diagnostic(diagnostic::param(symbol, &self.args_ignore_pattern));
|
ctx.diagnostic(diagnostic::param(symbol, &self.args_ignore_pattern));
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,12 @@ use oxc_semantic::{
|
||||||
SymbolTable,
|
SymbolTable,
|
||||||
};
|
};
|
||||||
use oxc_span::{GetSpan, Span};
|
use oxc_span::{GetSpan, Span};
|
||||||
|
use oxc_syntax::module_record::ModuleRecord;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(super) struct Symbol<'s, 'a> {
|
pub(super) struct Symbol<'s, 'a> {
|
||||||
semantic: &'s Semantic<'a>,
|
semantic: &'s Semantic<'a>,
|
||||||
|
module_record: &'s ModuleRecord,
|
||||||
id: SymbolId,
|
id: SymbolId,
|
||||||
flags: SymbolFlags,
|
flags: SymbolFlags,
|
||||||
span: OnceCell<Span>,
|
span: OnceCell<Span>,
|
||||||
|
|
@ -29,9 +31,13 @@ impl PartialEq for Symbol<'_, '_> {
|
||||||
|
|
||||||
// constructor and simple getters
|
// constructor and simple getters
|
||||||
impl<'s, 'a> Symbol<'s, 'a> {
|
impl<'s, 'a> Symbol<'s, 'a> {
|
||||||
pub fn new(semantic: &'s Semantic<'a>, symbol_id: SymbolId) -> Self {
|
pub fn new(
|
||||||
|
semantic: &'s Semantic<'a>,
|
||||||
|
module_record: &'s ModuleRecord,
|
||||||
|
symbol_id: SymbolId,
|
||||||
|
) -> Self {
|
||||||
let flags = semantic.symbols().get_flags(symbol_id);
|
let flags = semantic.symbols().get_flags(symbol_id);
|
||||||
Self { semantic, id: symbol_id, flags, span: OnceCell::new() }
|
Self { semantic, module_record, id: symbol_id, flags, span: OnceCell::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -172,7 +178,7 @@ impl<'a> Symbol<'_, 'a> {
|
||||||
pub fn is_exported(&self) -> bool {
|
pub fn is_exported(&self) -> bool {
|
||||||
let is_in_exportable_scope = self.is_root() || self.is_in_ts_namespace();
|
let is_in_exportable_scope = self.is_root() || self.is_in_ts_namespace();
|
||||||
is_in_exportable_scope
|
is_in_exportable_scope
|
||||||
&& (self.semantic.module_record().exported_bindings.contains_key(self.name())
|
&& (self.module_record.exported_bindings.contains_key(self.name())
|
||||||
|| self.in_export_node())
|
|| self.in_export_node())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ impl Rule for Named {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let module_record = semantic.module_record();
|
let module_record = ctx.module_record();
|
||||||
|
|
||||||
for import_entry in &module_record.import_entries {
|
for import_entry in &module_record.import_entries {
|
||||||
// Get named import
|
// Get named import
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ declare_oxc_lint!(
|
||||||
/// <https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/unambiguous.md>
|
/// <https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/docs/rules/unambiguous.md>
|
||||||
impl Rule for Unambiguous {
|
impl Rule for Unambiguous {
|
||||||
fn run_once(&self, ctx: &LintContext<'_>) {
|
fn run_once(&self, ctx: &LintContext<'_>) {
|
||||||
if ctx.semantic().module_record().not_esm {
|
if ctx.module_record().not_esm {
|
||||||
ctx.diagnostic(unambiguous_diagnostic(Span::default()));
|
ctx.diagnostic(unambiguous_diagnostic(Span::default()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,7 @@ impl Rule for NoBarrelFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_once(&self, ctx: &LintContext<'_>) {
|
fn run_once(&self, ctx: &LintContext<'_>) {
|
||||||
let semantic = ctx.semantic();
|
let module_record = ctx.module_record();
|
||||||
let module_record = semantic.module_record();
|
|
||||||
|
|
||||||
if module_record.not_esm {
|
if module_record.not_esm {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ pub fn import_matcher<'a>(
|
||||||
expected_module_name: &'a str,
|
expected_module_name: &'a str,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let expected_module_name = expected_module_name.cow_to_lowercase();
|
let expected_module_name = expected_module_name.cow_to_lowercase();
|
||||||
ctx.semantic().module_record().import_entries.iter().any(|import| {
|
ctx.module_record().import_entries.iter().any(|import| {
|
||||||
import.module_request.name().as_str() == expected_module_name
|
import.module_request.name().as_str() == expected_module_name
|
||||||
&& import.local_name.name().as_str() == actual_local_name
|
&& import.local_name.name().as_str() == actual_local_name
|
||||||
})
|
})
|
||||||
|
|
@ -109,7 +109,7 @@ pub fn is_import<'a>(
|
||||||
expected_local_name: &'a str,
|
expected_local_name: &'a str,
|
||||||
expected_module_name: &'a str,
|
expected_module_name: &'a str,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if ctx.semantic().module_record().requested_modules.is_empty()
|
if ctx.module_record().requested_modules.is_empty()
|
||||||
&& ctx.scopes().get_bindings(ctx.scopes().root_scope_id()).is_empty()
|
&& ctx.scopes().get_bindings(ctx.scopes().root_scope_id()).is_empty()
|
||||||
{
|
{
|
||||||
return actual_local_name == expected_local_name;
|
return actual_local_name == expected_local_name;
|
||||||
|
|
|
||||||
|
|
@ -297,9 +297,8 @@ impl Runtime {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut semantic = semantic_ret.semantic;
|
let mut semantic = semantic_ret.semantic;
|
||||||
semantic.set_module_record(&module_record);
|
|
||||||
semantic.set_irregular_whitespaces(ret.irregular_whitespaces);
|
semantic.set_irregular_whitespaces(ret.irregular_whitespaces);
|
||||||
self.linter.run(path, Rc::new(semantic))
|
self.linter.run(path, Rc::new(semantic), Arc::clone(&module_record))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn init_cache_state(&self, path: &Path) -> bool {
|
pub(super) fn init_cache_state(&self, path: &Path) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -321,10 +321,12 @@ mod test {
|
||||||
SemanticBuilder::new().with_cfg(true).build(&parser_ret.program).semantic;
|
SemanticBuilder::new().with_cfg(true).build(&parser_ret.program).semantic;
|
||||||
let semantic_ret = Rc::new(semantic_ret);
|
let semantic_ret = Rc::new(semantic_ret);
|
||||||
|
|
||||||
|
let module_record = Arc::new(parser_ret.module_record);
|
||||||
let build_ctx = |path: &'static str| {
|
let build_ctx = |path: &'static str| {
|
||||||
Rc::new(ContextHost::new(
|
Rc::new(ContextHost::new(
|
||||||
path,
|
path,
|
||||||
Rc::clone(&semantic_ret),
|
Rc::clone(&semantic_ret),
|
||||||
|
Arc::clone(&module_record),
|
||||||
LintOptions::default(),
|
LintOptions::default(),
|
||||||
Arc::default(),
|
Arc::default(),
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
//! Semantic Builder
|
//! Semantic Builder
|
||||||
|
|
||||||
use std::{
|
use std::cell::{Cell, RefCell};
|
||||||
cell::{Cell, RefCell},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
|
@ -289,7 +286,6 @@ impl<'a> SemanticBuilder<'a> {
|
||||||
source_type: self.source_type,
|
source_type: self.source_type,
|
||||||
comments,
|
comments,
|
||||||
irregular_whitespaces: [].into(),
|
irregular_whitespaces: [].into(),
|
||||||
module_record: Arc::new(oxc_syntax::module_record::ModuleRecord::default()),
|
|
||||||
nodes: self.nodes,
|
nodes: self.nodes,
|
||||||
scopes: self.scope,
|
scopes: self.scope,
|
||||||
symbols: self.symbols,
|
symbols: self.symbols,
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,12 @@
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use std::ops::RangeBounds;
|
use std::ops::RangeBounds;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use oxc_ast::{
|
use oxc_ast::{
|
||||||
ast::IdentifierReference, comments_range, has_comments_between, AstKind, Comment, CommentsRange,
|
ast::IdentifierReference, comments_range, has_comments_between, AstKind, Comment, CommentsRange,
|
||||||
};
|
};
|
||||||
use oxc_cfg::ControlFlowGraph;
|
use oxc_cfg::ControlFlowGraph;
|
||||||
use oxc_span::{GetSpan, SourceType, Span};
|
use oxc_span::{GetSpan, SourceType, Span};
|
||||||
use oxc_syntax::module_record::ModuleRecord;
|
|
||||||
pub use oxc_syntax::{
|
pub use oxc_syntax::{
|
||||||
scope::{ScopeFlags, ScopeId},
|
scope::{ScopeFlags, ScopeId},
|
||||||
symbol::{SymbolFlags, SymbolId},
|
symbol::{SymbolFlags, SymbolId},
|
||||||
|
|
@ -81,8 +79,6 @@ pub struct Semantic<'a> {
|
||||||
comments: &'a oxc_allocator::Vec<'a, Comment>,
|
comments: &'a oxc_allocator::Vec<'a, Comment>,
|
||||||
irregular_whitespaces: Box<[Span]>,
|
irregular_whitespaces: Box<[Span]>,
|
||||||
|
|
||||||
module_record: Arc<ModuleRecord>,
|
|
||||||
|
|
||||||
/// Parsed JSDoc comments.
|
/// Parsed JSDoc comments.
|
||||||
jsdoc: JSDocFinder<'a>,
|
jsdoc: JSDocFinder<'a>,
|
||||||
|
|
||||||
|
|
@ -134,10 +130,6 @@ impl<'a> Semantic<'a> {
|
||||||
self.irregular_whitespaces = irregular_whitespaces;
|
self.irregular_whitespaces = irregular_whitespaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_module_record(&mut self, module_record: &Arc<ModuleRecord>) {
|
|
||||||
self.module_record = Arc::clone(module_record);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trivias (comments) found while parsing
|
/// Trivias (comments) found while parsing
|
||||||
pub fn comments(&self) -> &[Comment] {
|
pub fn comments(&self) -> &[Comment] {
|
||||||
self.comments
|
self.comments
|
||||||
|
|
@ -165,11 +157,6 @@ impl<'a> Semantic<'a> {
|
||||||
&self.jsdoc
|
&self.jsdoc
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ESM module record containing imports and exports.
|
|
||||||
pub fn module_record(&self) -> &ModuleRecord {
|
|
||||||
self.module_record.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// [`SymbolTable`] containing all symbols in the program and their
|
/// [`SymbolTable`] containing all symbols in the program and their
|
||||||
/// [`Reference`]s.
|
/// [`Reference`]s.
|
||||||
pub fn symbols(&self) -> &SymbolTable {
|
pub fn symbols(&self) -> &SymbolTable {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use oxc::{
|
use oxc::{
|
||||||
|
|
@ -20,6 +21,7 @@ use oxc::{
|
||||||
ScopeFlags, ScopeId, ScopeTree, SemanticBuilder, SymbolTable,
|
ScopeFlags, ScopeId, ScopeTree, SemanticBuilder, SymbolTable,
|
||||||
},
|
},
|
||||||
span::SourceType,
|
span::SourceType,
|
||||||
|
syntax::module_record::ModuleRecord,
|
||||||
transformer::{TransformOptions, Transformer},
|
transformer::{TransformOptions, Transformer},
|
||||||
};
|
};
|
||||||
use oxc_index::Idx;
|
use oxc_index::Idx;
|
||||||
|
|
@ -198,7 +200,7 @@ impl Oxc {
|
||||||
.preserve_parens
|
.preserve_parens
|
||||||
.unwrap_or(default_parser_options.preserve_parens),
|
.unwrap_or(default_parser_options.preserve_parens),
|
||||||
};
|
};
|
||||||
let ParserReturn { mut program, errors, .. } =
|
let ParserReturn { mut program, errors, module_record, .. } =
|
||||||
Parser::new(&allocator, source_text, source_type)
|
Parser::new(&allocator, source_text, source_type)
|
||||||
.with_options(oxc_parser_options)
|
.with_options(oxc_parser_options)
|
||||||
.parse();
|
.parse();
|
||||||
|
|
@ -227,7 +229,8 @@ impl Oxc {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.run_linter(&run_options, &path, &program);
|
let module_record = Arc::new(module_record);
|
||||||
|
self.run_linter(&run_options, &path, &program, &module_record);
|
||||||
|
|
||||||
self.run_prettier(&run_options, source_text, source_type);
|
self.run_prettier(&run_options, source_text, source_type);
|
||||||
|
|
||||||
|
|
@ -296,12 +299,19 @@ impl Oxc {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_linter(&mut self, run_options: &OxcRunOptions, path: &Path, program: &Program) {
|
fn run_linter(
|
||||||
|
&mut self,
|
||||||
|
run_options: &OxcRunOptions,
|
||||||
|
path: &Path,
|
||||||
|
program: &Program,
|
||||||
|
module_record: &Arc<ModuleRecord>,
|
||||||
|
) {
|
||||||
// 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().with_cfg(true).build(program);
|
let semantic_ret = SemanticBuilder::new().with_cfg(true).build(program);
|
||||||
let semantic = Rc::new(semantic_ret.semantic);
|
let semantic = Rc::new(semantic_ret.semantic);
|
||||||
let linter_ret = Linter::default().run(path, Rc::clone(&semantic));
|
let linter_ret =
|
||||||
|
Linter::default().run(path, Rc::clone(&semantic), Arc::clone(module_record));
|
||||||
let diagnostics = linter_ret.into_iter().map(|e| e.error).collect();
|
let diagnostics = linter_ret.into_iter().map(|e| e.error).collect();
|
||||||
self.save_diagnostics(diagnostics);
|
self.save_diagnostics(diagnostics);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{env, path::Path, rc::Rc};
|
use std::{env, path::Path, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
use oxc_allocator::Allocator;
|
use oxc_allocator::Allocator;
|
||||||
use oxc_benchmark::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
use oxc_benchmark::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||||
|
|
@ -39,7 +39,8 @@ fn bench_linter(criterion: &mut Criterion) {
|
||||||
.build(&ret.program);
|
.build(&ret.program);
|
||||||
let linter = LinterBuilder::all().with_fix(FixKind::All).build();
|
let linter = LinterBuilder::all().with_fix(FixKind::All).build();
|
||||||
let semantic = Rc::new(semantic_ret.semantic);
|
let semantic = Rc::new(semantic_ret.semantic);
|
||||||
b.iter(|| linter.run(path, Rc::clone(&semantic)));
|
let module_record = Arc::new(ret.module_record);
|
||||||
|
b.iter(|| linter.run(path, Rc::clone(&semantic), Arc::clone(&module_record)));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue