perf(linter/typescript/no-this-alias): narrow AST dispatch (#28360)

Start from direct this expressions while preserving destructuring
options, allowed names, and wrapper behavior. Reduce fixture callbacks
from 13,590 to 4,350.


---

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Cam McHenryandCopilot authored and GitHub committed 2026-10-28 22:28:48 -04:00
1 parent b102a91b15
commit 1a1f66eeb9
4 files changed
+23 -14

No files matched your search

+2 -4
View File
@@ -1881,10 +1881,8 @@ impl RuleRunner for crate::rules::typescript::no_restricted_types::NoRestrictedT
}
impl RuleRunner for crate::rules::typescript::no_this_alias::NoThisAlias {
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
AstType::AssignmentExpression,
AstType::VariableDeclarator,
]));
const NODE_TYPES: Option<&AstTypesBitset> =
Some(&AstTypesBitset::from_types(&[AstType::ThisExpression]));
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
}
@@ -1,6 +1,6 @@
use oxc_ast::{
AstKind,
ast::{AssignmentTarget, BindingPattern, Expression, match_simple_assignment_target},
ast::{AssignmentTarget, BindingPattern, match_simple_assignment_target},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
@@ -108,11 +108,12 @@ impl Rule for NoThisAlias {
}
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
match node.kind() {
let AstKind::ThisExpression(this) = node.kind() else { return };
match ctx.nodes().parent_kind(node.id()) {
AstKind::VariableDeclarator(decl) => {
let Some(init) = &decl.init else { return };
if !rhs_is_this_reference(init) {
if init.span() != this.span {
return;
}
@@ -132,7 +133,7 @@ impl Rule for NoThisAlias {
ctx.diagnostic(no_this_destructure_diagnostic(decl.id.span()));
}
AstKind::AssignmentExpression(assignment) => {
if !rhs_is_this_reference(&assignment.right) {
if assignment.right.span() != this.span {
return;
}
match &assignment.left {
@@ -171,16 +172,18 @@ impl Rule for NoThisAlias {
}
}
#[inline]
fn rhs_is_this_reference(rhs_expression: &Expression) -> bool {
matches!(rhs_expression, Expression::ThisExpression(_))
}
#[test]
fn test() {
use crate::tester::Tester;
let pass = vec![
("const self = (this);", None),
("const self = this as Foo;", None),
("this.value = other;", None),
("this.self = this;", None),
("const self = [this];", None),
("function f(value = this) {}", None),
("({value} = this);", None),
// allow destructuring
(
"const { props, state } = this;",
@@ -201,6 +204,7 @@ fn test() {
let fail = vec![
("const self = this;", None),
("let self; self ||= this;", None),
(
"const { props, state } = this;",
Some(serde_json::json!([{ "allowDestructuring": false }])),
@@ -9,6 +9,13 @@ source: crates/oxc_linter/src/tester.rs
╰────
help: Assigning a variable to this instead of properly using arrow lambdas may be a symptom of pre-ES2015 practices or not managing scope well.
⚠ typescript(no-this-alias): Unexpected aliasing of 'this' to local variable.
╭─[no_this_alias.tsx:1:11]
1 │ let self; self ||= this;
· ────
╰────
help: Assigning a variable to this instead of properly using arrow lambdas may be a symptom of pre-ES2015 practices or not managing scope well.
⚠ typescript(no-this-alias): Unexpected aliasing of members of 'this' to local variables.
╭─[no_this_alias.tsx:1:7]
1 │ const { props, state } = this;
@@ -493,7 +493,7 @@ typescript/no-non-null-asserted-nullish-coalescing | 7341
typescript/no-non-null-asserted-optional-chain | 577
typescript/no-non-null-assertion | 577
typescript/no-require-imports | 62608
typescript/no-this-alias | 13590
typescript/no-this-alias | 4350
typescript/no-unnecessary-parameter-property-assignment | 1916
typescript/no-unnecessary-type-constraint | 362
typescript/no-unsafe-declaration-merging | 500