From 7d7a3fcef8eadb6e0d7ae42a0e87d84eea31bf97 Mon Sep 17 00:00:00 2001 From: Yunfei He Date: Sat, 10 Feb 2024 22:46:02 +0800 Subject: [PATCH] perf(lint/no_var_requires): quicker way to check if the `IdentifierReference` point to a global variable (#2376) The old code use this function to do the checking, which is too much for this simple checking https://github.com/oxc-project/oxc/blob/ef336cb66b4746073e9d6a2f950d46185fec3cf6/crates/oxc_linter/src/ast_util.rs#L267-L276 --- crates/oxc_linter/src/ast_util.rs | 23 +++++++++++++++++++ .../src/rules/typescript/no_var_requires.rs | 11 +++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/crates/oxc_linter/src/ast_util.rs b/crates/oxc_linter/src/ast_util.rs index 98066f94c..c393368d5 100644 --- a/crates/oxc_linter/src/ast_util.rs +++ b/crates/oxc_linter/src/ast_util.rs @@ -381,3 +381,26 @@ pub fn get_new_expr_ident_name<'a>(new_expr: &'a NewExpression<'a>) -> Option<&' Some(ident.name.as_str()) } + +/// Check if the given [IdentifierReference] is a global reference. +/// Such as `window`, `document`, `globalThis`, etc. +pub fn is_global_reference(ident: &IdentifierReference, ctx: &LintContext) -> bool { + let symbol_table = ctx.semantic().symbols(); + let Some(reference_id) = ident.reference_id.get() else { + return false; + }; + let reference = symbol_table.get_reference(reference_id); + reference.symbol_id().is_none() +} + +pub fn is_global_require_call(call_expr: &CallExpression, ctx: &LintContext) -> bool { + if call_expr.arguments.len() != 1 { + return false; + } + + if let Expression::Identifier(id_ref) = &call_expr.callee { + id_ref.name == "require" && is_global_reference(id_ref, ctx) + } else { + false + } +} diff --git a/crates/oxc_linter/src/rules/typescript/no_var_requires.rs b/crates/oxc_linter/src/rules/typescript/no_var_requires.rs index 941ba00e6..08fe15620 100644 --- a/crates/oxc_linter/src/rules/typescript/no_var_requires.rs +++ b/crates/oxc_linter/src/rules/typescript/no_var_requires.rs @@ -1,4 +1,4 @@ -use oxc_ast::{ast::Expression, AstKind}; +use oxc_ast::AstKind; use oxc_diagnostics::{ miette::{self, Diagnostic}, thiserror::Error, @@ -6,7 +6,7 @@ use oxc_diagnostics::{ use oxc_macros::declare_oxc_lint; use oxc_span::{GetSpan, Span}; -use crate::{ast_util::get_declaration_of_variable, context::LintContext, rule::Rule, AstNode}; +use crate::{ast_util::is_global_require_call, context::LintContext, rule::Rule, AstNode}; #[derive(Debug, Error, Diagnostic)] #[error("typescript-eslint(no-var-requires): Require statement not part of import statement.")] @@ -41,7 +41,7 @@ impl Rule for NoVarRequires { } let AstKind::CallExpression(expr) = node.kind() else { return }; - if expr.is_require_call() && no_local_require_declaration(&expr.callee, ctx) { + if is_global_require_call(expr, ctx) { // If the parent is an expression statement => this is a top level require() // Or, if the parent is a chain expression (require?.()) and // the grandparent is an expression statement => this is a top level require() @@ -70,11 +70,6 @@ impl Rule for NoVarRequires { } } -fn no_local_require_declaration(expr: &Expression, ctx: &LintContext) -> bool { - let Expression::Identifier(ident) = expr else { return true }; - get_declaration_of_variable(ident, ctx).is_none() -} - #[test] fn test() { use crate::tester::Tester;