From 6c3d99a9519879bc0aa73d11feedc8defff8e82c Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Fri, 17 May 2024 14:20:08 +0000 Subject: [PATCH] fix(linter/jsx-no-undef): check for globals when an identifier is undefined (#3331) closes #3319 --- .../src/rules/react/jsx_no_undef.rs | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/crates/oxc_linter/src/rules/react/jsx_no_undef.rs b/crates/oxc_linter/src/rules/react/jsx_no_undef.rs index 57314e880..af2cb3844 100644 --- a/crates/oxc_linter/src/rules/react/jsx_no_undef.rs +++ b/crates/oxc_linter/src/rules/react/jsx_no_undef.rs @@ -1,8 +1,5 @@ use oxc_ast::{ - ast::{ - JSXElementName, JSXIdentifier, JSXMemberExpression, JSXMemberExpressionObject, - JSXOpeningElement, - }, + ast::{JSXElementName, JSXIdentifier, JSXMemberExpression, JSXMemberExpressionObject}, AstKind, }; use oxc_diagnostics::OxcDiagnostic; @@ -39,12 +36,6 @@ declare_oxc_lint!( correctness ); -fn get_member_ident<'a>(expr: &'a JSXMemberExpression<'a>) -> &'a JSXIdentifier { - match expr.object { - JSXMemberExpressionObject::Identifier(ref ident) => ident, - JSXMemberExpressionObject::MemberExpression(ref next_expr) => get_member_ident(next_expr), - } -} fn get_resolvable_ident<'a>(node: &'a JSXElementName<'a>) -> Option<&'a JSXIdentifier> { match node { JSXElementName::Identifier(ref ident) @@ -57,19 +48,29 @@ fn get_resolvable_ident<'a>(node: &'a JSXElementName<'a>) -> Option<&'a JSXIdent } } +fn get_member_ident<'a>(expr: &'a JSXMemberExpression<'a>) -> &'a JSXIdentifier { + match &expr.object { + JSXMemberExpressionObject::Identifier(ident) => ident, + JSXMemberExpressionObject::MemberExpression(next_expr) => get_member_ident(next_expr), + } +} + impl Rule for JsxNoUndef { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { - if let AstKind::JSXOpeningElement(JSXOpeningElement { name: el_name, .. }) = &node.kind() { - if let Some(ident) = get_resolvable_ident(el_name) { - if ident.name.as_str() == "this" { + if let AstKind::JSXOpeningElement(elem) = &node.kind() { + if let Some(ident) = get_resolvable_ident(&elem.name) { + let name = ident.name.as_str(); + if name == "this" { return; } - let jsx_scope_id = node.scope_id(); - for scope_id in ctx.scopes().ancestors(jsx_scope_id) { - if ctx.scopes().has_binding(scope_id, &ident.name) { + for scope_id in ctx.scopes().ancestors(node.scope_id()) { + if ctx.scopes().has_binding(scope_id, name) { return; } } + if ctx.globals().is_enabled(name) { + return; + } ctx.diagnostic(jsx_no_undef_diagnostic(ident.name.as_str(), ident.span)); } } @@ -78,6 +79,8 @@ impl Rule for JsxNoUndef { #[test] fn test() { + use serde_json::json; + use crate::tester::Tester; let pass = vec![ @@ -126,4 +129,8 @@ fn test() { ]; Tester::new(JsxNoUndef::NAME, pass, fail).test_and_snapshot(); + + let pass = vec![("let x = ;", None, Some(json!({ "globals": {"A": "readonly" } })))]; + let fail = vec![("let x = ;", None, None)]; + Tester::new(JsxNoUndef::NAME, pass, fail).test(); }