diff --git a/crates/oxc_linter/src/ast_util.rs b/crates/oxc_linter/src/ast_util.rs index 97c0853e515e3..76828fb33d850 100644 --- a/crates/oxc_linter/src/ast_util.rs +++ b/crates/oxc_linter/src/ast_util.rs @@ -6,7 +6,6 @@ use oxc_ecmascript::ToBoolean; use oxc_semantic::{AstNode, IsGlobalReference, NodeId, ReferenceId, Semantic, SymbolId}; use oxc_span::{GetSpan, Span}; use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator}; -use std::borrow::Cow; /// Test if an AST node is a boolean value that never changes. Specifically we /// test for: @@ -470,44 +469,3 @@ pub fn leftmost_identifier_reference<'a, 'b: 'a>( _ => Err(expr), } } - -fn get_property_key_name<'a>(key: &PropertyKey<'a>) -> Option> { - if matches!(key, PropertyKey::NullLiteral(_)) { - return Some("null".into()); - } - - match key { - PropertyKey::RegExpLiteral(regex) => { - Some(Cow::Owned(format!("/{}/{}", regex.regex.pattern, regex.regex.flags))) - } - PropertyKey::BigIntLiteral(bigint) => Some(Cow::Borrowed(bigint.raw.as_str())), - PropertyKey::TemplateLiteral(template) => { - if template.expressions.len() == 0 && template.quasis.len() == 1 { - if let Some(cooked) = &template.quasis[0].value.cooked { - return Some(Cow::Borrowed(cooked.as_str())); - } - } - - None - } - _ => None, - } -} - -pub fn get_static_property_name<'a>(kind: &AstKind<'a>) -> Option> { - let (key, computed) = match kind { - AstKind::PropertyDefinition(definition) => (&definition.key, definition.computed), - AstKind::MethodDefinition(method_definition) => { - (&method_definition.key, method_definition.computed) - } - AstKind::ObjectProperty(property) => (&property.key, property.computed), - // AstKind::MemberExpression(member) => (member., member.is_computed()) - _ => return None, - }; - - if key.is_identifier() && !computed { - return key.name(); - } - - get_property_key_name(key) -} diff --git a/crates/oxc_linter/src/rules/eslint/func_names.rs b/crates/oxc_linter/src/rules/eslint/func_names.rs index fe3aa5cae1ee4..ad54b56c06e38 100644 --- a/crates/oxc_linter/src/rules/eslint/func_names.rs +++ b/crates/oxc_linter/src/rules/eslint/func_names.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use oxc_ast::{ ast::{ AssignmentTarget, AssignmentTargetProperty, BindingPatternKind, Expression, Function, - FunctionType, MethodDefinitionKind, PropertyKind, + FunctionType, MethodDefinitionKind, PropertyKey, PropertyKind, }, AstKind, }; @@ -14,7 +14,7 @@ use oxc_span::{Atom, GetSpan, Span}; use oxc_syntax::identifier::is_identifier_name; use phf::phf_set; -use crate::{ast_util::get_static_property_name, context::LintContext, rule::Rule, AstNode}; +use crate::{context::LintContext, rule::Rule, AstNode}; fn named_diagnostic(function_name: &str, span: Span) -> OxcDiagnostic { OxcDiagnostic::warn(format!("Unexpected named {function_name}.")) @@ -232,6 +232,46 @@ fn get_function_identifier<'a>(func: &'a Function<'a>) -> Option<&'a Span> { func.id.as_ref().map(|id| &id.span) } +fn get_property_key_name<'a>(key: &PropertyKey<'a>) -> Option> { + if matches!(key, PropertyKey::NullLiteral(_)) { + return Some("null".into()); + } + + match key { + PropertyKey::RegExpLiteral(regex) => { + Some(Cow::Owned(format!("/{}/{}", regex.regex.pattern, regex.regex.flags))) + } + PropertyKey::BigIntLiteral(bigint) => Some(Cow::Borrowed(bigint.raw.as_str())), + PropertyKey::TemplateLiteral(template) => { + if template.expressions.len() == 0 && template.quasis.len() == 1 { + if let Some(cooked) = &template.quasis[0].value.cooked { + return Some(Cow::Borrowed(cooked.as_str())); + } + } + + None + } + _ => None, + } +} + +fn get_static_property_name<'a>(parent_node: &AstNode<'a>) -> Option> { + let (key, computed) = match parent_node.kind() { + AstKind::PropertyDefinition(definition) => (&definition.key, definition.computed), + AstKind::MethodDefinition(method_definition) => { + (&method_definition.key, method_definition.computed) + } + AstKind::ObjectProperty(property) => (&property.key, property.computed), + _ => return None, + }; + + if key.is_identifier() && !computed { + return key.name(); + } + + get_property_key_name(key) +} + /// Gets the name and kind of the given function node. /// @see fn get_function_name_with_kind<'a>(func: &Function<'a>, parent_node: &AstNode<'a>) -> Cow<'a, str> { @@ -295,14 +335,14 @@ fn get_function_name_with_kind<'a>(func: &Function<'a>, parent_node: &AstNode<'a if let Some(name) = definition.key.name() { tokens.push(name); } - } else if let Some(static_name) = get_static_property_name(&parent_node.kind()) { + } else if let Some(static_name) = get_static_property_name(parent_node) { tokens.push(static_name); } else if let Some(name) = func.name() { tokens.push(Cow::Borrowed(name.as_str())); } } _ => { - if let Some(static_name) = get_static_property_name(&parent_node.kind()) { + if let Some(static_name) = get_static_property_name(parent_node) { tokens.push(static_name); } else if let Some(name) = func.name() { tokens.push(Cow::Borrowed(name.as_str())); diff --git a/crates/oxc_linter/src/rules/eslint/new_cap.rs b/crates/oxc_linter/src/rules/eslint/new_cap.rs index cdca0fc6434e3..9455a4c2e351a 100644 --- a/crates/oxc_linter/src/rules/eslint/new_cap.rs +++ b/crates/oxc_linter/src/rules/eslint/new_cap.rs @@ -1,4 +1,4 @@ -use crate::{ast_util::get_static_property_name, context::LintContext, rule::Rule, AstNode}; +use crate::{context::LintContext, rule::Rule, AstNode}; use oxc_ast::{ ast::{ChainElement, ComputedMemberExpression, Expression}, AstKind, @@ -448,13 +448,11 @@ impl Rule for NewCap { AstKind::NewExpression(expression) if self.new_is_cap => { let callee = expression.callee.without_parentheses(); - let Some(short_name) = &extract_name_from_new_expression(callee, &node.kind()) - else { + let Some(short_name) = &extract_name_from_expression(callee) else { return; }; - let Some(name) = &extract_name_deep_from_new_expression(callee, &node.kind()) - else { + let Some(name) = &extract_name_deep_from_expression(callee) else { return; }; @@ -477,13 +475,11 @@ impl Rule for NewCap { AstKind::CallExpression(expression) if self.cap_is_new => { let callee = expression.callee.without_parentheses(); - let Some(short_name) = &extract_name_from_new_expression(callee, &node.kind()) - else { + let Some(short_name) = &extract_name_from_expression(callee) else { return; }; - let Some(name) = &extract_name_deep_from_new_expression(callee, &node.kind()) - else { + let Some(name) = &extract_name_deep_from_expression(callee) else { return; }; @@ -511,10 +507,7 @@ impl Rule for NewCap { } } -fn extract_name_deep_from_new_expression( - expression: &Expression, - kind: &AstKind, -) -> Option { +fn extract_name_deep_from_expression(expression: &Expression) -> Option { if let Some(identifier) = expression.get_identifier_reference() { return Some(identifier.name.clone().into()); } @@ -522,10 +515,8 @@ fn extract_name_deep_from_new_expression( match expression.without_parentheses() { Expression::StaticMemberExpression(expression) => { let prop_name = expression.property.name.clone().into_compact_str(); - let obj_name = extract_name_deep_from_new_expression( - expression.object.without_parentheses(), - kind, - ); + let obj_name = + extract_name_deep_from_expression(expression.object.without_parentheses()); if let Some(obj_name) = obj_name { let new_name = format!("{obj_name}.{prop_name}"); @@ -536,10 +527,8 @@ fn extract_name_deep_from_new_expression( } Expression::ComputedMemberExpression(expression) => { let prop_name = get_computed_member_name(expression)?; - let obj_name = extract_name_deep_from_new_expression( - expression.object.without_parentheses(), - kind, - ); + let obj_name = + extract_name_deep_from_expression(expression.object.without_parentheses()); if let Some(obj_name) = obj_name { let new_name = format!("{obj_name}.{prop_name}"); @@ -549,18 +538,14 @@ fn extract_name_deep_from_new_expression( Some(prop_name) } Expression::ChainExpression(chain) => match &chain.expression { - ChainElement::CallExpression(call) => { - extract_name_deep_from_new_expression(&call.callee, kind) - } + ChainElement::CallExpression(call) => extract_name_deep_from_expression(&call.callee), ChainElement::TSNonNullExpression(non_null) => { - extract_name_deep_from_new_expression(&non_null.expression, kind) + extract_name_deep_from_expression(&non_null.expression) } ChainElement::StaticMemberExpression(expression) => { let prop_name = expression.property.name.clone().into_compact_str(); - let obj_name = extract_name_deep_from_new_expression( - expression.object.without_parentheses(), - kind, - ); + let obj_name = + extract_name_deep_from_expression(expression.object.without_parentheses()); if let Some(obj_name) = obj_name { let new_name = format!("{obj_name}.{prop_name}"); @@ -571,10 +556,8 @@ fn extract_name_deep_from_new_expression( } ChainElement::ComputedMemberExpression(expression) => { let prop_name = get_computed_member_name(expression)?; - let obj_name = extract_name_deep_from_new_expression( - expression.object.without_parentheses(), - kind, - ); + let obj_name = + extract_name_deep_from_expression(expression.object.without_parentheses()); if let Some(obj_name) = obj_name { let new_name = format!("{obj_name}.{prop_name}"); @@ -585,7 +568,7 @@ fn extract_name_deep_from_new_expression( } ChainElement::PrivateFieldExpression(_) => None, }, - _ => get_static_property_name(kind).map(std::convert::Into::into), + _ => None, } } @@ -602,7 +585,7 @@ fn get_computed_member_name(computed_member: &ComputedMemberExpression) -> Optio } } -fn extract_name_from_new_expression(expression: &Expression, kind: &AstKind) -> Option { +fn extract_name_from_expression(expression: &Expression) -> Option { if let Some(identifier) = expression.get_identifier_reference() { return Some(identifier.name.clone().into()); } @@ -613,11 +596,9 @@ fn extract_name_from_new_expression(expression: &Expression, kind: &AstKind) -> } Expression::ComputedMemberExpression(expression) => get_computed_member_name(expression), Expression::ChainExpression(chain) => match &chain.expression { - ChainElement::CallExpression(call) => { - extract_name_from_new_expression(&call.callee, kind) - } + ChainElement::CallExpression(call) => extract_name_from_expression(&call.callee), ChainElement::TSNonNullExpression(non_null) => { - extract_name_from_new_expression(&non_null.expression, kind) + extract_name_from_expression(&non_null.expression) } ChainElement::StaticMemberExpression(expression) => { Some(expression.property.name.clone().into_compact_str()) @@ -627,7 +608,7 @@ fn extract_name_from_new_expression(expression: &Expression, kind: &AstKind) -> } ChainElement::PrivateFieldExpression(_) => None, }, - _ => get_static_property_name(kind).map(std::convert::Into::into), + _ => None, } }