Skip to content

Commit 7f6cf81

Browse files
committed
touchup
1 parent 8f00fa4 commit 7f6cf81

File tree

2 files changed

+35
-55
lines changed

2 files changed

+35
-55
lines changed

crates/oxc_linter/src/generated/rule_runner_impls.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,6 +2176,7 @@ impl RuleRunner for crate::rules::react::no_unknown_property::NoUnknownProperty
21762176

21772177
impl RuleRunner for crate::rules::react::only_export_components::OnlyExportComponents {
21782178
const NODE_TYPES: Option<&AstTypesBitset> = None;
2179+
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::RunOnce;
21792180
}
21802181

21812182
impl RuleRunner for crate::rules::react::prefer_es6_class::PreferEs6Class {

crates/oxc_linter/src/rules/react/only_export_components.rs

Lines changed: 34 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,18 @@ impl Rule for OnlyExportComponents {
261261
return false;
262262
};
263263

264-
Self::should_scan(filename, self.check_js) && !Self::should_skip(filename)
264+
let should_scan = {
265+
let ext = Path::new(filename).extension().and_then(|e| e.to_str());
266+
matches!(ext, Some(e) if e.eq_ignore_ascii_case("tsx") || e.eq_ignore_ascii_case("jsx"))
267+
|| (self.check_js && matches!(ext, Some(e) if e.eq_ignore_ascii_case("js")))
268+
};
269+
270+
let should_skip = filename.contains(".test.")
271+
|| filename.contains(".spec.")
272+
|| filename.contains(".cy.")
273+
|| filename.contains(".stories.");
274+
275+
should_scan && !should_skip
265276
}
266277

267278
fn run_once(&self, ctx: &LintContext<'_>) {
@@ -274,46 +285,31 @@ impl Rule for OnlyExportComponents {
274285
return;
275286
}
276287

277-
let react_hocs: Vec<&str> = DEFAULT_REACT_HOCS
278-
.iter()
279-
.copied()
280-
.chain(self.custom_hocs.iter().map(String::as_str))
281-
.collect();
282-
283-
let export_info = self.analyze_exports(ctx, &react_hocs);
284-
let local_components = Self::find_local_components(ctx, &react_hocs);
288+
let export_info = self.analyze_exports(ctx);
289+
let local_components = self.find_local_components(ctx);
285290

286291
Self::report_diagnostics(ctx, &export_info, &local_components);
287292
}
288293
}
289294

290295
impl OnlyExportComponents {
291-
fn should_skip(f: &str) -> bool {
292-
f.contains(".test.")
293-
|| f.contains(".spec.")
294-
|| f.contains(".cy.")
295-
|| f.contains(".stories.")
296-
}
297-
298-
fn should_scan(f: &str, check_js: bool) -> bool {
299-
let ext = Path::new(f).extension().and_then(|e| e.to_str());
300-
matches!(ext, Some(e) if e.eq_ignore_ascii_case("tsx") || e.eq_ignore_ascii_case("jsx"))
301-
|| (check_js && matches!(ext, Some(e) if e.eq_ignore_ascii_case("js")))
296+
fn is_react_hoc(&self, name: &str) -> bool {
297+
DEFAULT_REACT_HOCS.contains(&name) || self.custom_hocs.iter().any(|h| h.as_str() == name)
302298
}
303299

304300
fn starts_with_ascii_upper(s: &str) -> bool {
305301
matches!(s.as_bytes().first(), Some(b'A'..=b'Z'))
306302
}
307303

308-
fn can_be_react_function_component(init: Option<&Expression>, react_hocs: &[&str]) -> bool {
304+
fn can_be_react_function_component(&self, init: Option<&Expression>) -> bool {
309305
if let Some(raw_init) = init {
310306
let js_init = Self::skip_ts_expression(raw_init);
311307

312308
match js_init {
313309
Expression::ArrowFunctionExpression(_) => true,
314310
Expression::CallExpression(call_expr) => {
315311
if let Expression::Identifier(callee) = &call_expr.callee {
316-
react_hocs.contains(&callee.name.as_str())
312+
self.is_react_hoc(&callee.name)
317313
} else {
318314
false
319315
}
@@ -349,7 +345,7 @@ impl OnlyExportComponents {
349345
})
350346
}
351347

352-
fn analyze_exports(&self, ctx: &LintContext, react_hocs: &[&str]) -> ExportAnalysis {
348+
fn analyze_exports(&self, ctx: &LintContext) -> ExportAnalysis {
353349
let mut analysis = ExportAnalysis::default();
354350
let module_record = ctx.module_record();
355351

@@ -368,7 +364,7 @@ impl OnlyExportComponents {
368364
ctx.diagnostic(export_all_components_diagnostic(export_all.span));
369365
}
370366
AstKind::ExportDefaultDeclaration(export_default) => {
371-
let result = self.analyze_export_default(export_default, react_hocs);
367+
let result = self.analyze_export_default(export_default);
372368
if let Some(span) = result.anonymous_span {
373369
ctx.diagnostic(anonymous_components_diagnostic(span));
374370
}
@@ -377,7 +373,7 @@ impl OnlyExportComponents {
377373
AstKind::ExportNamedDeclaration(export_named)
378374
if export_named.export_kind.is_value() =>
379375
{
380-
let result = self.analyze_export_named(ctx, export_named, react_hocs);
376+
let result = self.analyze_export_named(ctx, export_named);
381377
analysis.merge(result);
382378
}
383379
_ => {}
@@ -387,7 +383,7 @@ impl OnlyExportComponents {
387383
analysis
388384
}
389385

390-
fn find_local_components(ctx: &LintContext, react_hocs: &[&str]) -> Vec<Span> {
386+
fn find_local_components(&self, ctx: &LintContext) -> Vec<Span> {
391387
ctx.semantic()
392388
.nodes()
393389
.iter()
@@ -397,10 +393,7 @@ impl OnlyExportComponents {
397393
if let BindingPatternKind::BindingIdentifier(binding_id) =
398394
&declarator.id.kind
399395
&& Self::starts_with_ascii_upper(&binding_id.name)
400-
&& Self::can_be_react_function_component(
401-
declarator.init.as_ref(),
402-
react_hocs,
403-
)
396+
&& self.can_be_react_function_component(declarator.init.as_ref())
404397
&& !Self::is_exported(ctx, node.id())
405398
{
406399
return Some(binding_id.span);
@@ -451,11 +444,7 @@ impl OnlyExportComponents {
451444
}
452445
}
453446

454-
fn analyze_export_default(
455-
&self,
456-
export_default: &ExportDefaultDeclaration,
457-
react_hocs: &[&str],
458-
) -> ExportAnalysis {
447+
fn analyze_export_default(&self, export_default: &ExportDefaultDeclaration) -> ExportAnalysis {
459448
let mut analysis = ExportAnalysis::default();
460449

461450
match &export_default.declaration {
@@ -477,7 +466,7 @@ impl OnlyExportComponents {
477466
}
478467
}
479468
ExportDefaultDeclarationKind::CallExpression(call_expr) => {
480-
if Self::is_hoc_call_expression(call_expr, react_hocs) {
469+
if self.is_hoc_call_expression(call_expr) {
481470
analysis.has_react_export = true;
482471
} else {
483472
analysis.anonymous_span = Some(export_default.span);
@@ -489,17 +478,13 @@ impl OnlyExportComponents {
489478
analysis.add_export(export_type);
490479
}
491480
ExportDefaultDeclarationKind::TSAsExpression(ts_as_expr) => {
492-
return self.analyze_export_default_expression(
493-
&ts_as_expr.expression,
494-
export_default,
495-
react_hocs,
496-
);
481+
return self
482+
.analyze_export_default_expression(&ts_as_expr.expression, export_default);
497483
}
498484
ExportDefaultDeclarationKind::TSSatisfiesExpression(ts_satisfies_expr) => {
499485
return self.analyze_export_default_expression(
500486
&ts_satisfies_expr.expression,
501487
export_default,
502-
react_hocs,
503488
);
504489
}
505490
_ => {
@@ -514,13 +499,12 @@ impl OnlyExportComponents {
514499
&self,
515500
expr: &Expression,
516501
export_default: &ExportDefaultDeclaration,
517-
react_hocs: &[&str],
518502
) -> ExportAnalysis {
519503
let mut analysis = ExportAnalysis::default();
520504

521505
match expr {
522506
Expression::CallExpression(call_expr) => {
523-
if Self::is_hoc_call_expression(call_expr, react_hocs) {
507+
if self.is_hoc_call_expression(call_expr) {
524508
analysis.has_react_export = true;
525509
} else {
526510
analysis.anonymous_span = Some(export_default.span);
@@ -543,7 +527,6 @@ impl OnlyExportComponents {
543527
&self,
544528
ctx: &LintContext,
545529
export_named: &ExportNamedDeclaration,
546-
react_hocs: &[&str],
547530
) -> ExportAnalysis {
548531
let mut analysis = ExportAnalysis::default();
549532
if let Some(declaration) = &export_named.declaration {
@@ -553,10 +536,8 @@ impl OnlyExportComponents {
553536
.iter()
554537
.map(|declarator| match &declarator.id.kind {
555538
BindingPatternKind::BindingIdentifier(binding_id) => {
556-
let is_func = Self::can_be_react_function_component(
557-
declarator.init.as_ref(),
558-
react_hocs,
559-
);
539+
let is_func =
540+
self.can_be_react_function_component(declarator.init.as_ref());
560541
self.classify_export(
561542
binding_id.name.as_str(),
562543
binding_id.span,
@@ -695,7 +676,7 @@ impl OnlyExportComponents {
695676
}
696677
}
697678

698-
fn is_hoc_call_expression(call_expr: &CallExpression, react_hocs: &[&str]) -> bool {
679+
fn is_hoc_call_expression(&self, call_expr: &CallExpression) -> bool {
699680
let is_callee_hoc = match &call_expr.callee {
700681
Expression::CallExpression(inner_call) => {
701682
if let Expression::Identifier(ident) = &inner_call.callee {
@@ -706,12 +687,12 @@ impl OnlyExportComponents {
706687
}
707688
Expression::StaticMemberExpression(member) => {
708689
if let Expression::Identifier(_) = &member.object {
709-
react_hocs.contains(&member.property.name.as_str())
690+
self.is_react_hoc(&member.property.name)
710691
} else {
711692
false
712693
}
713694
}
714-
Expression::Identifier(ident) => react_hocs.contains(&ident.name.as_str()),
695+
Expression::Identifier(ident) => self.is_react_hoc(&ident.name),
715696
_ => false,
716697
};
717698

@@ -728,9 +709,7 @@ impl OnlyExportComponents {
728709
match expr_without_ts {
729710
Expression::Identifier(_) => true,
730711
Expression::FunctionExpression(func) => func.id.is_some(),
731-
Expression::CallExpression(inner_call) => {
732-
Self::is_hoc_call_expression(inner_call, react_hocs)
733-
}
712+
Expression::CallExpression(inner_call) => self.is_hoc_call_expression(inner_call),
734713
_ => false,
735714
}
736715
})

0 commit comments

Comments
 (0)