Skip to content

Commit dd49280

Browse files
authored
fix(scope-manager): incorrect reference for this within a jsx identifier (typescript-eslint#4535)
1 parent f3a97ff commit dd49280

File tree

3 files changed

+168
-3
lines changed

3 files changed

+168
-3
lines changed

packages/scope-manager/src/referencer/Referencer.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -509,17 +509,27 @@ class Referencer extends Visitor {
509509
}
510510

511511
protected JSXMemberExpression(node: TSESTree.JSXMemberExpression): void {
512-
this.visit(node.object);
512+
if (node.object.type !== AST_NODE_TYPES.JSXIdentifier) {
513+
this.visit(node.object);
514+
} else {
515+
if (node.object.name !== 'this') {
516+
this.visit(node.object);
517+
}
518+
}
513519
// we don't ever reference the property as it's always going to be a property on the thing
514520
}
515-
516521
protected JSXOpeningElement(node: TSESTree.JSXOpeningElement): void {
517522
this.referenceJsxPragma();
518523
if (node.name.type === AST_NODE_TYPES.JSXIdentifier) {
519-
if (node.name.name[0].toUpperCase() === node.name.name[0]) {
524+
if (
525+
node.name.name[0].toUpperCase() === node.name.name[0] ||
526+
node.name.name === 'this'
527+
) {
520528
// lower cased component names are always treated as "intrinsic" names, and are converted to a string,
521529
// not a variable by JSX transforms:
522530
// <div /> => React.createElement("div", null)
531+
532+
// the only case we want to visit a lower-cased component has its name as "this",
523533
this.visit(node.name);
524534
}
525535
} else {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
declare const React;
2+
3+
class Foo {
4+
foo: any;
5+
Div = {
6+
Element: () => <div />,
7+
};
8+
method() {
9+
<this.foo />;
10+
(<Div.Element />)(<this />);
11+
}
12+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`jsx this-jsxidentifier 1`] = `
4+
ScopeManager {
5+
variables: Array [
6+
ImplicitGlobalConstTypeVariable,
7+
Variable$2 {
8+
defs: Array [
9+
VariableDefinition$1 {
10+
name: Identifier<"React">,
11+
node: VariableDeclarator$1,
12+
},
13+
],
14+
name: "React",
15+
references: Array [
16+
Reference$1 {
17+
identifier: Identifier<"React">,
18+
isRead: true,
19+
isTypeReference: false,
20+
isValueReference: true,
21+
isWrite: false,
22+
resolved: Variable$2,
23+
},
24+
],
25+
isValueVariable: true,
26+
isTypeVariable: false,
27+
},
28+
Variable$3 {
29+
defs: Array [
30+
ClassNameDefinition$2 {
31+
name: Identifier<"Foo">,
32+
node: ClassDeclaration$2,
33+
},
34+
],
35+
name: "Foo",
36+
references: Array [],
37+
isValueVariable: true,
38+
isTypeVariable: true,
39+
},
40+
Variable$4 {
41+
defs: Array [
42+
ClassNameDefinition$3 {
43+
name: Identifier<"Foo">,
44+
node: ClassDeclaration$2,
45+
},
46+
],
47+
name: "Foo",
48+
references: Array [],
49+
isValueVariable: true,
50+
isTypeVariable: true,
51+
},
52+
Variable$5 {
53+
defs: Array [],
54+
name: "arguments",
55+
references: Array [],
56+
isValueVariable: true,
57+
isTypeVariable: true,
58+
},
59+
],
60+
scopes: Array [
61+
GlobalScope$1 {
62+
block: Program$3,
63+
isStrict: false,
64+
references: Array [
65+
Reference$1,
66+
],
67+
set: Map {
68+
"const" => ImplicitGlobalConstTypeVariable,
69+
"React" => Variable$2,
70+
"Foo" => Variable$3,
71+
},
72+
type: "global",
73+
upper: null,
74+
variables: Array [
75+
ImplicitGlobalConstTypeVariable,
76+
Variable$2,
77+
Variable$3,
78+
],
79+
},
80+
ClassScope$2 {
81+
block: ClassDeclaration$2,
82+
isStrict: true,
83+
references: Array [],
84+
set: Map {
85+
"Foo" => Variable$4,
86+
},
87+
type: "class",
88+
upper: GlobalScope$1,
89+
variables: Array [
90+
Variable$4,
91+
],
92+
},
93+
ClassFieldInitializerScope$3 {
94+
block: ObjectExpression$4,
95+
isStrict: true,
96+
references: Array [],
97+
set: Map {},
98+
type: "class-field-initializer",
99+
upper: ClassScope$2,
100+
variables: Array [],
101+
},
102+
FunctionScope$4 {
103+
block: ArrowFunctionExpression$5,
104+
isStrict: true,
105+
references: Array [],
106+
set: Map {},
107+
type: "function",
108+
upper: ClassFieldInitializerScope$3,
109+
variables: Array [],
110+
},
111+
FunctionScope$5 {
112+
block: FunctionExpression$6,
113+
isStrict: true,
114+
references: Array [
115+
Reference$2 {
116+
identifier: JSXIdentifier$7,
117+
isRead: true,
118+
isTypeReference: false,
119+
isValueReference: true,
120+
isWrite: false,
121+
resolved: null,
122+
},
123+
Reference$3 {
124+
identifier: JSXIdentifier$8,
125+
isRead: true,
126+
isTypeReference: false,
127+
isValueReference: true,
128+
isWrite: false,
129+
resolved: null,
130+
},
131+
],
132+
set: Map {
133+
"arguments" => Variable$5,
134+
},
135+
type: "function",
136+
upper: ClassScope$2,
137+
variables: Array [
138+
Variable$5,
139+
],
140+
},
141+
],
142+
}
143+
`;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy