]>
Commit | Line | Data |
---|---|---|
eb39fafa DC |
1 | /** |
2 | * @fileoverview Tests for no-this-before-super rule. | |
3 | * @author Toru Nagashima | |
4 | */ | |
5 | ||
6 | "use strict"; | |
7 | ||
8 | //------------------------------------------------------------------------------ | |
9 | // Requirements | |
10 | //------------------------------------------------------------------------------ | |
11 | ||
12 | const rule = require("../../../lib/rules/no-this-before-super"); | |
13 | const { RuleTester } = require("../../../lib/rule-tester"); | |
14 | ||
15 | //------------------------------------------------------------------------------ | |
16 | // Tests | |
17 | //------------------------------------------------------------------------------ | |
18 | ||
19 | const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } }); | |
20 | ||
21 | ruleTester.run("no-this-before-super", rule, { | |
22 | valid: [ | |
23 | ||
24 | /* | |
25 | * if the class has no extends or `extends null`, just ignore. | |
26 | * those classes cannot call `super()`. | |
27 | */ | |
28 | "class A { }", | |
29 | "class A { constructor() { } }", | |
30 | "class A { constructor() { this.b = 0; } }", | |
31 | "class A { constructor() { this.b(); } }", | |
32 | "class A extends null { }", | |
33 | "class A extends null { constructor() { } }", | |
34 | ||
35 | // allows `this`/`super` after `super()`. | |
36 | "class A extends B { }", | |
37 | "class A extends B { constructor() { super(); } }", | |
38 | "class A extends B { constructor() { super(); this.c = this.d; } }", | |
39 | "class A extends B { constructor() { super(); this.c(); } }", | |
40 | "class A extends B { constructor() { super(); super.c(); } }", | |
41 | "class A extends B { constructor() { if (true) { super(); } else { super(); } this.c(); } }", | |
6f036462 TL |
42 | "class A extends B { constructor() { foo = super(); this.c(); } }", |
43 | "class A extends B { constructor() { foo += super().a; this.c(); } }", | |
44 | "class A extends B { constructor() { foo |= super().a; this.c(); } }", | |
45 | "class A extends B { constructor() { foo &= super().a; this.c(); } }", | |
eb39fafa DC |
46 | |
47 | // allows `this`/`super` in nested executable scopes, even if before `super()`. | |
48 | "class A extends B { constructor() { class B extends C { constructor() { super(); this.d = 0; } } super(); } }", | |
49 | "class A extends B { constructor() { var B = class extends C { constructor() { super(); this.d = 0; } }; super(); } }", | |
50 | "class A extends B { constructor() { function c() { this.d(); } super(); } }", | |
51 | "class A extends B { constructor() { var c = function c() { this.d(); }; super(); } }", | |
52 | "class A extends B { constructor() { var c = () => this.d(); super(); } }", | |
53 | ||
54 | // ignores out of constructors. | |
55 | "class A { b() { this.c = 0; } }", | |
56 | "class A extends B { c() { this.d = 0; } }", | |
57 | "function a() { this.b = 0; }", | |
58 | ||
59 | // multi code path. | |
60 | "class A extends B { constructor() { if (a) { super(); this.a(); } else { super(); this.b(); } } }", | |
61 | "class A extends B { constructor() { if (a) super(); else super(); this.a(); } }", | |
62 | "class A extends B { constructor() { try { super(); } finally {} this.a(); } }", | |
63 | ||
64 | // https://github.com/eslint/eslint/issues/5261 | |
65 | "class A extends B { constructor(a) { super(); for (const b of a) { this.a(); } } }", | |
66 | "class A extends B { constructor(a) { for (const b of a) { foo(b); } super(); } }", | |
67 | ||
68 | // https://github.com/eslint/eslint/issues/5319 | |
69 | "class A extends B { constructor(a) { super(); this.a = a && function(){} && this.foo; } }", | |
70 | ||
71 | // https://github.com/eslint/eslint/issues/5394 | |
72 | [ | |
73 | "class A extends Object {", | |
74 | " constructor() {", | |
75 | " super();", | |
76 | " for (let i = 0; i < 0; i++);", | |
77 | " this;", | |
78 | " }", | |
79 | "}" | |
80 | ].join("\n"), | |
81 | ||
82 | // https://github.com/eslint/eslint/issues/5894 | |
83 | "class A { constructor() { return; this; } }", | |
84 | "class A extends B { constructor() { return; this; } }", | |
85 | ||
86 | // https://github.com/eslint/eslint/issues/8848 | |
87 | ` | |
88 | class A extends B { | |
89 | constructor(props) { | |
90 | super(props); | |
91 | ||
92 | try { | |
93 | let arr = []; | |
94 | for (let a of arr) { | |
95 | } | |
96 | } catch (err) { | |
97 | } | |
98 | } | |
99 | } | |
100 | ` | |
101 | ], | |
102 | invalid: [ | |
103 | ||
104 | // disallows all `this`/`super` if `super()` is missing. | |
105 | { | |
106 | code: "class A extends B { constructor() { this.c = 0; } }", | |
107 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
108 | }, | |
109 | { | |
110 | code: "class A extends B { constructor() { this.c(); } }", | |
111 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
112 | }, | |
113 | { | |
114 | code: "class A extends B { constructor() { super.c(); } }", | |
115 | errors: [{ messageId: "noBeforeSuper", data: { kind: "super" }, type: "Super" }] | |
116 | }, | |
117 | ||
118 | // disallows `this`/`super` before `super()`. | |
119 | { | |
120 | code: "class A extends B { constructor() { this.c = 0; super(); } }", | |
121 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
122 | }, | |
123 | { | |
124 | code: "class A extends B { constructor() { this.c(); super(); } }", | |
125 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
126 | }, | |
127 | { | |
128 | code: "class A extends B { constructor() { super.c(); super(); } }", | |
129 | errors: [{ messageId: "noBeforeSuper", data: { kind: "super" }, type: "Super" }] | |
130 | }, | |
131 | ||
132 | // disallows `this`/`super` in arguments of `super()`. | |
133 | { | |
134 | code: "class A extends B { constructor() { super(this.c); } }", | |
135 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
136 | }, | |
137 | { | |
138 | code: "class A extends B { constructor() { super(this.c()); } }", | |
139 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
140 | }, | |
141 | { | |
142 | code: "class A extends B { constructor() { super(super.c()); } }", | |
143 | errors: [{ messageId: "noBeforeSuper", data: { kind: "super" }, type: "Super" }] | |
144 | }, | |
145 | ||
146 | // even if is nested, reports correctly. | |
147 | { | |
148 | code: "class A extends B { constructor() { class C extends D { constructor() { super(); this.e(); } } this.f(); super(); } }", | |
149 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression", column: 96 }] | |
150 | }, | |
151 | { | |
152 | code: "class A extends B { constructor() { class C extends D { constructor() { this.e(); super(); } } super(); this.f(); } }", | |
153 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression", column: 73 }] | |
154 | }, | |
155 | ||
156 | // multi code path. | |
157 | { | |
158 | code: "class A extends B { constructor() { if (a) super(); this.a(); } }", | |
159 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
160 | }, | |
161 | { | |
162 | code: "class A extends B { constructor() { try { super(); } finally { this.a; } } }", | |
163 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
164 | }, | |
165 | { | |
166 | code: "class A extends B { constructor() { try { super(); } catch (err) { } this.a; } }", | |
167 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
6f036462 TL |
168 | }, |
169 | { | |
170 | code: "class A extends B { constructor() { foo &&= super().a; this.c(); } }", | |
171 | parserOptions: { ecmaVersion: 2021 }, | |
172 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
173 | }, | |
174 | { | |
175 | code: "class A extends B { constructor() { foo ||= super().a; this.c(); } }", | |
176 | parserOptions: { ecmaVersion: 2021 }, | |
177 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
178 | }, | |
179 | { | |
180 | code: "class A extends B { constructor() { foo ??= super().a; this.c(); } }", | |
181 | parserOptions: { ecmaVersion: 2021 }, | |
182 | errors: [{ messageId: "noBeforeSuper", data: { kind: "this" }, type: "ThisExpression" }] | |
eb39fafa DC |
183 | } |
184 | ] | |
185 | }); |