refactor(linter): clean up APIs for ModuleRecord (#7556)

This commit is contained in:
Boshen 2024-12-01 04:48:42 +00:00
parent c2ced15dfd
commit 823353a6fc
13 changed files with 45 additions and 54 deletions

View file

@ -1,5 +1,4 @@
//! [ECMAScript Module Record](https://tc39.es/ecma262/#sec-abstract-module-records) //! [ECMAScript Module Record](https://tc39.es/ecma262/#sec-abstract-module-records)
#![allow(missing_docs)] // fixme
use std::{ use std::{
fmt, fmt,
@ -124,7 +123,7 @@ impl fmt::Debug for ModuleRecord {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct NameSpan { pub struct NameSpan {
name: CompactStr, pub name: CompactStr,
span: Span, span: Span,
} }
@ -133,11 +132,11 @@ impl NameSpan {
Self { name, span } Self { name, span }
} }
pub const fn name(&self) -> &CompactStr { pub fn name(&self) -> &str {
&self.name self.name.as_str()
} }
pub const fn span(&self) -> Span { pub fn span(&self) -> Span {
self.span self.span
} }
} }
@ -413,9 +412,9 @@ impl ExportLocalName {
} }
/// Get the bound name of this export. [`None`] for [`ExportLocalName::Null`]. /// 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 { 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, Self::Null => None,
} }
} }

View file

@ -92,7 +92,7 @@ impl Rule for NoDuplicateImports {
let mut side_effect_import_map: FxHashMap<&CompactStr, Vec<Span>> = FxHashMap::default(); let mut side_effect_import_map: FxHashMap<&CompactStr, Vec<Span>> = FxHashMap::default();
for entry in &module_record.import_entries { 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 span = entry.module_request.span();
let same_statement = if let Some(curr_span) = current_span { let same_statement = if let Some(curr_span) = current_span {
@ -153,7 +153,7 @@ impl Rule for NoDuplicateImports {
if self.include_exports { if self.include_exports {
for entry in &module_record.star_export_entries { for entry in &module_record.star_export_entries {
if let Some(module_request) = &entry.module_request { if let Some(module_request) = &entry.module_request {
let source = module_request.name(); let source = &module_request.name;
let span = entry.span; let span = entry.span;
if entry.import_name.is_all_but_default() { if entry.import_name.is_all_but_default() {
@ -208,7 +208,7 @@ impl Rule for NoDuplicateImports {
for entry in &module_record.indirect_export_entries { for entry in &module_record.indirect_export_entries {
if let Some(module_request) = &entry.module_request { if let Some(module_request) = &entry.module_request {
let source = module_request.name(); let source = &module_request.name;
let span = entry.span; let span = entry.span;
if let Some(existing) = import_map.get(source) { if let Some(existing) = import_map.get(source) {

View file

@ -106,25 +106,25 @@ impl Rule for Named {
continue; continue;
} }
let import_span = import_name.span(); let import_span = import_name.span();
let import_name = import_name.name(); let name = import_name.name();
// Check `import { default as foo } from 'bar'` // 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; continue;
} }
// Check remote bindings // Check remote bindings
if remote_module_record.exported_bindings.contains_key(import_name) { if remote_module_record.exported_bindings.contains_key(name) {
continue; continue;
} }
// check re-export // check re-export
if remote_module_record if remote_module_record
.exported_bindings_from_star_export .exported_bindings_from_star_export
.iter() .iter()
.any(|entry| entry.value().contains(import_name)) .any(|entry| entry.value().contains(&import_name.name))
{ {
continue; 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 { for export_entry in &module_record.indirect_export_entries {
@ -146,7 +146,7 @@ impl Rule for Named {
// Check remote bindings // Check remote bindings
let name = import_name.name(); let name = import_name.name();
// `export { default as foo } from './source'` <> `export default xxx` // `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; continue;
} }
if remote_module_record.exported_bindings.contains_key(name) { if remote_module_record.exported_bindings.contains_key(name) {

View file

@ -155,8 +155,7 @@ impl Rule for Namespace {
return; return;
} }
let Some(symbol_id) = ctx.scopes().get_root_binding(entry.local_name.name().as_str()) let Some(symbol_id) = ctx.scopes().get_root_binding(entry.local_name.name()) else {
else {
return; 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 { module_record.indirect_export_entries.iter().find(|e| match &e.import_name {
ExportImportName::All => { ExportImportName::All => {
if let ExportExportName::Name(name_span) = &e.export_name { if let ExportExportName::Name(name_span) = &e.export_name {
return name_span.name().as_str() == name; return name_span.name() == name;
} }
false false
} }
ExportImportName::Name(name_span) => { ExportImportName::Name(name_span) => {
name_span.name().as_str() == name name_span.name() == name
&& module_record.import_entries.iter().any(|entry| { && module_record.import_entries.iter().any(|entry| {
entry.local_name.name().as_str() == name entry.local_name.name() == name && entry.import_name.is_namespace_object()
&& entry.import_name.is_namespace_object()
}) })
} }
_ => false, _ => false,
@ -256,9 +254,7 @@ fn get_module_request_name(name: &str, module_record: &ModuleRecord) -> Option<S
module_record module_record
.import_entries .import_entries
.iter() .iter()
.find(|entry| { .find(|entry| entry.local_name.name() == name && entry.import_name.is_namespace_object())
entry.local_name.name().as_str() == name && entry.import_name.is_namespace_object()
})
.map(|entry| entry.module_request.name().to_string()) .map(|entry| entry.module_request.name().to_string())
} }

View file

@ -90,16 +90,13 @@ impl Rule for NoNamedAsDefaultMember {
continue; continue;
} }
let Some(symbol_id) = let Some(symbol_id) = ctx.scopes().get_root_binding(import_entry.local_name.name())
ctx.scopes().get_root_binding(import_entry.local_name.name().as_str())
else { else {
return; return;
}; };
has_members_map.insert( has_members_map
symbol_id, .insert(symbol_id, (remote_module_record_ref, import_entry.module_request.clone()));
(remote_module_record_ref, import_entry.module_request.name().clone()),
);
} }
if has_members_map.is_empty() { if has_members_map.is_empty() {
@ -134,7 +131,7 @@ impl Rule for NoNamedAsDefaultMember {
}, },
&ident.name, &ident.name,
prop_str, prop_str,
module_name, module_name.name(),
)); ));
}; };
}; };
@ -161,7 +158,7 @@ impl Rule for NoNamedAsDefaultMember {
decl.span, decl.span,
&ident.name, &ident.name,
&name, &name,
module_name, module_name.name(),
)); ));
} }
} }

View file

@ -37,7 +37,7 @@ impl Rule for NoMocksImport {
let module_records = ctx.module_record(); let module_records = ctx.module_record();
for import_entry in &module_records.import_entries { 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) { if contains_mocks_dir(module_specifier) {
ctx.diagnostic(no_mocks_import_diagnostic(import_entry.module_request.span())); ctx.diagnostic(no_mocks_import_diagnostic(import_entry.module_request.span()));
} }

View file

@ -73,7 +73,7 @@ impl Rule for NoBeforeInteractiveScriptOutsideDocument {
return; return;
} }
let next_script_import_local_name = get_next_script_import_local_name(ctx); 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; return;
} }

View file

@ -107,10 +107,12 @@ fn is_inside_export_default(node: &AstNode<'_>, ctx: &LintContext<'_>) -> bool {
let Some(name) = name else { let Some(name) = name else {
continue; continue;
}; };
if ctx.module_record().local_export_entries.iter().any(|e| { if ctx
e.local_name.is_default() .module_record()
&& e.local_name.name().is_some_and(|n| n.as_str() == name.as_str()) .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; is_inside_export_default = true;
} }
} }

View file

@ -117,8 +117,7 @@ impl Rule for NoUnwantedPolyfillio {
if tag_name.as_str() != "script" { if tag_name.as_str() != "script" {
let next_script_import_local_name = get_next_script_import_local_name(ctx); 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; return;
} }
} }

View file

@ -98,8 +98,8 @@ pub fn import_matcher<'a>(
) -> bool { ) -> bool {
let expected_module_name = expected_module_name.cow_to_lowercase(); let expected_module_name = expected_module_name.cow_to_lowercase();
ctx.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() == expected_module_name
&& import.local_name.name().as_str() == actual_local_name && import.local_name.name() == actual_local_name
}) })
} }

View file

@ -81,7 +81,7 @@ fn is_inside_process_event_handler(ctx: &LintContext, node: &AstNode) -> bool {
fn is_worker_threads_imported(ctx: &LintContext) -> bool { fn is_worker_threads_imported(ctx: &LintContext) -> bool {
ctx.module_record().import_entries.iter().any(|entry| { 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")
}) })
} }

View file

@ -1,5 +1,3 @@
use oxc_span::CompactStr;
use crate::LintContext; use crate::LintContext;
pub fn is_in_app_dir(file_path: &str) -> bool { 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") 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| { 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()) Some(entry.local_name.name())
} else { } else {
None None

View file

@ -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> { impl PartialEq<CompactStr> for Cow<'_, str> {
fn eq(&self, other: &CompactStr) -> bool { fn eq(&self, other: &CompactStr) -> bool {
self.as_ref() == other.as_str() 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 { impl Index<Span> for CompactStr {
type Output = str; type Output = str;