diff --git a/crates/oxc_linter/src/generated/rule_runner_impls.rs b/crates/oxc_linter/src/generated/rule_runner_impls.rs index 3c87e3fcd64aa..629b874c83a63 100644 --- a/crates/oxc_linter/src/generated/rule_runner_impls.rs +++ b/crates/oxc_linter/src/generated/rule_runner_impls.rs @@ -2393,6 +2393,11 @@ impl RuleRunner for crate::rules::react::no_is_mounted::NoIsMounted { const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run; } +impl RuleRunner for crate::rules::react::no_multi_comp::NoMultiComp { + const NODE_TYPES: Option<&AstTypesBitset> = None; + const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::RunOnce; +} + impl RuleRunner for crate::rules::react::no_namespace::NoNamespace { const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[AstType::CallExpression, AstType::JSXOpeningElement])); diff --git a/crates/oxc_linter/src/generated/rules_enum.rs b/crates/oxc_linter/src/generated/rules_enum.rs index bff4a47c38735..d3b8da77ad630 100644 --- a/crates/oxc_linter/src/generated/rules_enum.rs +++ b/crates/oxc_linter/src/generated/rules_enum.rs @@ -405,6 +405,7 @@ pub use crate::rules::react::no_did_mount_set_state::NoDidMountSetState as React pub use crate::rules::react::no_direct_mutation_state::NoDirectMutationState as ReactNoDirectMutationState; pub use crate::rules::react::no_find_dom_node::NoFindDomNode as ReactNoFindDomNode; pub use crate::rules::react::no_is_mounted::NoIsMounted as ReactNoIsMounted; +pub use crate::rules::react::no_multi_comp::NoMultiComp as ReactNoMultiComp; pub use crate::rules::react::no_namespace::NoNamespace as ReactNoNamespace; pub use crate::rules::react::no_redundant_should_component_update::NoRedundantShouldComponentUpdate as ReactNoRedundantShouldComponentUpdate; pub use crate::rules::react::no_render_return_value::NoRenderReturnValue as ReactNoRenderReturnValue; @@ -1053,6 +1054,7 @@ pub enum RuleEnum { ReactNoDirectMutationState(ReactNoDirectMutationState), ReactNoFindDomNode(ReactNoFindDomNode), ReactNoIsMounted(ReactNoIsMounted), + ReactNoMultiComp(ReactNoMultiComp), ReactNoNamespace(ReactNoNamespace), ReactNoRedundantShouldComponentUpdate(ReactNoRedundantShouldComponentUpdate), ReactNoRenderReturnValue(ReactNoRenderReturnValue), @@ -1723,297 +1725,298 @@ impl RuleEnum { Self::ReactNoDirectMutationState(_) => 370usize, Self::ReactNoFindDomNode(_) => 371usize, Self::ReactNoIsMounted(_) => 372usize, - Self::ReactNoNamespace(_) => 373usize, - Self::ReactNoRedundantShouldComponentUpdate(_) => 374usize, - Self::ReactNoRenderReturnValue(_) => 375usize, - Self::ReactNoSetState(_) => 376usize, - Self::ReactNoStringRefs(_) => 377usize, - Self::ReactNoThisInSfc(_) => 378usize, - Self::ReactNoUnescapedEntities(_) => 379usize, - Self::ReactNoUnknownProperty(_) => 380usize, - Self::ReactNoUnsafe(_) => 381usize, - Self::ReactNoWillUpdateSetState(_) => 382usize, - Self::ReactOnlyExportComponents(_) => 383usize, - Self::ReactPreferEs6Class(_) => 384usize, - Self::ReactReactInJsxScope(_) => 385usize, - Self::ReactRequireRenderReturn(_) => 386usize, - Self::ReactRulesOfHooks(_) => 387usize, - Self::ReactSelfClosingComp(_) => 388usize, - Self::ReactStateInConstructor(_) => 389usize, - Self::ReactStylePropObject(_) => 390usize, - Self::ReactVoidDomElementsNoChildren(_) => 391usize, - Self::ReactPerfJsxNoJsxAsProp(_) => 392usize, - Self::ReactPerfJsxNoNewArrayAsProp(_) => 393usize, - Self::ReactPerfJsxNoNewFunctionAsProp(_) => 394usize, - Self::ReactPerfJsxNoNewObjectAsProp(_) => 395usize, - Self::UnicornCatchErrorName(_) => 396usize, - Self::UnicornConsistentAssert(_) => 397usize, - Self::UnicornConsistentDateClone(_) => 398usize, - Self::UnicornConsistentEmptyArraySpread(_) => 399usize, - Self::UnicornConsistentExistenceIndexCheck(_) => 400usize, - Self::UnicornConsistentFunctionScoping(_) => 401usize, - Self::UnicornEmptyBraceSpaces(_) => 402usize, - Self::UnicornErrorMessage(_) => 403usize, - Self::UnicornEscapeCase(_) => 404usize, - Self::UnicornExplicitLengthCheck(_) => 405usize, - Self::UnicornFilenameCase(_) => 406usize, - Self::UnicornNewForBuiltins(_) => 407usize, - Self::UnicornNoAbusiveEslintDisable(_) => 408usize, - Self::UnicornNoAccessorRecursion(_) => 409usize, - Self::UnicornNoAnonymousDefaultExport(_) => 410usize, - Self::UnicornNoArrayCallbackReference(_) => 411usize, - Self::UnicornNoArrayForEach(_) => 412usize, - Self::UnicornNoArrayMethodThisArgument(_) => 413usize, - Self::UnicornNoArrayReduce(_) => 414usize, - Self::UnicornNoArrayReverse(_) => 415usize, - Self::UnicornNoArraySort(_) => 416usize, - Self::UnicornNoAwaitExpressionMember(_) => 417usize, - Self::UnicornNoAwaitInPromiseMethods(_) => 418usize, - Self::UnicornNoConsoleSpaces(_) => 419usize, - Self::UnicornNoDocumentCookie(_) => 420usize, - Self::UnicornNoEmptyFile(_) => 421usize, - Self::UnicornNoHexEscape(_) => 422usize, - Self::UnicornNoImmediateMutation(_) => 423usize, - Self::UnicornNoInstanceofArray(_) => 424usize, - Self::UnicornNoInstanceofBuiltins(_) => 425usize, - Self::UnicornNoInvalidFetchOptions(_) => 426usize, - Self::UnicornNoInvalidRemoveEventListener(_) => 427usize, - Self::UnicornNoLengthAsSliceEnd(_) => 428usize, - Self::UnicornNoLonelyIf(_) => 429usize, - Self::UnicornNoMagicArrayFlatDepth(_) => 430usize, - Self::UnicornNoNegationInEqualityCheck(_) => 431usize, - Self::UnicornNoNestedTernary(_) => 432usize, - Self::UnicornNoNewArray(_) => 433usize, - Self::UnicornNoNewBuffer(_) => 434usize, - Self::UnicornNoNull(_) => 435usize, - Self::UnicornNoObjectAsDefaultParameter(_) => 436usize, - Self::UnicornNoProcessExit(_) => 437usize, - Self::UnicornNoSinglePromiseInPromiseMethods(_) => 438usize, - Self::UnicornNoStaticOnlyClass(_) => 439usize, - Self::UnicornNoThenable(_) => 440usize, - Self::UnicornNoThisAssignment(_) => 441usize, - Self::UnicornNoTypeofUndefined(_) => 442usize, - Self::UnicornNoUnnecessaryArrayFlatDepth(_) => 443usize, - Self::UnicornNoUnnecessaryArraySpliceCount(_) => 444usize, - Self::UnicornNoUnnecessaryAwait(_) => 445usize, - Self::UnicornNoUnnecessarySliceEnd(_) => 446usize, - Self::UnicornNoUnreadableArrayDestructuring(_) => 447usize, - Self::UnicornNoUnreadableIife(_) => 448usize, - Self::UnicornNoUselessCollectionArgument(_) => 449usize, - Self::UnicornNoUselessErrorCaptureStackTrace(_) => 450usize, - Self::UnicornNoUselessFallbackInSpread(_) => 451usize, - Self::UnicornNoUselessLengthCheck(_) => 452usize, - Self::UnicornNoUselessPromiseResolveReject(_) => 453usize, - Self::UnicornNoUselessSpread(_) => 454usize, - Self::UnicornNoUselessSwitchCase(_) => 455usize, - Self::UnicornNoUselessUndefined(_) => 456usize, - Self::UnicornNoZeroFractions(_) => 457usize, - Self::UnicornNumberLiteralCase(_) => 458usize, - Self::UnicornNumericSeparatorsStyle(_) => 459usize, - Self::UnicornPreferAddEventListener(_) => 460usize, - Self::UnicornPreferArrayFind(_) => 461usize, - Self::UnicornPreferArrayFlat(_) => 462usize, - Self::UnicornPreferArrayFlatMap(_) => 463usize, - Self::UnicornPreferArrayIndexOf(_) => 464usize, - Self::UnicornPreferArraySome(_) => 465usize, - Self::UnicornPreferAt(_) => 466usize, - Self::UnicornPreferBigintLiterals(_) => 467usize, - Self::UnicornPreferBlobReadingMethods(_) => 468usize, - Self::UnicornPreferClassFields(_) => 469usize, - Self::UnicornPreferClasslistToggle(_) => 470usize, - Self::UnicornPreferCodePoint(_) => 471usize, - Self::UnicornPreferDateNow(_) => 472usize, - Self::UnicornPreferDefaultParameters(_) => 473usize, - Self::UnicornPreferDomNodeAppend(_) => 474usize, - Self::UnicornPreferDomNodeDataset(_) => 475usize, - Self::UnicornPreferDomNodeRemove(_) => 476usize, - Self::UnicornPreferDomNodeTextContent(_) => 477usize, - Self::UnicornPreferEventTarget(_) => 478usize, - Self::UnicornPreferGlobalThis(_) => 479usize, - Self::UnicornPreferIncludes(_) => 480usize, - Self::UnicornPreferKeyboardEventKey(_) => 481usize, - Self::UnicornPreferLogicalOperatorOverTernary(_) => 482usize, - Self::UnicornPreferMathMinMax(_) => 483usize, - Self::UnicornPreferMathTrunc(_) => 484usize, - Self::UnicornPreferModernDomApis(_) => 485usize, - Self::UnicornPreferModernMathApis(_) => 486usize, - Self::UnicornPreferNativeCoercionFunctions(_) => 487usize, - Self::UnicornPreferNegativeIndex(_) => 488usize, - Self::UnicornPreferNodeProtocol(_) => 489usize, - Self::UnicornPreferNumberProperties(_) => 490usize, - Self::UnicornPreferObjectFromEntries(_) => 491usize, - Self::UnicornPreferOptionalCatchBinding(_) => 492usize, - Self::UnicornPreferPrototypeMethods(_) => 493usize, - Self::UnicornPreferQuerySelector(_) => 494usize, - Self::UnicornPreferReflectApply(_) => 495usize, - Self::UnicornPreferRegexpTest(_) => 496usize, - Self::UnicornPreferResponseStaticJson(_) => 497usize, - Self::UnicornPreferSetHas(_) => 498usize, - Self::UnicornPreferSetSize(_) => 499usize, - Self::UnicornPreferSpread(_) => 500usize, - Self::UnicornPreferStringRaw(_) => 501usize, - Self::UnicornPreferStringReplaceAll(_) => 502usize, - Self::UnicornPreferStringSlice(_) => 503usize, - Self::UnicornPreferStringStartsEndsWith(_) => 504usize, - Self::UnicornPreferStringTrimStartEnd(_) => 505usize, - Self::UnicornPreferStructuredClone(_) => 506usize, - Self::UnicornPreferTopLevelAwait(_) => 507usize, - Self::UnicornPreferTypeError(_) => 508usize, - Self::UnicornRequireArrayJoinSeparator(_) => 509usize, - Self::UnicornRequireModuleAttributes(_) => 510usize, - Self::UnicornRequireModuleSpecifiers(_) => 511usize, - Self::UnicornRequireNumberToFixedDigitsArgument(_) => 512usize, - Self::UnicornRequirePostMessageTargetOrigin(_) => 513usize, - Self::UnicornSwitchCaseBraces(_) => 514usize, - Self::UnicornTextEncodingIdentifierCase(_) => 515usize, - Self::UnicornThrowNewError(_) => 516usize, - Self::JsxA11YAltText(_) => 517usize, - Self::JsxA11YAnchorAmbiguousText(_) => 518usize, - Self::JsxA11YAnchorHasContent(_) => 519usize, - Self::JsxA11YAnchorIsValid(_) => 520usize, - Self::JsxA11YAriaActivedescendantHasTabindex(_) => 521usize, - Self::JsxA11YAriaProps(_) => 522usize, - Self::JsxA11YAriaProptypes(_) => 523usize, - Self::JsxA11YAriaRole(_) => 524usize, - Self::JsxA11YAriaUnsupportedElements(_) => 525usize, - Self::JsxA11YAutocompleteValid(_) => 526usize, - Self::JsxA11YClickEventsHaveKeyEvents(_) => 527usize, - Self::JsxA11YHeadingHasContent(_) => 528usize, - Self::JsxA11YHtmlHasLang(_) => 529usize, - Self::JsxA11YIframeHasTitle(_) => 530usize, - Self::JsxA11YImgRedundantAlt(_) => 531usize, - Self::JsxA11YLabelHasAssociatedControl(_) => 532usize, - Self::JsxA11YLang(_) => 533usize, - Self::JsxA11YMediaHasCaption(_) => 534usize, - Self::JsxA11YMouseEventsHaveKeyEvents(_) => 535usize, - Self::JsxA11YNoAccessKey(_) => 536usize, - Self::JsxA11YNoAriaHiddenOnFocusable(_) => 537usize, - Self::JsxA11YNoAutofocus(_) => 538usize, - Self::JsxA11YNoDistractingElements(_) => 539usize, - Self::JsxA11YNoNoninteractiveTabindex(_) => 540usize, - Self::JsxA11YNoRedundantRoles(_) => 541usize, - Self::JsxA11YNoStaticElementInteractions(_) => 542usize, - Self::JsxA11YPreferTagOverRole(_) => 543usize, - Self::JsxA11YRoleHasRequiredAriaProps(_) => 544usize, - Self::JsxA11YRoleSupportsAriaProps(_) => 545usize, - Self::JsxA11YScope(_) => 546usize, - Self::JsxA11YTabindexNoPositive(_) => 547usize, - Self::OxcApproxConstant(_) => 548usize, - Self::OxcBadArrayMethodOnArguments(_) => 549usize, - Self::OxcBadBitwiseOperator(_) => 550usize, - Self::OxcBadCharAtComparison(_) => 551usize, - Self::OxcBadComparisonSequence(_) => 552usize, - Self::OxcBadMinMaxFunc(_) => 553usize, - Self::OxcBadObjectLiteralComparison(_) => 554usize, - Self::OxcBadReplaceAllArg(_) => 555usize, - Self::OxcBranchesSharingCode(_) => 556usize, - Self::OxcConstComparisons(_) => 557usize, - Self::OxcDoubleComparisons(_) => 558usize, - Self::OxcErasingOp(_) => 559usize, - Self::OxcMisrefactoredAssignOp(_) => 560usize, - Self::OxcMissingThrow(_) => 561usize, - Self::OxcNoAccumulatingSpread(_) => 562usize, - Self::OxcNoAsyncAwait(_) => 563usize, - Self::OxcNoAsyncEndpointHandlers(_) => 564usize, - Self::OxcNoBarrelFile(_) => 565usize, - Self::OxcNoConstEnum(_) => 566usize, - Self::OxcNoMapSpread(_) => 567usize, - Self::OxcNoOptionalChaining(_) => 568usize, - Self::OxcNoRestSpreadProperties(_) => 569usize, - Self::OxcNoThisInExportedFunction(_) => 570usize, - Self::OxcNumberArgOutOfRange(_) => 571usize, - Self::OxcOnlyUsedInRecursion(_) => 572usize, - Self::OxcUninvokedArrayCallback(_) => 573usize, - Self::NextjsGoogleFontDisplay(_) => 574usize, - Self::NextjsGoogleFontPreconnect(_) => 575usize, - Self::NextjsInlineScriptId(_) => 576usize, - Self::NextjsNextScriptForGa(_) => 577usize, - Self::NextjsNoAssignModuleVariable(_) => 578usize, - Self::NextjsNoAsyncClientComponent(_) => 579usize, - Self::NextjsNoBeforeInteractiveScriptOutsideDocument(_) => 580usize, - Self::NextjsNoCssTags(_) => 581usize, - Self::NextjsNoDocumentImportInPage(_) => 582usize, - Self::NextjsNoDuplicateHead(_) => 583usize, - Self::NextjsNoHeadElement(_) => 584usize, - Self::NextjsNoHeadImportInDocument(_) => 585usize, - Self::NextjsNoHtmlLinkForPages(_) => 586usize, - Self::NextjsNoImgElement(_) => 587usize, - Self::NextjsNoPageCustomFont(_) => 588usize, - Self::NextjsNoScriptComponentInHead(_) => 589usize, - Self::NextjsNoStyledJsxInDocument(_) => 590usize, - Self::NextjsNoSyncScripts(_) => 591usize, - Self::NextjsNoTitleInDocumentHead(_) => 592usize, - Self::NextjsNoTypos(_) => 593usize, - Self::NextjsNoUnwantedPolyfillio(_) => 594usize, - Self::JsdocCheckAccess(_) => 595usize, - Self::JsdocCheckPropertyNames(_) => 596usize, - Self::JsdocCheckTagNames(_) => 597usize, - Self::JsdocEmptyTags(_) => 598usize, - Self::JsdocImplementsOnClasses(_) => 599usize, - Self::JsdocNoDefaults(_) => 600usize, - Self::JsdocRequireParam(_) => 601usize, - Self::JsdocRequireParamDescription(_) => 602usize, - Self::JsdocRequireParamName(_) => 603usize, - Self::JsdocRequireParamType(_) => 604usize, - Self::JsdocRequireProperty(_) => 605usize, - Self::JsdocRequirePropertyDescription(_) => 606usize, - Self::JsdocRequirePropertyName(_) => 607usize, - Self::JsdocRequirePropertyType(_) => 608usize, - Self::JsdocRequireReturns(_) => 609usize, - Self::JsdocRequireReturnsDescription(_) => 610usize, - Self::JsdocRequireReturnsType(_) => 611usize, - Self::JsdocRequireYields(_) => 612usize, - Self::PromiseAlwaysReturn(_) => 613usize, - Self::PromiseAvoidNew(_) => 614usize, - Self::PromiseCatchOrReturn(_) => 615usize, - Self::PromiseNoCallbackInPromise(_) => 616usize, - Self::PromiseNoMultipleResolved(_) => 617usize, - Self::PromiseNoNesting(_) => 618usize, - Self::PromiseNoNewStatics(_) => 619usize, - Self::PromiseNoPromiseInCallback(_) => 620usize, - Self::PromiseNoReturnInFinally(_) => 621usize, - Self::PromiseNoReturnWrap(_) => 622usize, - Self::PromiseParamNames(_) => 623usize, - Self::PromisePreferAwaitToCallbacks(_) => 624usize, - Self::PromisePreferAwaitToThen(_) => 625usize, - Self::PromisePreferCatch(_) => 626usize, - Self::PromiseSpecOnly(_) => 627usize, - Self::PromiseValidParams(_) => 628usize, - Self::VitestConsistentEachFor(_) => 629usize, - Self::VitestConsistentTestFilename(_) => 630usize, - Self::VitestConsistentVitestVi(_) => 631usize, - Self::VitestHoistedApisOnTop(_) => 632usize, - Self::VitestNoConditionalTests(_) => 633usize, - Self::VitestNoImportNodeTest(_) => 634usize, - Self::VitestPreferCalledOnce(_) => 635usize, - Self::VitestPreferCalledTimes(_) => 636usize, - Self::VitestPreferDescribeFunctionTitle(_) => 637usize, - Self::VitestPreferToBeFalsy(_) => 638usize, - Self::VitestPreferToBeObject(_) => 639usize, - Self::VitestPreferToBeTruthy(_) => 640usize, - Self::VitestRequireLocalTestContextForConcurrentSnapshots(_) => 641usize, - Self::VitestWarnTodo(_) => 642usize, - Self::NodeGlobalRequire(_) => 643usize, - Self::NodeNoExportsAssign(_) => 644usize, - Self::NodeNoNewRequire(_) => 645usize, - Self::NodeNoProcessEnv(_) => 646usize, - Self::VueDefineEmitsDeclaration(_) => 647usize, - Self::VueDefinePropsDeclaration(_) => 648usize, - Self::VueDefinePropsDestructuring(_) => 649usize, - Self::VueMaxProps(_) => 650usize, - Self::VueNoArrowFunctionsInWatch(_) => 651usize, - Self::VueNoDeprecatedDestroyedLifecycle(_) => 652usize, - Self::VueNoExportInScriptSetup(_) => 653usize, - Self::VueNoImportCompilerMacros(_) => 654usize, - Self::VueNoLifecycleAfterAwait(_) => 655usize, - Self::VueNoMultipleSlotArgs(_) => 656usize, - Self::VueNoRequiredPropWithDefault(_) => 657usize, - Self::VueNoThisInBeforeRouteEnter(_) => 658usize, - Self::VuePreferImportFromVue(_) => 659usize, - Self::VueRequireDefaultExport(_) => 660usize, - Self::VueRequireTypedRef(_) => 661usize, - Self::VueValidDefineEmits(_) => 662usize, - Self::VueValidDefineProps(_) => 663usize, + Self::ReactNoMultiComp(_) => 373usize, + Self::ReactNoNamespace(_) => 374usize, + Self::ReactNoRedundantShouldComponentUpdate(_) => 375usize, + Self::ReactNoRenderReturnValue(_) => 376usize, + Self::ReactNoSetState(_) => 377usize, + Self::ReactNoStringRefs(_) => 378usize, + Self::ReactNoThisInSfc(_) => 379usize, + Self::ReactNoUnescapedEntities(_) => 380usize, + Self::ReactNoUnknownProperty(_) => 381usize, + Self::ReactNoUnsafe(_) => 382usize, + Self::ReactNoWillUpdateSetState(_) => 383usize, + Self::ReactOnlyExportComponents(_) => 384usize, + Self::ReactPreferEs6Class(_) => 385usize, + Self::ReactReactInJsxScope(_) => 386usize, + Self::ReactRequireRenderReturn(_) => 387usize, + Self::ReactRulesOfHooks(_) => 388usize, + Self::ReactSelfClosingComp(_) => 389usize, + Self::ReactStateInConstructor(_) => 390usize, + Self::ReactStylePropObject(_) => 391usize, + Self::ReactVoidDomElementsNoChildren(_) => 392usize, + Self::ReactPerfJsxNoJsxAsProp(_) => 393usize, + Self::ReactPerfJsxNoNewArrayAsProp(_) => 394usize, + Self::ReactPerfJsxNoNewFunctionAsProp(_) => 395usize, + Self::ReactPerfJsxNoNewObjectAsProp(_) => 396usize, + Self::UnicornCatchErrorName(_) => 397usize, + Self::UnicornConsistentAssert(_) => 398usize, + Self::UnicornConsistentDateClone(_) => 399usize, + Self::UnicornConsistentEmptyArraySpread(_) => 400usize, + Self::UnicornConsistentExistenceIndexCheck(_) => 401usize, + Self::UnicornConsistentFunctionScoping(_) => 402usize, + Self::UnicornEmptyBraceSpaces(_) => 403usize, + Self::UnicornErrorMessage(_) => 404usize, + Self::UnicornEscapeCase(_) => 405usize, + Self::UnicornExplicitLengthCheck(_) => 406usize, + Self::UnicornFilenameCase(_) => 407usize, + Self::UnicornNewForBuiltins(_) => 408usize, + Self::UnicornNoAbusiveEslintDisable(_) => 409usize, + Self::UnicornNoAccessorRecursion(_) => 410usize, + Self::UnicornNoAnonymousDefaultExport(_) => 411usize, + Self::UnicornNoArrayCallbackReference(_) => 412usize, + Self::UnicornNoArrayForEach(_) => 413usize, + Self::UnicornNoArrayMethodThisArgument(_) => 414usize, + Self::UnicornNoArrayReduce(_) => 415usize, + Self::UnicornNoArrayReverse(_) => 416usize, + Self::UnicornNoArraySort(_) => 417usize, + Self::UnicornNoAwaitExpressionMember(_) => 418usize, + Self::UnicornNoAwaitInPromiseMethods(_) => 419usize, + Self::UnicornNoConsoleSpaces(_) => 420usize, + Self::UnicornNoDocumentCookie(_) => 421usize, + Self::UnicornNoEmptyFile(_) => 422usize, + Self::UnicornNoHexEscape(_) => 423usize, + Self::UnicornNoImmediateMutation(_) => 424usize, + Self::UnicornNoInstanceofArray(_) => 425usize, + Self::UnicornNoInstanceofBuiltins(_) => 426usize, + Self::UnicornNoInvalidFetchOptions(_) => 427usize, + Self::UnicornNoInvalidRemoveEventListener(_) => 428usize, + Self::UnicornNoLengthAsSliceEnd(_) => 429usize, + Self::UnicornNoLonelyIf(_) => 430usize, + Self::UnicornNoMagicArrayFlatDepth(_) => 431usize, + Self::UnicornNoNegationInEqualityCheck(_) => 432usize, + Self::UnicornNoNestedTernary(_) => 433usize, + Self::UnicornNoNewArray(_) => 434usize, + Self::UnicornNoNewBuffer(_) => 435usize, + Self::UnicornNoNull(_) => 436usize, + Self::UnicornNoObjectAsDefaultParameter(_) => 437usize, + Self::UnicornNoProcessExit(_) => 438usize, + Self::UnicornNoSinglePromiseInPromiseMethods(_) => 439usize, + Self::UnicornNoStaticOnlyClass(_) => 440usize, + Self::UnicornNoThenable(_) => 441usize, + Self::UnicornNoThisAssignment(_) => 442usize, + Self::UnicornNoTypeofUndefined(_) => 443usize, + Self::UnicornNoUnnecessaryArrayFlatDepth(_) => 444usize, + Self::UnicornNoUnnecessaryArraySpliceCount(_) => 445usize, + Self::UnicornNoUnnecessaryAwait(_) => 446usize, + Self::UnicornNoUnnecessarySliceEnd(_) => 447usize, + Self::UnicornNoUnreadableArrayDestructuring(_) => 448usize, + Self::UnicornNoUnreadableIife(_) => 449usize, + Self::UnicornNoUselessCollectionArgument(_) => 450usize, + Self::UnicornNoUselessErrorCaptureStackTrace(_) => 451usize, + Self::UnicornNoUselessFallbackInSpread(_) => 452usize, + Self::UnicornNoUselessLengthCheck(_) => 453usize, + Self::UnicornNoUselessPromiseResolveReject(_) => 454usize, + Self::UnicornNoUselessSpread(_) => 455usize, + Self::UnicornNoUselessSwitchCase(_) => 456usize, + Self::UnicornNoUselessUndefined(_) => 457usize, + Self::UnicornNoZeroFractions(_) => 458usize, + Self::UnicornNumberLiteralCase(_) => 459usize, + Self::UnicornNumericSeparatorsStyle(_) => 460usize, + Self::UnicornPreferAddEventListener(_) => 461usize, + Self::UnicornPreferArrayFind(_) => 462usize, + Self::UnicornPreferArrayFlat(_) => 463usize, + Self::UnicornPreferArrayFlatMap(_) => 464usize, + Self::UnicornPreferArrayIndexOf(_) => 465usize, + Self::UnicornPreferArraySome(_) => 466usize, + Self::UnicornPreferAt(_) => 467usize, + Self::UnicornPreferBigintLiterals(_) => 468usize, + Self::UnicornPreferBlobReadingMethods(_) => 469usize, + Self::UnicornPreferClassFields(_) => 470usize, + Self::UnicornPreferClasslistToggle(_) => 471usize, + Self::UnicornPreferCodePoint(_) => 472usize, + Self::UnicornPreferDateNow(_) => 473usize, + Self::UnicornPreferDefaultParameters(_) => 474usize, + Self::UnicornPreferDomNodeAppend(_) => 475usize, + Self::UnicornPreferDomNodeDataset(_) => 476usize, + Self::UnicornPreferDomNodeRemove(_) => 477usize, + Self::UnicornPreferDomNodeTextContent(_) => 478usize, + Self::UnicornPreferEventTarget(_) => 479usize, + Self::UnicornPreferGlobalThis(_) => 480usize, + Self::UnicornPreferIncludes(_) => 481usize, + Self::UnicornPreferKeyboardEventKey(_) => 482usize, + Self::UnicornPreferLogicalOperatorOverTernary(_) => 483usize, + Self::UnicornPreferMathMinMax(_) => 484usize, + Self::UnicornPreferMathTrunc(_) => 485usize, + Self::UnicornPreferModernDomApis(_) => 486usize, + Self::UnicornPreferModernMathApis(_) => 487usize, + Self::UnicornPreferNativeCoercionFunctions(_) => 488usize, + Self::UnicornPreferNegativeIndex(_) => 489usize, + Self::UnicornPreferNodeProtocol(_) => 490usize, + Self::UnicornPreferNumberProperties(_) => 491usize, + Self::UnicornPreferObjectFromEntries(_) => 492usize, + Self::UnicornPreferOptionalCatchBinding(_) => 493usize, + Self::UnicornPreferPrototypeMethods(_) => 494usize, + Self::UnicornPreferQuerySelector(_) => 495usize, + Self::UnicornPreferReflectApply(_) => 496usize, + Self::UnicornPreferRegexpTest(_) => 497usize, + Self::UnicornPreferResponseStaticJson(_) => 498usize, + Self::UnicornPreferSetHas(_) => 499usize, + Self::UnicornPreferSetSize(_) => 500usize, + Self::UnicornPreferSpread(_) => 501usize, + Self::UnicornPreferStringRaw(_) => 502usize, + Self::UnicornPreferStringReplaceAll(_) => 503usize, + Self::UnicornPreferStringSlice(_) => 504usize, + Self::UnicornPreferStringStartsEndsWith(_) => 505usize, + Self::UnicornPreferStringTrimStartEnd(_) => 506usize, + Self::UnicornPreferStructuredClone(_) => 507usize, + Self::UnicornPreferTopLevelAwait(_) => 508usize, + Self::UnicornPreferTypeError(_) => 509usize, + Self::UnicornRequireArrayJoinSeparator(_) => 510usize, + Self::UnicornRequireModuleAttributes(_) => 511usize, + Self::UnicornRequireModuleSpecifiers(_) => 512usize, + Self::UnicornRequireNumberToFixedDigitsArgument(_) => 513usize, + Self::UnicornRequirePostMessageTargetOrigin(_) => 514usize, + Self::UnicornSwitchCaseBraces(_) => 515usize, + Self::UnicornTextEncodingIdentifierCase(_) => 516usize, + Self::UnicornThrowNewError(_) => 517usize, + Self::JsxA11YAltText(_) => 518usize, + Self::JsxA11YAnchorAmbiguousText(_) => 519usize, + Self::JsxA11YAnchorHasContent(_) => 520usize, + Self::JsxA11YAnchorIsValid(_) => 521usize, + Self::JsxA11YAriaActivedescendantHasTabindex(_) => 522usize, + Self::JsxA11YAriaProps(_) => 523usize, + Self::JsxA11YAriaProptypes(_) => 524usize, + Self::JsxA11YAriaRole(_) => 525usize, + Self::JsxA11YAriaUnsupportedElements(_) => 526usize, + Self::JsxA11YAutocompleteValid(_) => 527usize, + Self::JsxA11YClickEventsHaveKeyEvents(_) => 528usize, + Self::JsxA11YHeadingHasContent(_) => 529usize, + Self::JsxA11YHtmlHasLang(_) => 530usize, + Self::JsxA11YIframeHasTitle(_) => 531usize, + Self::JsxA11YImgRedundantAlt(_) => 532usize, + Self::JsxA11YLabelHasAssociatedControl(_) => 533usize, + Self::JsxA11YLang(_) => 534usize, + Self::JsxA11YMediaHasCaption(_) => 535usize, + Self::JsxA11YMouseEventsHaveKeyEvents(_) => 536usize, + Self::JsxA11YNoAccessKey(_) => 537usize, + Self::JsxA11YNoAriaHiddenOnFocusable(_) => 538usize, + Self::JsxA11YNoAutofocus(_) => 539usize, + Self::JsxA11YNoDistractingElements(_) => 540usize, + Self::JsxA11YNoNoninteractiveTabindex(_) => 541usize, + Self::JsxA11YNoRedundantRoles(_) => 542usize, + Self::JsxA11YNoStaticElementInteractions(_) => 543usize, + Self::JsxA11YPreferTagOverRole(_) => 544usize, + Self::JsxA11YRoleHasRequiredAriaProps(_) => 545usize, + Self::JsxA11YRoleSupportsAriaProps(_) => 546usize, + Self::JsxA11YScope(_) => 547usize, + Self::JsxA11YTabindexNoPositive(_) => 548usize, + Self::OxcApproxConstant(_) => 549usize, + Self::OxcBadArrayMethodOnArguments(_) => 550usize, + Self::OxcBadBitwiseOperator(_) => 551usize, + Self::OxcBadCharAtComparison(_) => 552usize, + Self::OxcBadComparisonSequence(_) => 553usize, + Self::OxcBadMinMaxFunc(_) => 554usize, + Self::OxcBadObjectLiteralComparison(_) => 555usize, + Self::OxcBadReplaceAllArg(_) => 556usize, + Self::OxcBranchesSharingCode(_) => 557usize, + Self::OxcConstComparisons(_) => 558usize, + Self::OxcDoubleComparisons(_) => 559usize, + Self::OxcErasingOp(_) => 560usize, + Self::OxcMisrefactoredAssignOp(_) => 561usize, + Self::OxcMissingThrow(_) => 562usize, + Self::OxcNoAccumulatingSpread(_) => 563usize, + Self::OxcNoAsyncAwait(_) => 564usize, + Self::OxcNoAsyncEndpointHandlers(_) => 565usize, + Self::OxcNoBarrelFile(_) => 566usize, + Self::OxcNoConstEnum(_) => 567usize, + Self::OxcNoMapSpread(_) => 568usize, + Self::OxcNoOptionalChaining(_) => 569usize, + Self::OxcNoRestSpreadProperties(_) => 570usize, + Self::OxcNoThisInExportedFunction(_) => 571usize, + Self::OxcNumberArgOutOfRange(_) => 572usize, + Self::OxcOnlyUsedInRecursion(_) => 573usize, + Self::OxcUninvokedArrayCallback(_) => 574usize, + Self::NextjsGoogleFontDisplay(_) => 575usize, + Self::NextjsGoogleFontPreconnect(_) => 576usize, + Self::NextjsInlineScriptId(_) => 577usize, + Self::NextjsNextScriptForGa(_) => 578usize, + Self::NextjsNoAssignModuleVariable(_) => 579usize, + Self::NextjsNoAsyncClientComponent(_) => 580usize, + Self::NextjsNoBeforeInteractiveScriptOutsideDocument(_) => 581usize, + Self::NextjsNoCssTags(_) => 582usize, + Self::NextjsNoDocumentImportInPage(_) => 583usize, + Self::NextjsNoDuplicateHead(_) => 584usize, + Self::NextjsNoHeadElement(_) => 585usize, + Self::NextjsNoHeadImportInDocument(_) => 586usize, + Self::NextjsNoHtmlLinkForPages(_) => 587usize, + Self::NextjsNoImgElement(_) => 588usize, + Self::NextjsNoPageCustomFont(_) => 589usize, + Self::NextjsNoScriptComponentInHead(_) => 590usize, + Self::NextjsNoStyledJsxInDocument(_) => 591usize, + Self::NextjsNoSyncScripts(_) => 592usize, + Self::NextjsNoTitleInDocumentHead(_) => 593usize, + Self::NextjsNoTypos(_) => 594usize, + Self::NextjsNoUnwantedPolyfillio(_) => 595usize, + Self::JsdocCheckAccess(_) => 596usize, + Self::JsdocCheckPropertyNames(_) => 597usize, + Self::JsdocCheckTagNames(_) => 598usize, + Self::JsdocEmptyTags(_) => 599usize, + Self::JsdocImplementsOnClasses(_) => 600usize, + Self::JsdocNoDefaults(_) => 601usize, + Self::JsdocRequireParam(_) => 602usize, + Self::JsdocRequireParamDescription(_) => 603usize, + Self::JsdocRequireParamName(_) => 604usize, + Self::JsdocRequireParamType(_) => 605usize, + Self::JsdocRequireProperty(_) => 606usize, + Self::JsdocRequirePropertyDescription(_) => 607usize, + Self::JsdocRequirePropertyName(_) => 608usize, + Self::JsdocRequirePropertyType(_) => 609usize, + Self::JsdocRequireReturns(_) => 610usize, + Self::JsdocRequireReturnsDescription(_) => 611usize, + Self::JsdocRequireReturnsType(_) => 612usize, + Self::JsdocRequireYields(_) => 613usize, + Self::PromiseAlwaysReturn(_) => 614usize, + Self::PromiseAvoidNew(_) => 615usize, + Self::PromiseCatchOrReturn(_) => 616usize, + Self::PromiseNoCallbackInPromise(_) => 617usize, + Self::PromiseNoMultipleResolved(_) => 618usize, + Self::PromiseNoNesting(_) => 619usize, + Self::PromiseNoNewStatics(_) => 620usize, + Self::PromiseNoPromiseInCallback(_) => 621usize, + Self::PromiseNoReturnInFinally(_) => 622usize, + Self::PromiseNoReturnWrap(_) => 623usize, + Self::PromiseParamNames(_) => 624usize, + Self::PromisePreferAwaitToCallbacks(_) => 625usize, + Self::PromisePreferAwaitToThen(_) => 626usize, + Self::PromisePreferCatch(_) => 627usize, + Self::PromiseSpecOnly(_) => 628usize, + Self::PromiseValidParams(_) => 629usize, + Self::VitestConsistentEachFor(_) => 630usize, + Self::VitestConsistentTestFilename(_) => 631usize, + Self::VitestConsistentVitestVi(_) => 632usize, + Self::VitestHoistedApisOnTop(_) => 633usize, + Self::VitestNoConditionalTests(_) => 634usize, + Self::VitestNoImportNodeTest(_) => 635usize, + Self::VitestPreferCalledOnce(_) => 636usize, + Self::VitestPreferCalledTimes(_) => 637usize, + Self::VitestPreferDescribeFunctionTitle(_) => 638usize, + Self::VitestPreferToBeFalsy(_) => 639usize, + Self::VitestPreferToBeObject(_) => 640usize, + Self::VitestPreferToBeTruthy(_) => 641usize, + Self::VitestRequireLocalTestContextForConcurrentSnapshots(_) => 642usize, + Self::VitestWarnTodo(_) => 643usize, + Self::NodeGlobalRequire(_) => 644usize, + Self::NodeNoExportsAssign(_) => 645usize, + Self::NodeNoNewRequire(_) => 646usize, + Self::NodeNoProcessEnv(_) => 647usize, + Self::VueDefineEmitsDeclaration(_) => 648usize, + Self::VueDefinePropsDeclaration(_) => 649usize, + Self::VueDefinePropsDestructuring(_) => 650usize, + Self::VueMaxProps(_) => 651usize, + Self::VueNoArrowFunctionsInWatch(_) => 652usize, + Self::VueNoDeprecatedDestroyedLifecycle(_) => 653usize, + Self::VueNoExportInScriptSetup(_) => 654usize, + Self::VueNoImportCompilerMacros(_) => 655usize, + Self::VueNoLifecycleAfterAwait(_) => 656usize, + Self::VueNoMultipleSlotArgs(_) => 657usize, + Self::VueNoRequiredPropWithDefault(_) => 658usize, + Self::VueNoThisInBeforeRouteEnter(_) => 659usize, + Self::VuePreferImportFromVue(_) => 660usize, + Self::VueRequireDefaultExport(_) => 661usize, + Self::VueRequireTypedRef(_) => 662usize, + Self::VueValidDefineEmits(_) => 663usize, + Self::VueValidDefineProps(_) => 664usize, } } pub fn name(&self) -> &'static str { @@ -2445,6 +2448,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(_) => ReactNoDirectMutationState::NAME, Self::ReactNoFindDomNode(_) => ReactNoFindDomNode::NAME, Self::ReactNoIsMounted(_) => ReactNoIsMounted::NAME, + Self::ReactNoMultiComp(_) => ReactNoMultiComp::NAME, Self::ReactNoNamespace(_) => ReactNoNamespace::NAME, Self::ReactNoRedundantShouldComponentUpdate(_) => { ReactNoRedundantShouldComponentUpdate::NAME @@ -3219,6 +3223,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(_) => ReactNoDirectMutationState::CATEGORY, Self::ReactNoFindDomNode(_) => ReactNoFindDomNode::CATEGORY, Self::ReactNoIsMounted(_) => ReactNoIsMounted::CATEGORY, + Self::ReactNoMultiComp(_) => ReactNoMultiComp::CATEGORY, Self::ReactNoNamespace(_) => ReactNoNamespace::CATEGORY, Self::ReactNoRedundantShouldComponentUpdate(_) => { ReactNoRedundantShouldComponentUpdate::CATEGORY @@ -3992,6 +3997,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(_) => ReactNoDirectMutationState::FIX, Self::ReactNoFindDomNode(_) => ReactNoFindDomNode::FIX, Self::ReactNoIsMounted(_) => ReactNoIsMounted::FIX, + Self::ReactNoMultiComp(_) => ReactNoMultiComp::FIX, Self::ReactNoNamespace(_) => ReactNoNamespace::FIX, Self::ReactNoRedundantShouldComponentUpdate(_) => { ReactNoRedundantShouldComponentUpdate::FIX @@ -4827,6 +4833,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(_) => ReactNoDirectMutationState::documentation(), Self::ReactNoFindDomNode(_) => ReactNoFindDomNode::documentation(), Self::ReactNoIsMounted(_) => ReactNoIsMounted::documentation(), + Self::ReactNoMultiComp(_) => ReactNoMultiComp::documentation(), Self::ReactNoNamespace(_) => ReactNoNamespace::documentation(), Self::ReactNoRedundantShouldComponentUpdate(_) => { ReactNoRedundantShouldComponentUpdate::documentation() @@ -6284,6 +6291,8 @@ impl RuleEnum { .or_else(|| ReactNoFindDomNode::schema(generator)), Self::ReactNoIsMounted(_) => ReactNoIsMounted::config_schema(generator) .or_else(|| ReactNoIsMounted::schema(generator)), + Self::ReactNoMultiComp(_) => ReactNoMultiComp::config_schema(generator) + .or_else(|| ReactNoMultiComp::schema(generator)), Self::ReactNoNamespace(_) => ReactNoNamespace::config_schema(generator) .or_else(|| ReactNoNamespace::schema(generator)), Self::ReactNoRedundantShouldComponentUpdate(_) => { @@ -7500,6 +7509,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(_) => "react", Self::ReactNoFindDomNode(_) => "react", Self::ReactNoIsMounted(_) => "react", + Self::ReactNoMultiComp(_) => "react", Self::ReactNoNamespace(_) => "react", Self::ReactNoRedundantShouldComponentUpdate(_) => "react", Self::ReactNoRenderReturnValue(_) => "react", @@ -8983,6 +8993,9 @@ impl RuleEnum { Self::ReactNoIsMounted(_) => { Ok(Self::ReactNoIsMounted(ReactNoIsMounted::from_configuration(value)?)) } + Self::ReactNoMultiComp(_) => { + Ok(Self::ReactNoMultiComp(ReactNoMultiComp::from_configuration(value)?)) + } Self::ReactNoNamespace(_) => { Ok(Self::ReactNoNamespace(ReactNoNamespace::from_configuration(value)?)) } @@ -10293,6 +10306,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(rule) => rule.to_configuration(), Self::ReactNoFindDomNode(rule) => rule.to_configuration(), Self::ReactNoIsMounted(rule) => rule.to_configuration(), + Self::ReactNoMultiComp(rule) => rule.to_configuration(), Self::ReactNoNamespace(rule) => rule.to_configuration(), Self::ReactNoRedundantShouldComponentUpdate(rule) => rule.to_configuration(), Self::ReactNoRenderReturnValue(rule) => rule.to_configuration(), @@ -10963,6 +10977,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(rule) => rule.run(node, ctx), Self::ReactNoFindDomNode(rule) => rule.run(node, ctx), Self::ReactNoIsMounted(rule) => rule.run(node, ctx), + Self::ReactNoMultiComp(rule) => rule.run(node, ctx), Self::ReactNoNamespace(rule) => rule.run(node, ctx), Self::ReactNoRedundantShouldComponentUpdate(rule) => rule.run(node, ctx), Self::ReactNoRenderReturnValue(rule) => rule.run(node, ctx), @@ -11631,6 +11646,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(rule) => rule.run_once(ctx), Self::ReactNoFindDomNode(rule) => rule.run_once(ctx), Self::ReactNoIsMounted(rule) => rule.run_once(ctx), + Self::ReactNoMultiComp(rule) => rule.run_once(ctx), Self::ReactNoNamespace(rule) => rule.run_once(ctx), Self::ReactNoRedundantShouldComponentUpdate(rule) => rule.run_once(ctx), Self::ReactNoRenderReturnValue(rule) => rule.run_once(ctx), @@ -12357,6 +12373,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(rule) => rule.run_on_jest_node(jest_node, ctx), Self::ReactNoFindDomNode(rule) => rule.run_on_jest_node(jest_node, ctx), Self::ReactNoIsMounted(rule) => rule.run_on_jest_node(jest_node, ctx), + Self::ReactNoMultiComp(rule) => rule.run_on_jest_node(jest_node, ctx), Self::ReactNoNamespace(rule) => rule.run_on_jest_node(jest_node, ctx), Self::ReactNoRedundantShouldComponentUpdate(rule) => { rule.run_on_jest_node(jest_node, ctx) @@ -13055,6 +13072,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(rule) => rule.should_run(ctx), Self::ReactNoFindDomNode(rule) => rule.should_run(ctx), Self::ReactNoIsMounted(rule) => rule.should_run(ctx), + Self::ReactNoMultiComp(rule) => rule.should_run(ctx), Self::ReactNoNamespace(rule) => rule.should_run(ctx), Self::ReactNoRedundantShouldComponentUpdate(rule) => rule.should_run(ctx), Self::ReactNoRenderReturnValue(rule) => rule.should_run(ctx), @@ -13859,6 +13877,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(_) => ReactNoDirectMutationState::IS_TSGOLINT_RULE, Self::ReactNoFindDomNode(_) => ReactNoFindDomNode::IS_TSGOLINT_RULE, Self::ReactNoIsMounted(_) => ReactNoIsMounted::IS_TSGOLINT_RULE, + Self::ReactNoMultiComp(_) => ReactNoMultiComp::IS_TSGOLINT_RULE, Self::ReactNoNamespace(_) => ReactNoNamespace::IS_TSGOLINT_RULE, Self::ReactNoRedundantShouldComponentUpdate(_) => { ReactNoRedundantShouldComponentUpdate::IS_TSGOLINT_RULE @@ -14655,6 +14674,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(rule) => rule.types_info(), Self::ReactNoFindDomNode(rule) => rule.types_info(), Self::ReactNoIsMounted(rule) => rule.types_info(), + Self::ReactNoMultiComp(rule) => rule.types_info(), Self::ReactNoNamespace(rule) => rule.types_info(), Self::ReactNoRedundantShouldComponentUpdate(rule) => rule.types_info(), Self::ReactNoRenderReturnValue(rule) => rule.types_info(), @@ -15323,6 +15343,7 @@ impl RuleEnum { Self::ReactNoDirectMutationState(rule) => rule.run_info(), Self::ReactNoFindDomNode(rule) => rule.run_info(), Self::ReactNoIsMounted(rule) => rule.run_info(), + Self::ReactNoMultiComp(rule) => rule.run_info(), Self::ReactNoNamespace(rule) => rule.run_info(), Self::ReactNoRedundantShouldComponentUpdate(rule) => rule.run_info(), Self::ReactNoRenderReturnValue(rule) => rule.run_info(), @@ -16067,6 +16088,7 @@ pub static RULES: std::sync::LazyLock> = std::sync::LazyLock::new( RuleEnum::ReactNoDirectMutationState(ReactNoDirectMutationState::default()), RuleEnum::ReactNoFindDomNode(ReactNoFindDomNode::default()), RuleEnum::ReactNoIsMounted(ReactNoIsMounted::default()), + RuleEnum::ReactNoMultiComp(ReactNoMultiComp::default()), RuleEnum::ReactNoNamespace(ReactNoNamespace::default()), RuleEnum::ReactNoRedundantShouldComponentUpdate( ReactNoRedundantShouldComponentUpdate::default(), diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 4346f13b6b539..b92983bf315c4 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -390,6 +390,7 @@ pub(crate) mod react { pub mod no_direct_mutation_state; pub mod no_find_dom_node; pub mod no_is_mounted; + pub mod no_multi_comp; pub mod no_namespace; pub mod no_redundant_should_component_update; pub mod no_render_return_value; diff --git a/crates/oxc_linter/src/rules/react/no_multi_comp.rs b/crates/oxc_linter/src/rules/react/no_multi_comp.rs new file mode 100644 index 0000000000000..f1cbb21750d6f --- /dev/null +++ b/crates/oxc_linter/src/rules/react/no_multi_comp.rs @@ -0,0 +1,743 @@ +use oxc_ast::{ + AstKind, + ast::{ + Argument, AssignmentExpression, AssignmentTarget, CallExpression, Class, + ExportDefaultDeclaration, ExportDefaultDeclarationKind, Expression, Function, + ObjectProperty, PropertyKey, Statement, VariableDeclarator, + }, +}; +use oxc_ast_visit::{Visit, walk}; +use oxc_diagnostics::OxcDiagnostic; +use oxc_macros::declare_oxc_lint; +use oxc_span::Span; +use oxc_syntax::scope::ScopeFlags; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::{ + context::LintContext, + rule::{DefaultRuleConfig, Rule}, + rules::ContextHost, + utils::{ + expression_contains_jsx, function_body_contains_jsx, function_contains_jsx, is_hoc_call, + is_react_component_name, + }, +}; + +fn no_multi_comp_diagnostic(component_name: &str, span: Span) -> OxcDiagnostic { + OxcDiagnostic::warn(format!( + "Declare only one React component per file. Found: {component_name}" + )) + .with_help("Move this component to a separate file.") + .with_label(span) +} + +#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "camelCase", default, deny_unknown_fields)] +struct NoMultiCompConfig { + // When `true`, the rule will ignore stateless components and will allow you to have multiple + // stateless components in the same file. Or one stateful component and one-or-more stateless + // components in the same file. + // + // Stateless basically just means function components, including those created via + // `memo` and `forwardRef`. + ignore_stateless: bool, +} + +#[derive(Debug, Default, Clone, Deserialize, Serialize, JsonSchema)] +pub struct NoMultiComp(NoMultiCompConfig); + +declare_oxc_lint!( + /// ### What it does + /// + /// Prevents multiple React components from being defined in the same file. + /// + /// ### Why is this bad? + /// + /// Declaring multiple components in a single file can make it harder to navigate + /// and maintain the codebase. Each component should ideally be in its own file + /// for better organization and reusability. + /// + /// ### Examples + /// + /// Examples of **incorrect** code for this rule: + /// ```jsx + /// function Foo({ name }) { + /// return
Hello {name}
; + /// } + /// + /// function Bar({ name }) { + /// return
Hello again {name}
; + /// } + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```jsx + /// function Foo({ name }) { + /// return
Hello {name}
; + /// } + /// ``` + NoMultiComp, + react, + restriction, + none, + config = NoMultiComp, +); + +/// Represents a detected React component +#[derive(Debug, Clone)] +struct DetectedComponent { + name: String, + span: Span, + is_stateless: bool, +} + +impl Rule for NoMultiComp { + fn from_configuration(value: serde_json::Value) -> Result { + serde_json::from_value::>(value).map(DefaultRuleConfig::into_inner) + } + + fn run_once(&self, ctx: &LintContext) { + let mut finder = ComponentFinder::new(ctx); + finder.visit_program(ctx.nodes().program()); + + // Filter components based on ignoreStateless option and report all after the first + for component in + finder.components.iter().filter(|c| !self.0.ignore_stateless || !c.is_stateless).skip(1) + { + ctx.diagnostic(no_multi_comp_diagnostic(&component.name, component.span)); + } + } + + fn should_run(&self, ctx: &ContextHost) -> bool { + ctx.source_type().is_jsx() + } +} + +/// Visitor that finds React components while tracking nesting depth. +/// Components found while inside another component are not recorded. +struct ComponentFinder<'a, 'ctx> { + components: Vec, + component_depth: usize, + ctx: &'ctx LintContext<'a>, + /// Track variable name when visiting VariableDeclarator so we can access it in nested visits + current_var_name: Option, +} + +impl<'a, 'ctx> ComponentFinder<'a, 'ctx> { + fn new(ctx: &'ctx LintContext<'a>) -> Self { + Self { components: Vec::new(), component_depth: 0, ctx, current_var_name: None } + } + + fn record_component(&mut self, name: String, span: Span, is_stateless: bool) { + if self.component_depth == 0 { + self.components.push(DetectedComponent { name, span, is_stateless }); + } + } +} + +impl<'a> Visit<'a> for ComponentFinder<'a, '_> { + fn visit_class(&mut self, class: &Class<'a>) { + if is_es6_component_class(class) { + let name = class + .id + .as_ref() + .map_or_else(|| "UnnamedComponent".into(), |id| id.name.to_string()); + self.record_component(name, class.span, false); + self.component_depth += 1; + walk::walk_class(self, class); + self.component_depth -= 1; + } else { + walk::walk_class(self, class); + } + } + + fn visit_function(&mut self, func: &Function<'a>, flags: ScopeFlags) { + // Named function that contains JSX: function Foo() { return
} + if let Some(func_id) = &func.id + && is_react_component_name(&func_id.name) + && function_contains_jsx(func) + { + self.record_component(func_id.name.to_string(), func.span, true); + self.component_depth += 1; + walk::walk_function(self, func, flags); + self.component_depth -= 1; + } else { + walk::walk_function(self, func, flags); + } + } + + fn visit_variable_declarator(&mut self, decl: &VariableDeclarator<'a>) { + if let Some(component) = detect_variable_component(decl, self.ctx) { + self.record_component(component.name, component.span, component.is_stateless); + // Store var name for potential createReactClass detection in nested call + self.current_var_name = decl.id.get_identifier_name().map(|s| s.to_string()); + self.component_depth += 1; + walk::walk_variable_declarator(self, decl); + self.component_depth -= 1; + self.current_var_name = None; + } else { + // Check if this might contain a createReactClass call + let old_name = self.current_var_name.take(); + self.current_var_name = decl.id.get_identifier_name().map(|s| s.to_string()); + walk::walk_variable_declarator(self, decl); + self.current_var_name = old_name; + } + } + + fn visit_call_expression(&mut self, call: &CallExpression<'a>) { + // ES5 component: createReactClass({...}) + if is_es5_component_call(call) && self.component_depth == 0 { + let name = self.current_var_name.clone().unwrap_or_else(|| "UnnamedComponent".into()); + self.record_component(name, call.span, false); + self.component_depth += 1; + walk::walk_call_expression(self, call); + self.component_depth -= 1; + } else { + walk::walk_call_expression(self, call); + } + } + + fn visit_export_default_declaration(&mut self, export_decl: &ExportDefaultDeclaration<'a>) { + // export default React.forwardRef(...) + if let ExportDefaultDeclarationKind::CallExpression(call) = &export_decl.declaration + && is_hoc_component(call, self.ctx) + { + self.record_component("UnnamedComponent".into(), export_decl.span, true); + self.component_depth += 1; + walk::walk_export_default_declaration(self, export_decl); + self.component_depth -= 1; + } else { + walk::walk_export_default_declaration(self, export_decl); + } + } + + fn visit_object_property(&mut self, prop: &ObjectProperty<'a>) { + // { RenderFoo() { return
} } + // We increment depth after recording to prevent the inner function from being + // detected again when visiting the function expression. + if let PropertyKey::StaticIdentifier(id) = &prop.key + && is_react_component_name(&id.name) + && let Expression::FunctionExpression(func) = &prop.value + && function_contains_jsx(func) + { + self.record_component(id.name.to_string(), prop.span, true); + self.component_depth += 1; + walk::walk_object_property(self, prop); + self.component_depth -= 1; + } else { + walk::walk_object_property(self, prop); + } + } + + fn visit_assignment_expression(&mut self, assign: &AssignmentExpression<'a>) { + // exports.Foo = function() { return
} + // We increment depth after recording to prevent the inner function from being + // detected again when visiting the function expression. + if let AssignmentTarget::StaticMemberExpression(member) = &assign.left { + let prop_name = member.property.name.as_str(); + if is_react_component_name(prop_name) { + let is_component = expression_contains_jsx(&assign.right) + || matches!(&assign.right, Expression::FunctionExpression(func) if returns_component(func)); + + if is_component { + self.record_component(prop_name.to_string(), assign.span, true); + self.component_depth += 1; + walk::walk_assignment_expression(self, assign); + self.component_depth -= 1; + return; + } + } + } + walk::walk_assignment_expression(self, assign); + } +} + +/// Detect component from variable declarator (without ancestor check - handled by visitor depth) +fn detect_variable_component( + decl: &VariableDeclarator, + ctx: &LintContext, +) -> Option { + let name = decl.id.get_identifier_name()?.to_string(); + + if !is_react_component_name(&name) { + return None; + } + + let init = decl.init.as_ref()?.without_parentheses(); + + // Arrow function or function expression with JSX, or returning null (valid component pattern) + if expression_contains_jsx(init) || is_function_returning_null(init) { + return Some(DetectedComponent { name, span: decl.span, is_stateless: true }); + } + + // Sequence expression: const Foo = (0, () =>
) or const Foo = (0, () => null) + if let Expression::SequenceExpression(seq) = init + && let Some(last) = seq.expressions.last() + && (expression_contains_jsx(last) || is_function_returning_null(last)) + { + return Some(DetectedComponent { name, span: decl.span, is_stateless: true }); + } + + // HOC: const Foo = memo(() =>
) + if let Expression::CallExpression(call) = init + && is_hoc_component(call, ctx) + { + return Some(DetectedComponent { name, span: decl.span, is_stateless: true }); + } + + None +} + +/// Check if a call expression is a HOC (memo/forwardRef) wrapping a component +fn is_hoc_component(call: &CallExpression, ctx: &LintContext) -> bool { + get_hoc_callee_name(call, ctx).is_some_and(|name| is_hoc_call(&name, ctx)) + && call.arguments.first().is_some_and(|arg| match arg { + Argument::FunctionExpression(func) => { + !is_passthrough_function(func) && function_contains_jsx(func) + } + Argument::ArrowFunctionExpression(arrow) => { + !is_passthrough_arrow(arrow) && function_body_contains_jsx(&arrow.body) + } + _ => false, + }) +} + +/// Get the name of a HOC callee, resolving local aliases +fn get_hoc_callee_name(call: &CallExpression, ctx: &LintContext) -> Option { + // Direct name like React.memo, memo, or forwardRef + if let Some(name) = call.callee_name() { + return Some(name.to_string()); + } + + // Check for aliased imports: const myMemo = React.memo + // Note: This does not handle destructured aliased imports like `const {memo: myMemo} = React` + let Expression::Identifier(ident) = &call.callee else { + return None; + }; + + let scoping = ctx.scoping(); + let reference = scoping.get_reference(ident.reference_id()); + let symbol_id = reference.symbol_id()?; + let decl_node = ctx.nodes().get_node(scoping.symbol_declaration(symbol_id)); + let AstKind::VariableDeclarator(var_decl) = decl_node.kind() else { + return None; + }; + let Expression::StaticMemberExpression(member) = var_decl.init.as_ref()? else { + return None; + }; + let Expression::Identifier(obj) = &member.object else { + return None; + }; + + (obj.name == "React" && matches!(member.property.name.as_str(), "memo" | "forwardRef")) + .then(|| format!("React.{}", member.property.name)) +} + +/// Check if a function just passes through to a single JSX component +fn is_passthrough_function(func: &oxc_ast::ast::Function) -> bool { + func.body.as_ref().is_some_and(|body| is_single_return_passthrough(&body.statements)) +} + +/// Check if an arrow function just passes through to a single JSX component +fn is_passthrough_arrow(arrow: &oxc_ast::ast::ArrowFunctionExpression) -> bool { + // Expression arrow: `() => ` + arrow.get_expression().is_some_and(is_simple_jsx_passthrough) + // Block body with single return: `() => { return ; }` + || is_single_return_passthrough(&arrow.body.statements) +} + +/// Check if statements consist of a single return with a simple JSX passthrough +fn is_single_return_passthrough(statements: &[Statement]) -> bool { + matches!(statements, [Statement::ReturnStatement(ret)] if ret.argument.as_ref().is_some_and(is_simple_jsx_passthrough)) +} + +/// Check if an expression is a simple JSX element that just renders another component +/// This is for cases like: React.forwardRef((props, ref) => ) +fn is_simple_jsx_passthrough(expr: &Expression) -> bool { + let Expression::JSXElement(jsx) = expr else { + return false; + }; + let oxc_ast::ast::JSXElementName::IdentifierReference(id) = &jsx.opening_element.name else { + return false; + }; + let attrs = &jsx.opening_element.attributes; + + // Must be a component (PascalCase), have a spread attribute, and at most 2 attributes + is_react_component_name(&id.name) + && attrs.len() <= 2 + && attrs + .iter() + .any(|attr| matches!(attr, oxc_ast::ast::JSXAttributeItem::SpreadAttribute(_))) +} + +/// Check if a function returns another function with JSX (component factory) +fn returns_component(func: &Function) -> bool { + func.body.as_ref().is_some_and(|body| { + body.statements.iter().any(|stmt| { + matches!(stmt, Statement::ReturnStatement(ret) if ret.argument.as_ref().is_some_and(expression_contains_jsx)) + }) + }) +} + +/// Check if an expression is a function that returns null (valid React component pattern) +fn is_function_returning_null(expr: &Expression) -> bool { + match expr { + Expression::ArrowFunctionExpression(arrow) => { + // `() => null` + if let Some(expr) = arrow.get_expression() { + return expr.is_null(); + } + // `() => { return null; }` + arrow.body.statements.iter().any(|stmt| { + matches!(stmt, Statement::ReturnStatement(ret) if ret.argument.as_ref().is_some_and(Expression::is_null)) + }) + } + Expression::FunctionExpression(func) => func.body.as_ref().is_some_and(|body| { + body.statements.iter().any(|stmt| { + matches!(stmt, Statement::ReturnStatement(ret) if ret.argument.as_ref().is_some_and(Expression::is_null)) + }) + }), + _ => false, + } +} + +/// Check if a class is an ES6 React component (extends React.Component or React.PureComponent) +fn is_es6_component_class(class: &Class) -> bool { + class.super_class.as_ref().is_some_and(|super_class| { + if let Some(member_expr) = super_class.as_member_expression() + && let Expression::Identifier(ident) = member_expr.object() + && ident.name == "React" + { + return member_expr + .static_property_name() + .is_some_and(|name| matches!(name, "Component" | "PureComponent")); + } + super_class + .get_identifier_reference() + .is_some_and(|id| matches!(id.name.as_str(), "Component" | "PureComponent")) + }) +} + +/// Check if a call expression is createReactClass +fn is_es5_component_call(call: &CallExpression) -> bool { + if let Some(member_expr) = call.callee.as_member_expression() + && let Expression::Identifier(ident) = member_expr.object() + && ident.name == "React" + { + return member_expr.static_property_name() == Some("createReactClass"); + } + call.callee.get_identifier_reference().is_some_and(|id| id.name == "createReactClass") +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + (r#"var Hello = require('./components/Hello'); + var HelloJohn = createReactClass({ + render: function() { + return ; + } + });"#, None, None), + ("class Hello extends React.Component { + render() { + return
Hello {this.props.name}
; + } + }", None, None), + ("var Heading = createReactClass({ + render: function() { + return ( +
+ {this.props.buttons.map(function(button, index) { + return
+ ); + } + });", None, None), + ("function Hello(props) { + return
Hello {props.name}
; + } + function HelloAgain(props) { + return
Hello again {props.name}
; + }", Some(serde_json::json!([{ "ignoreStateless": true }])), None), + (r#"function Hello(props) { + return
Hello {props.name}
; + } + class HelloJohn extends React.Component { + render() { + return ; + } + }"#, Some(serde_json::json!([{ "ignoreStateless": true }])), None), + (r#"import React, { createElement } from "react" + const helperFoo = () => { + return true; + }; + function helperBar() { + return false; + }; + function RealComponent() { + return createElement("img"); + };"#, None, None), + (r#"const Hello = React.memo(function(props) { + return
Hello {props.name}
; + }); + class HelloJohn extends React.Component { + render() { + return ; + } + }"#, Some(serde_json::json!([{ "ignoreStateless": true }])), None), + ("class StoreListItem extends React.PureComponent { + // A bunch of stuff here + } + export default React.forwardRef((props, ref) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("class StoreListItem extends React.PureComponent { + // A bunch of stuff here + } + export default React.forwardRef((props, ref) => { + return + });", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const HelloComponent = (props) => { + return
; + } + export default React.forwardRef((props, ref) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("class StoreListItem extends React.PureComponent { + // A bunch of stuff here + } + export default React.forwardRef( + function myFunction(props, ref) { + return ; + } + );", Some(serde_json::json!([{ "ignoreStateless": true }])), None), + ("const HelloComponent = (props) => { + return
; + } + class StoreListItem extends React.PureComponent { + // A bunch of stuff here + } + export default React.forwardRef( + function myFunction(props, ref) { + return ; + } + );", Some(serde_json::json!([{ "ignoreStateless": true }])), None), + ("const HelloComponent = (props) => { + return
; + } + export default React.memo((props, ref) => );", Some(serde_json::json!([{ "ignoreStateless": true }])), None), + (r#"import React from 'react'; + function memo() { + var outOfScope = "hello" + return null; + } + class ComponentY extends React.Component { + memoCities = memo((cities) => cities.map((v) => ({ label: v }))); + render() { + return ( +
+
Counter
+
+ ); + } + }"#, None, None), + (r#"const MenuList = forwardRef(({onClose, ...props}, ref) => { + const {t} = useTranslation(); + const handleLogout = useLogoutHandler(); + + const onLogout = useCallback(() => { + onClose(); + handleLogout(); + }, [onClose, handleLogout]); + + return ( + + + {t('global-logout')} + + + ); + }); + + MenuList.displayName = 'MenuList'; + + MenuList.propTypes = { + onClose: PropTypes.func, + }; + + MenuList.defaultProps = { + onClose: () => null, + }; + + export default MenuList;"#, None, None), + (r#"const MenuList = forwardRef(({ onClose, ...props }, ref) => { + const onLogout = useCallback(() => { + onClose() + }, [onClose]) + + return ( + + + Logout + + + ) + }) + + MenuList.displayName = 'MenuList' + + MenuList.propTypes = { + onClose: PropTypes.func + } + + MenuList.defaultProps = { + onClose: () => null + } + + export default MenuList"#, None, None), + // These do not count as React components because the name is not capitalized. + ("export const foo = () => { return null; } + export const bar = () => { return null; }", None, None), + ]; + + let fail = vec![ + ("function Hello(props) { + return
Hello {props.name}
; + } + function HelloAgain(props) { + return
Hello again {props.name}
; + }", None, None), + (r#"function Hello(props) { + return
Hello {props.name}
; + } + class HelloJohn extends React.Component { + render() { + return ; + } + }"#, None, None), + ("export default { + RenderHello(props) { + let {name} = props; + return
{name}
; + }, + RenderHello2(props) { + let {name} = props; + return
{name}
; + } + };", None, None), + ("exports.Foo = function Foo() { + return <> + } + + exports.createSomeComponent = function createSomeComponent(opts) { + return function Foo() { + return <>{opts.a} + } + }", None, None), + ("class StoreListItem extends React.PureComponent { + // A bunch of stuff here + } + export default React.forwardRef((props, ref) =>
);", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const HelloComponent = (props) => { + return
; + } + const HelloComponent2 = React.forwardRef((props, ref) =>
);", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const HelloComponent = (0, (props) => { + return
; + }); + const HelloComponent2 = React.forwardRef((props, ref) => <>);", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const forwardRef = React.forwardRef; + const HelloComponent = (0, (props) => { + return
; + }); + const HelloComponent2 = forwardRef((props, ref) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const memo = React.memo; + const HelloComponent = (props) => { + return
; + }; + const HelloComponent2 = memo((props) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const {forwardRef} = React; + const HelloComponent = (0, (props) => { + return
; + }); + const HelloComponent2 = forwardRef((props, ref) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const {memo} = React; + const HelloComponent = (0, (props) => { + return
; + }); + const HelloComponent2 = memo((props) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("import React, { memo } from 'react'; + const HelloComponent = (0, (props) => { + return
; + }); + const HelloComponent2 = memo((props) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("import {forwardRef} from 'react'; + const HelloComponent = (0, (props) => { + return
; + }); + const HelloComponent2 = forwardRef((props, ref) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const { memo } = require('react'); + const HelloComponent = (0, (props) => { + return
; + }); + const HelloComponent2 = memo((props) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const {forwardRef} = require('react'); + const HelloComponent = (0, (props) => { + return
; + }); + const HelloComponent2 = forwardRef((props, ref) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const forwardRef = require('react').forwardRef; + const HelloComponent = (0, (props) => { + return
; + }); + const HelloComponent2 = forwardRef((props, ref) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + ("const memo = require('react').memo; + const HelloComponent = (0, (props) => { + return
; + }); + const HelloComponent2 = memo((props) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + // We do not support the pragma option. + // ("import Foo, { memo, forwardRef } from 'foo'; + // const Text = forwardRef(({ text }, ref) => { + // return
{text}
; + // }) + // const Label = memo(() => );", None, Some(serde_json::json!({ "settings": { "react": { "pragma": "Foo", }, } }))) + + // Custom tests not from the original rule. + + // Multiple named exports with HOCs + ("import { memo, forwardRef } from 'react'; + export const Foo = memo(() =>
); + export const Bar = forwardRef((props, ref) => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + // Class components with direct Component/PureComponent imports + ("import { Component } from 'react'; + class Foo extends Component { + render() { return
; } + } + class Bar extends Component { + render() { return ; } + }", None, None), + ("import { PureComponent } from 'react'; + class Foo extends PureComponent { + render() { return
; } + } + class Bar extends PureComponent { + render() { return ; } + }", None, None), + // Anonymous default export with another component + ("import { memo } from 'react'; + const Foo = () =>
; + export default memo(() => );", Some(serde_json::json!([{ "ignoreStateless": false }])), None), + // Count it as a React component if you return null and have a PascalCase name. + ("export const Foo = () => { + return
; + } + export const Bar = () => { return null; }", None, None), + ("export const Foo = () => { return null; } + export const Bar = () => { return null; }", None, None), + ("export const Foo = () => null; + export const Bar = () => null;", None, None), + ]; + + Tester::new(NoMultiComp::NAME, NoMultiComp::PLUGIN, pass, fail).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/react_no_multi_comp.snap b/crates/oxc_linter/src/snapshots/react_no_multi_comp.snap new file mode 100644 index 0000000000000..8b9c2019492b1 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/react_no_multi_comp.snap @@ -0,0 +1,205 @@ +--- +source: crates/oxc_linter/src/tester.rs +--- + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloAgain + ╭─[no_multi_comp.tsx:4:11] + 3 │ } + 4 │ ╭─▶ function HelloAgain(props) { + 5 │ │ return
Hello again {props.name}
; + 6 │ ╰─▶ } + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloJohn + ╭─[no_multi_comp.tsx:4:13] + 3 │ } + 4 │ ╭─▶ class HelloJohn extends React.Component { + 5 │ │ render() { + 6 │ │ return ; + 7 │ │ } + 8 │ ╰─▶ } + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: RenderHello2 + ╭─[no_multi_comp.tsx:6:13] + 5 │ }, + 6 │ ╭─▶ RenderHello2(props) { + 7 │ │ let {name} = props; + 8 │ │ return
{name}
; + 9 │ ╰─▶ } + 10 │ }; + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: Foo + ╭─[no_multi_comp.tsx:6:20] + 5 │ exports.createSomeComponent = function createSomeComponent(opts) { + 6 │ ╭─▶ return function Foo() { + 7 │ │ return <>{opts.a} + 8 │ ╰─▶ } + 9 │ } + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: UnnamedComponent + ╭─[no_multi_comp.tsx:4:13] + 3 │ } + 4 │ export default React.forwardRef((props, ref) =>
); + · ────────────────────────────────────────────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:4:17] + 3 │ } + 4 │ const HelloComponent2 = React.forwardRef((props, ref) =>
); + · ─────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:4:17] + 3 │ }); + 4 │ const HelloComponent2 = React.forwardRef((props, ref) => <>); + · ────────────────────────────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:5:17] + 4 │ }); + 5 │ const HelloComponent2 = forwardRef((props, ref) => ); + · ─────────────────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:5:17] + 4 │ }; + 5 │ const HelloComponent2 = memo((props) => ); + · ──────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:5:17] + 4 │ }); + 5 │ const HelloComponent2 = forwardRef((props, ref) => ); + · ─────────────────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:5:17] + 4 │ }); + 5 │ const HelloComponent2 = memo((props) => ); + · ──────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:5:17] + 4 │ }); + 5 │ const HelloComponent2 = memo((props) => ); + · ──────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:5:17] + 4 │ }); + 5 │ const HelloComponent2 = forwardRef((props, ref) => ); + · ─────────────────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:5:17] + 4 │ }); + 5 │ const HelloComponent2 = memo((props) => ); + · ──────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:5:17] + 4 │ }); + 5 │ const HelloComponent2 = forwardRef((props, ref) => ); + · ─────────────────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:5:17] + 4 │ }); + 5 │ const HelloComponent2 = forwardRef((props, ref) => ); + · ─────────────────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: HelloComponent2 + ╭─[no_multi_comp.tsx:5:17] + 4 │ }); + 5 │ const HelloComponent2 = memo((props) => ); + · ──────────────────────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: Bar + ╭─[no_multi_comp.tsx:3:24] + 2 │ export const Foo = memo(() =>
); + 3 │ export const Bar = forwardRef((props, ref) => ); + · ─────────────────────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: Bar + ╭─[no_multi_comp.tsx:5:11] + 4 │ } + 5 │ ╭─▶ class Bar extends Component { + 6 │ │ render() { return ; } + 7 │ ╰─▶ } + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: Bar + ╭─[no_multi_comp.tsx:5:11] + 4 │ } + 5 │ ╭─▶ class Bar extends PureComponent { + 6 │ │ render() { return ; } + 7 │ ╰─▶ } + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: UnnamedComponent + ╭─[no_multi_comp.tsx:3:11] + 2 │ const Foo = () =>
; + 3 │ export default memo(() => ); + · ─────────────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: Bar + ╭─[no_multi_comp.tsx:4:24] + 3 │ } + 4 │ export const Bar = () => { return null; } + · ──────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: Bar + ╭─[no_multi_comp.tsx:2:24] + 1 │ export const Foo = () => { return null; } + 2 │ export const Bar = () => { return null; } + · ──────────────────────────── + ╰──── + help: Move this component to a separate file. + + ⚠ eslint-plugin-react(no-multi-comp): Declare only one React component per file. Found: Bar + ╭─[no_multi_comp.tsx:2:24] + 1 │ export const Foo = () => null; + 2 │ export const Bar = () => null; + · ──────────────── + ╰──── + help: Move this component to a separate file.