mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
refactor(linter): clean up APIs for ModuleRecord (#7556)
This commit is contained in:
parent
c2ced15dfd
commit
823353a6fc
13 changed files with 45 additions and 54 deletions
|
|
@ -1,5 +1,4 @@
|
|||
//! [ECMAScript Module Record](https://tc39.es/ecma262/#sec-abstract-module-records)
|
||||
#![allow(missing_docs)] // fixme
|
||||
|
||||
use std::{
|
||||
fmt,
|
||||
|
|
@ -124,7 +123,7 @@ impl fmt::Debug for ModuleRecord {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct NameSpan {
|
||||
name: CompactStr,
|
||||
pub name: CompactStr,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
|
|
@ -133,11 +132,11 @@ impl NameSpan {
|
|||
Self { name, span }
|
||||
}
|
||||
|
||||
pub const fn name(&self) -> &CompactStr {
|
||||
&self.name
|
||||
pub fn name(&self) -> &str {
|
||||
self.name.as_str()
|
||||
}
|
||||
|
||||
pub const fn span(&self) -> Span {
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
|
@ -413,9 +412,9 @@ impl ExportLocalName {
|
|||
}
|
||||
|
||||
/// Get the bound name of this export. [`None`] for [`ExportLocalName::Null`].
|
||||
pub const fn name(&self) -> Option<&CompactStr> {
|
||||
pub fn name(&self) -> Option<&str> {
|
||||
match self {
|
||||
Self::Name(name) | Self::Default(name) => Some(name.name()),
|
||||
Self::Name(name) | Self::Default(name) => Some(name.name.as_str()),
|
||||
Self::Null => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ impl Rule for NoDuplicateImports {
|
|||
let mut side_effect_import_map: FxHashMap<&CompactStr, Vec<Span>> = FxHashMap::default();
|
||||
|
||||
for entry in &module_record.import_entries {
|
||||
let source = entry.module_request.name();
|
||||
let source = &entry.module_request.name;
|
||||
let span = entry.module_request.span();
|
||||
|
||||
let same_statement = if let Some(curr_span) = current_span {
|
||||
|
|
@ -153,7 +153,7 @@ impl Rule for NoDuplicateImports {
|
|||
if self.include_exports {
|
||||
for entry in &module_record.star_export_entries {
|
||||
if let Some(module_request) = &entry.module_request {
|
||||
let source = module_request.name();
|
||||
let source = &module_request.name;
|
||||
let span = entry.span;
|
||||
|
||||
if entry.import_name.is_all_but_default() {
|
||||
|
|
@ -208,7 +208,7 @@ impl Rule for NoDuplicateImports {
|
|||
|
||||
for entry in &module_record.indirect_export_entries {
|
||||
if let Some(module_request) = &entry.module_request {
|
||||
let source = module_request.name();
|
||||
let source = &module_request.name;
|
||||
let span = entry.span;
|
||||
|
||||
if let Some(existing) = import_map.get(source) {
|
||||
|
|
|
|||
|
|
@ -106,25 +106,25 @@ impl Rule for Named {
|
|||
continue;
|
||||
}
|
||||
let import_span = import_name.span();
|
||||
let import_name = import_name.name();
|
||||
let name = import_name.name();
|
||||
// Check `import { default as foo } from 'bar'`
|
||||
if import_name.as_str() == "default" && remote_module_record.export_default.is_some() {
|
||||
if name == "default" && remote_module_record.export_default.is_some() {
|
||||
continue;
|
||||
}
|
||||
// Check remote bindings
|
||||
if remote_module_record.exported_bindings.contains_key(import_name) {
|
||||
if remote_module_record.exported_bindings.contains_key(name) {
|
||||
continue;
|
||||
}
|
||||
// check re-export
|
||||
if remote_module_record
|
||||
.exported_bindings_from_star_export
|
||||
.iter()
|
||||
.any(|entry| entry.value().contains(import_name))
|
||||
.any(|entry| entry.value().contains(&import_name.name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ctx.diagnostic(named_diagnostic(import_name, specifier, import_span));
|
||||
ctx.diagnostic(named_diagnostic(name, specifier, import_span));
|
||||
}
|
||||
|
||||
for export_entry in &module_record.indirect_export_entries {
|
||||
|
|
@ -146,7 +146,7 @@ impl Rule for Named {
|
|||
// Check remote bindings
|
||||
let name = import_name.name();
|
||||
// `export { default as foo } from './source'` <> `export default xxx`
|
||||
if *name == "default" && remote_module_record.export_default.is_some() {
|
||||
if name == "default" && remote_module_record.export_default.is_some() {
|
||||
continue;
|
||||
}
|
||||
if remote_module_record.exported_bindings.contains_key(name) {
|
||||
|
|
|
|||
|
|
@ -155,8 +155,7 @@ impl Rule for Namespace {
|
|||
return;
|
||||
}
|
||||
|
||||
let Some(symbol_id) = ctx.scopes().get_root_binding(entry.local_name.name().as_str())
|
||||
else {
|
||||
let Some(symbol_id) = ctx.scopes().get_root_binding(entry.local_name.name()) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -235,16 +234,15 @@ fn get_module_request_name(name: &str, module_record: &ModuleRecord) -> Option<S
|
|||
module_record.indirect_export_entries.iter().find(|e| match &e.import_name {
|
||||
ExportImportName::All => {
|
||||
if let ExportExportName::Name(name_span) = &e.export_name {
|
||||
return name_span.name().as_str() == name;
|
||||
return name_span.name() == name;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
ExportImportName::Name(name_span) => {
|
||||
name_span.name().as_str() == name
|
||||
name_span.name() == name
|
||||
&& module_record.import_entries.iter().any(|entry| {
|
||||
entry.local_name.name().as_str() == name
|
||||
&& entry.import_name.is_namespace_object()
|
||||
entry.local_name.name() == name && entry.import_name.is_namespace_object()
|
||||
})
|
||||
}
|
||||
_ => false,
|
||||
|
|
@ -256,9 +254,7 @@ fn get_module_request_name(name: &str, module_record: &ModuleRecord) -> Option<S
|
|||
module_record
|
||||
.import_entries
|
||||
.iter()
|
||||
.find(|entry| {
|
||||
entry.local_name.name().as_str() == name && entry.import_name.is_namespace_object()
|
||||
})
|
||||
.find(|entry| entry.local_name.name() == name && entry.import_name.is_namespace_object())
|
||||
.map(|entry| entry.module_request.name().to_string())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,16 +90,13 @@ impl Rule for NoNamedAsDefaultMember {
|
|||
continue;
|
||||
}
|
||||
|
||||
let Some(symbol_id) =
|
||||
ctx.scopes().get_root_binding(import_entry.local_name.name().as_str())
|
||||
let Some(symbol_id) = ctx.scopes().get_root_binding(import_entry.local_name.name())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
has_members_map.insert(
|
||||
symbol_id,
|
||||
(remote_module_record_ref, import_entry.module_request.name().clone()),
|
||||
);
|
||||
has_members_map
|
||||
.insert(symbol_id, (remote_module_record_ref, import_entry.module_request.clone()));
|
||||
}
|
||||
|
||||
if has_members_map.is_empty() {
|
||||
|
|
@ -134,7 +131,7 @@ impl Rule for NoNamedAsDefaultMember {
|
|||
},
|
||||
&ident.name,
|
||||
prop_str,
|
||||
module_name,
|
||||
module_name.name(),
|
||||
));
|
||||
};
|
||||
};
|
||||
|
|
@ -161,7 +158,7 @@ impl Rule for NoNamedAsDefaultMember {
|
|||
decl.span,
|
||||
&ident.name,
|
||||
&name,
|
||||
module_name,
|
||||
module_name.name(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ impl Rule for NoMocksImport {
|
|||
let module_records = ctx.module_record();
|
||||
|
||||
for import_entry in &module_records.import_entries {
|
||||
let module_specifier = import_entry.module_request.name().as_str();
|
||||
let module_specifier = import_entry.module_request.name();
|
||||
if contains_mocks_dir(module_specifier) {
|
||||
ctx.diagnostic(no_mocks_import_diagnostic(import_entry.module_request.span()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ impl Rule for NoBeforeInteractiveScriptOutsideDocument {
|
|||
return;
|
||||
}
|
||||
let next_script_import_local_name = get_next_script_import_local_name(ctx);
|
||||
if !matches!(next_script_import_local_name, Some(import) if tag_name.as_str() == import.as_str())
|
||||
if !matches!(next_script_import_local_name, Some(import) if tag_name == import)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,10 +107,12 @@ fn is_inside_export_default(node: &AstNode<'_>, ctx: &LintContext<'_>) -> bool {
|
|||
let Some(name) = name else {
|
||||
continue;
|
||||
};
|
||||
if ctx.module_record().local_export_entries.iter().any(|e| {
|
||||
e.local_name.is_default()
|
||||
&& e.local_name.name().is_some_and(|n| n.as_str() == name.as_str())
|
||||
}) {
|
||||
if ctx
|
||||
.module_record()
|
||||
.local_export_entries
|
||||
.iter()
|
||||
.any(|e| e.local_name.is_default() && e.local_name.name().is_some_and(|n| n == name))
|
||||
{
|
||||
is_inside_export_default = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,8 +117,7 @@ impl Rule for NoUnwantedPolyfillio {
|
|||
|
||||
if tag_name.as_str() != "script" {
|
||||
let next_script_import_local_name = get_next_script_import_local_name(ctx);
|
||||
if !matches!(next_script_import_local_name, Some(import) if tag_name.as_str() == import.as_str())
|
||||
{
|
||||
if !matches!(next_script_import_local_name, Some(import) if tag_name == import) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,8 +98,8 @@ pub fn import_matcher<'a>(
|
|||
) -> bool {
|
||||
let expected_module_name = expected_module_name.cow_to_lowercase();
|
||||
ctx.module_record().import_entries.iter().any(|import| {
|
||||
import.module_request.name().as_str() == expected_module_name
|
||||
&& import.local_name.name().as_str() == actual_local_name
|
||||
import.module_request.name() == expected_module_name
|
||||
&& import.local_name.name() == actual_local_name
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ fn is_inside_process_event_handler(ctx: &LintContext, node: &AstNode) -> bool {
|
|||
|
||||
fn is_worker_threads_imported(ctx: &LintContext) -> bool {
|
||||
ctx.module_record().import_entries.iter().any(|entry| {
|
||||
matches!(entry.module_request.name().as_str(), "worker_threads" | "node:worker_threads")
|
||||
matches!(entry.module_request.name(), "worker_threads" | "node:worker_threads")
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
use oxc_span::CompactStr;
|
||||
|
||||
use crate::LintContext;
|
||||
|
||||
pub fn is_in_app_dir(file_path: &str) -> bool {
|
||||
|
|
@ -13,9 +11,9 @@ pub fn is_document_page(file_path: &str) -> bool {
|
|||
page.starts_with("/_document") || page.starts_with("\\_document")
|
||||
}
|
||||
|
||||
pub fn get_next_script_import_local_name<'a>(ctx: &'a LintContext) -> Option<&'a CompactStr> {
|
||||
pub fn get_next_script_import_local_name<'a>(ctx: &'a LintContext) -> Option<&'a str> {
|
||||
ctx.module_record().import_entries.iter().find_map(|entry| {
|
||||
if entry.module_request.name().as_str() == "next/script" {
|
||||
if entry.module_request.name() == "next/script" {
|
||||
Some(entry.local_name.name())
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -184,18 +184,18 @@ impl PartialEq<CompactStr> for str {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for CompactStr {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
self.as_str() == other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<CompactStr> for Cow<'_, str> {
|
||||
fn eq(&self, other: &CompactStr) -> bool {
|
||||
self.as_ref() == other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for CompactStr {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
self.as_str() == other
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<Span> for CompactStr {
|
||||
type Output = str;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue