From 37de80d9c906fbd8a2ac7ce4ee0fdb028a09e274 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Fri, 1 Mar 2024 21:07:57 +0800 Subject: [PATCH] fix(semantic): jsx reference with an incorrect node id (#2546) The get kind from the node id should be `JSXIdentifier`, but now it's `JSXOpeningElement`. --- .../oxc_linter/src/rules/import/namespace.rs | 8 ++-- .../src/rules/nextjs/inline_script_id.rs | 2 +- .../nextjs/no_script_component_in_head.rs | 2 +- .../rules/nextjs/no_title_in_document_head.rs | 2 +- crates/oxc_semantic/src/builder.rs | 40 ++++++++----------- 5 files changed, 25 insertions(+), 29 deletions(-) diff --git a/crates/oxc_linter/src/rules/import/namespace.rs b/crates/oxc_linter/src/rules/import/namespace.rs index 65d78511afcc2..42e87eecaa520 100644 --- a/crates/oxc_linter/src/rules/import/namespace.rs +++ b/crates/oxc_linter/src/rules/import/namespace.rs @@ -1,4 +1,4 @@ -use oxc_ast::{ast::JSXElementName, AstKind}; +use oxc_ast::AstKind; use oxc_diagnostics::{ miette::{self, Diagnostic}, thiserror::Error, @@ -95,8 +95,10 @@ impl Rule for Namespace { } } - AstKind::JSXOpeningElement(element) => { - if let JSXElementName::MemberExpression(expr) = &element.name { + AstKind::JSXMemberExpressionObject(_) => { + if let Some(AstKind::JSXMemberExpression(expr)) = + ctx.nodes().parent_kind(node.id()) + { check_binding_exported(&expr.property.name, expr.property.span); } } diff --git a/crates/oxc_linter/src/rules/nextjs/inline_script_id.rs b/crates/oxc_linter/src/rules/nextjs/inline_script_id.rs index 1cfa8286f3991..b6de30d3394e5 100644 --- a/crates/oxc_linter/src/rules/nextjs/inline_script_id.rs +++ b/crates/oxc_linter/src/rules/nextjs/inline_script_id.rs @@ -51,7 +51,7 @@ impl Rule for InlineScriptId { 'references_loop: for reference in ctx.semantic().symbol_references(specifier.local.symbol_id.get().unwrap()) { - let node = ctx.nodes().get_node(reference.node_id()); + let Some(node) = ctx.nodes().parent_node(reference.node_id()) else { return }; let AstKind::JSXElementName(_) = node.kind() else { continue }; let parent_node = ctx.nodes().parent_node(node.id()).unwrap(); diff --git a/crates/oxc_linter/src/rules/nextjs/no_script_component_in_head.rs b/crates/oxc_linter/src/rules/nextjs/no_script_component_in_head.rs index c9d350b775d76..bf93d9944719e 100644 --- a/crates/oxc_linter/src/rules/nextjs/no_script_component_in_head.rs +++ b/crates/oxc_linter/src/rules/nextjs/no_script_component_in_head.rs @@ -65,7 +65,7 @@ impl Rule for NoScriptComponentInHead { for reference in ctx.semantic().symbol_references(default_import.local.symbol_id.get().unwrap()) { - let node = ctx.nodes().get_node(reference.node_id()); + let Some(node) = ctx.nodes().parent_node(reference.node_id()) else { return }; let AstKind::JSXElementName(_) = node.kind() else { continue }; let parent_node = ctx.nodes().parent_node(node.id()).unwrap(); diff --git a/crates/oxc_linter/src/rules/nextjs/no_title_in_document_head.rs b/crates/oxc_linter/src/rules/nextjs/no_title_in_document_head.rs index ee8dce6fa93a2..11c83760c39bf 100644 --- a/crates/oxc_linter/src/rules/nextjs/no_title_in_document_head.rs +++ b/crates/oxc_linter/src/rules/nextjs/no_title_in_document_head.rs @@ -65,7 +65,7 @@ impl Rule for NoTitleInDocumentHead { for reference in ctx.semantic().symbol_references(default_import.local.symbol_id.get().unwrap()) { - let node = ctx.nodes().get_node(reference.node_id()); + let Some(node) = ctx.nodes().parent_node(reference.node_id()) else { return }; let AstKind::JSXElementName(_) = node.kind() else { continue }; let parent_node = ctx.nodes().parent_node(node.id()).unwrap(); diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index d6294397b8b68..2863b6b457070 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -1748,6 +1748,9 @@ impl<'a> SemanticBuilder<'a> { AstKind::IdentifierReference(ident) => { self.reference_identifier(ident); } + AstKind::JSXIdentifier(ident) => { + self.reference_jsx_identifier(ident); + } AstKind::UpdateExpression(_) => { if self.is_not_expression_statement_parent() { self.current_reference_flag |= ReferenceFlag::Read; @@ -1767,9 +1770,6 @@ impl<'a> SemanticBuilder<'a> { AstKind::AssignmentTarget(_) => { self.current_reference_flag |= ReferenceFlag::Write; } - AstKind::JSXElementName(elem) => { - self.reference_jsx_element_name(elem); - } AstKind::LabeledStatement(stmt) => { self.label_builder.enter(stmt, self.current_node_id); } @@ -1872,29 +1872,23 @@ impl<'a> SemanticBuilder<'a> { } } - fn reference_jsx_element_name(&mut self, elem: &JSXElementName) { - if matches!( - self.nodes.parent_kind(self.current_node_id), - Some(AstKind::JSXOpeningElement(_)) - ) { - if let Some(ident) = match elem { - JSXElementName::Identifier(ident) - if ident.name.chars().next().is_some_and(char::is_uppercase) => - { - Some(ident) + fn reference_jsx_identifier(&mut self, ident: &JSXIdentifier) { + match self.nodes.parent_kind(self.current_node_id) { + Some(AstKind::JSXElementName(_)) => { + if !ident.name.chars().next().is_some_and(char::is_uppercase) { + return; } - JSXElementName::MemberExpression(expr) => Some(expr.get_object_identifier()), - _ => None, - } { - let reference = Reference::new( - ident.span, - ident.name.to_compact_string(), - self.current_node_id, - ReferenceFlag::read(), - ); - self.declare_reference(reference); } + Some(AstKind::JSXMemberExpressionObject(_)) => {} + _ => return, } + let reference = Reference::new( + ident.span, + ident.name.to_compact_string(), + self.current_node_id, + ReferenceFlag::read(), + ); + self.declare_reference(reference); } fn is_not_expression_statement_parent(&self) -> bool {