Skip to content

Commit 1c78d0c

Browse files
authored
prefer-switch: Avoid conflict with no-unreachable rule (sindresorhus#1234)
1 parent f4ba012 commit 1c78d0c

File tree

4 files changed

+680
-38
lines changed

4 files changed

+680
-38
lines changed

rules/prefer-switch.js

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,48 @@ function * insertBreakStatement(node, fixer, sourceCode, indent) {
139139
}
140140
}
141141

142+
function getBlockStatementLastNode(blockStatement) {
143+
const {body} = blockStatement;
144+
for (let index = body.length - 1; index >= 0; index--) {
145+
const node = body[index];
146+
if (node.type === 'FunctionDeclaration' || node.type === 'EmptyStatement') {
147+
continue;
148+
}
149+
150+
if (node.type === 'BlockStatement') {
151+
const last = getBlockStatementLastNode(node);
152+
if (last) {
153+
return last;
154+
}
155+
156+
continue;
157+
}
158+
159+
return node;
160+
}
161+
}
162+
163+
function shouldInsertBreakStatement(node) {
164+
switch (node.type) {
165+
case 'ReturnStatement':
166+
case 'ThrowStatement':
167+
return false;
168+
169+
case 'IfStatement':
170+
return !node.alternate ||
171+
shouldInsertBreakStatement(node.consequent) ||
172+
shouldInsertBreakStatement(node.alternate);
173+
174+
case 'BlockStatement': {
175+
const lastNode = getBlockStatementLastNode(node);
176+
return !lastNode || shouldInsertBreakStatement(lastNode);
177+
}
178+
179+
default:
180+
return true;
181+
}
182+
}
183+
142184
function fix({discriminant, ifStatements}, sourceCode, options) {
143185
const discriminantText = sourceCode.getText(discriminant);
144186

@@ -184,8 +226,10 @@ function fix({discriminant, ifStatements}, sourceCode, options) {
184226
yield fixer.insertTextBefore(consequent, `\n${indent}case ${text}: `);
185227
}
186228

187-
yield * insertBreakStatement(consequent, fixer, sourceCode, indent);
188-
yield * insertBracesIfNotBlockStatement(consequent, fixer, indent);
229+
if (shouldInsertBreakStatement(consequent)) {
230+
yield * insertBreakStatement(consequent, fixer, sourceCode, indent);
231+
yield * insertBracesIfNotBlockStatement(consequent, fixer, indent);
232+
}
189233
}
190234
};
191235
}

test/prefer-switch.mjs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,148 @@ test.snapshot({
242242
break;
243243
}
244244
}
245+
`,
246+
// Should not insert `break`, #1232
247+
outdent`
248+
function unicorn() {
249+
if (foo === 1) return 1;
250+
else if (foo === 2) throw new Error("");
251+
else if (foo === 3) process.exit(1);
252+
else if (foo === 4) {}
253+
else if (foo === 5) ;
254+
else if (foo === 6) {
255+
return 6;
256+
// Already unreachable
257+
call();
258+
}
259+
else if (foo === 7) {
260+
return 7;
261+
// EmptyStatement after return
262+
;;;;;;
263+
}
264+
else if (foo === 8) {
265+
return 8;
266+
// FunctionDeclaration after return
267+
function afterReturn() {}
268+
}
269+
else if (foo === 9) {
270+
return 9;
271+
// FunctionExpression after return
272+
const afterReturn = function afterReturn() {return 9}
273+
}
274+
else if (foo === 10) {
275+
{{{
276+
return 10;
277+
};};};
278+
}
279+
else if (foo === 11) {
280+
return 11;
281+
282+
{{{
283+
;;;
284+
function afterReturn() {}
285+
;;;
286+
function afterReturn2() {}
287+
;;;
288+
}}}
289+
}
290+
else if (foo === 12) {
291+
return twelve;
292+
var twelve = 12;
293+
}
294+
else return 'default';
295+
}
296+
`,
297+
outdent`
298+
function unicorn() {
299+
if (foo === 1) {
300+
if (true) {
301+
throw error;
302+
} else {
303+
return false;
304+
}
305+
}
306+
else if (foo === 2) {
307+
if (true) {
308+
throw error;
309+
}
310+
// no else, need break
311+
}
312+
else if (foo === 3) {
313+
if (a) {
314+
return a;
315+
} else if (b) {
316+
return b;
317+
} else if (c) {
318+
return c;
319+
} else if (d) {
320+
if (dd) {
321+
return dd;
322+
} else {
323+
return dd;
324+
}
325+
} else {
326+
return f;
327+
}
328+
}
329+
else if (foo === 4) {
330+
if (a) {
331+
return a;
332+
} else if (b) {
333+
return b;
334+
} else if (c) {
335+
return c;
336+
} else if (d) {
337+
return e;
338+
} // here
339+
// missing else deep inside, need break
340+
}
341+
else if (foo === 5) {
342+
if (a) {
343+
return a;
344+
} else if (b) {
345+
return b;
346+
} else if (c) {
347+
return c;
348+
} else if (d) {
349+
if (dd) {
350+
return dd;
351+
} else if (de) {
352+
return de;
353+
} // here
354+
} else {
355+
return f;
356+
}
357+
// missing else deep inside, need break
358+
}
359+
else if (foo === 6) {
360+
if (a) {
361+
return a;
362+
} else if (b) {
363+
return b;
364+
} else if (c) {
365+
// here
366+
} else if (d) {
367+
return e;
368+
} else {
369+
return f;
370+
}
371+
// missing one return, need break
372+
}
373+
else if (foo === 7) {
374+
if (a) return a;
375+
else if (b) {
376+
return b;;;;;
377+
} else if (c) {
378+
return c;
379+
function x() {}
380+
} else if (d) {
381+
return e;
382+
} else {
383+
return f;
384+
}
385+
}
386+
}
245387
`
246388
]
247389
});

0 commit comments

Comments
 (0)