From 5b1ba6632fcfd01d120cbcc282168a3a535ca00d Mon Sep 17 00:00:00 2001 From: Zzzen Date: Mon, 3 Jan 2022 23:53:08 +0800 Subject: [PATCH] fix: add `this` to implicit global variables --- .../tests/eslint-rules/no-undef.test.ts | 12 +++++++++- .../src/referencer/Referencer.ts | 7 ++++++ .../src/referencer/TypeVisitor.ts | 11 +-------- packages/typescript-estree/src/convert.ts | 9 ------- packages/typescript-estree/src/node-utils.ts | 24 ------------------- 5 files changed, 19 insertions(+), 44 deletions(-) diff --git a/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts b/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts index 53dd3be8d0d6..392725d653f2 100644 --- a/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts +++ b/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts @@ -249,13 +249,23 @@ class Foo {} export type AppState = typeof import('./src/store/reducers').default; `, ` +let self: typeof this; +let foo: typeof this.foo; const obj = { foo: '', bar() { let self: typeof this; - let foo: typeof this.foo; }, }; + +class C { + foo() { + let self: typeof this; + } + bar = () => { + let self: typeof this; + } +} `, ], invalid: [ diff --git a/packages/scope-manager/src/referencer/Referencer.ts b/packages/scope-manager/src/referencer/Referencer.ts index 10273bfb6b35..14f16aa7f268 100644 --- a/packages/scope-manager/src/referencer/Referencer.ts +++ b/packages/scope-manager/src/referencer/Referencer.ts @@ -98,6 +98,13 @@ class Referencer extends Visitor { isTypeVariable: true, isValueVariable: false, }); + + // prevent `no-undef` from reporting `typeof this` + globalScope.defineImplicitVariable('this', { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: false, + isValueVariable: true, + }); } /** diff --git a/packages/scope-manager/src/referencer/TypeVisitor.ts b/packages/scope-manager/src/referencer/TypeVisitor.ts index bbfbab230202..e9abb40f4f42 100644 --- a/packages/scope-manager/src/referencer/TypeVisitor.ts +++ b/packages/scope-manager/src/referencer/TypeVisitor.ts @@ -258,20 +258,11 @@ class TypeVisitor extends Visitor { protected TSTypeQuery(node: TSESTree.TSTypeQuery): void { if (node.exprName.type === AST_NODE_TYPES.Identifier) { this.#referencer.currentScope().referenceValue(node.exprName); - } else if ( - (node.exprName.type as unknown) === AST_NODE_TYPES.ThisExpression - ) { - // technically exprName is either Identifier or QualifiedName, but eslint does not recognize `typeof this`, - // so we have translated it to ThisExpression. - return; } else { let expr = node.exprName.left; - while (expr.type === TSESTree.AST_NODE_TYPES.TSQualifiedName) { + while (expr.type !== AST_NODE_TYPES.Identifier) { expr = expr.left; } - if ((expr.type as unknown) === AST_NODE_TYPES.ThisExpression) { - return; - } this.#referencer.currentScope().referenceValue(expr); } } diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index 99453a9f4093..f0fb7d3cf58b 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -20,7 +20,6 @@ import { isComputedProperty, isESTreeClassMember, isOptional, - isThisInTypeQuery, TSError, unescapeStringLiteralText, } from './node-utils'; @@ -788,14 +787,6 @@ export class Converter { } case SyntaxKind.Identifier: { - if (isThisInTypeQuery(node)) { - return this.createNode( - node as unknown as ts.ThisExpression, - { - type: AST_NODE_TYPES.ThisExpression, - }, - ); - } return this.createNode(node, { type: AST_NODE_TYPES.Identifier, name: node.text, diff --git a/packages/typescript-estree/src/node-utils.ts b/packages/typescript-estree/src/node-utils.ts index 8bca0930cb7e..d8182aa5655e 100644 --- a/packages/typescript-estree/src/node-utils.ts +++ b/packages/typescript-estree/src/node-utils.ts @@ -663,27 +663,3 @@ export function firstDefined( } return undefined; } - -export function identifierIsThisKeyword(id: ts.Identifier): boolean { - return id.originalKeywordKind === SyntaxKind.ThisKeyword; -} - -export function isThisIdentifier(node: ts.Node | undefined): boolean { - return ( - !!node && - node.kind === SyntaxKind.Identifier && - identifierIsThisKeyword(node as ts.Identifier) - ); -} - -export function isThisInTypeQuery(node: ts.Node): boolean { - if (!isThisIdentifier(node)) { - return false; - } - - while (ts.isQualifiedName(node.parent) && node.parent.left === node) { - node = node.parent; - } - - return node.parent.kind === SyntaxKind.TypeQuery; -}