Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb8448ff

Browse files
feat: correct no-useless-return behaviour in try statements (#16996)
* feat: correct `no-useless-return` behaviour in try statements* test: add more test cases for no-useless-return* refactor: fix formatting* refactor: fix formatting* fix: check all try block statements in the list* Fix a false positive---------Co-authored-by: Francesco Trotta <github@fasttime.org>
1 parent37432f2 commitb8448ff

File tree

2 files changed

+198
-20
lines changed

2 files changed

+198
-20
lines changed

‎lib/rules/no-useless-return.js‎

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ module.exports = {
8282

8383
create(context){
8484
constsegmentInfoMap=newWeakMap();
85-
constusedUnreachableSegments=newWeakSet();
8685
constsourceCode=context.sourceCode;
8786
letscopeInfo=null;
8887

@@ -152,24 +151,44 @@ module.exports = {
152151
* This behavior would simulate code paths for the case that the return
153152
* statement does not exist.
154153
*@param {CodePathSegment} segment The segment to get return statements.
154+
*@param {Set<CodePathSegment>} usedUnreachableSegments A set of segments that have already been traversed in this call.
155155
*@returns {void}
156156
*/
157-
functionmarkReturnStatementsOnSegmentAsUsed(segment){
157+
functionmarkReturnStatementsOnSegmentAsUsed(segment,usedUnreachableSegments){
158158
if(!segment.reachable){
159159
usedUnreachableSegments.add(segment);
160160
segment.allPrevSegments
161161
.filter(isReturned)
162162
.filter(prevSegment=>!usedUnreachableSegments.has(prevSegment))
163-
.forEach(markReturnStatementsOnSegmentAsUsed);
163+
.forEach(prevSegment=>markReturnStatementsOnSegmentAsUsed(prevSegment,usedUnreachableSegments));
164164
return;
165165
}
166166

167167
constinfo=segmentInfoMap.get(segment);
168168

169-
for(constnodeofinfo.uselessReturns){
169+
info.uselessReturns=info.uselessReturns.filter(node=>{
170+
if(scopeInfo.traversedTryBlockStatements&&scopeInfo.traversedTryBlockStatements.length>0){
171+
constreturnInitialRange=node.range[0];
172+
constreturnFinalRange=node.range[1];
173+
174+
constareBlocksInRange=scopeInfo.traversedTryBlockStatements.some(tryBlockStatement=>{
175+
constblockInitialRange=tryBlockStatement.range[0];
176+
constblockFinalRange=tryBlockStatement.range[1];
177+
178+
return(
179+
returnInitialRange>=blockInitialRange&&
180+
returnFinalRange<=blockFinalRange
181+
);
182+
});
183+
184+
if(areBlocksInRange){
185+
returntrue;
186+
}
187+
}
188+
170189
remove(scopeInfo.uselessReturns,node);
171-
}
172-
info.uselessReturns=[];
190+
returnfalse;
191+
});
173192
}
174193

175194
/**
@@ -188,7 +207,7 @@ module.exports = {
188207
scopeInfo
189208
.codePath
190209
.currentSegments
191-
.forEach(markReturnStatementsOnSegmentAsUsed);
210+
.forEach(segment=>markReturnStatementsOnSegmentAsUsed(segment,newSet()));
192211
}
193212

194213
//----------------------------------------------------------------------
@@ -202,6 +221,7 @@ module.exports = {
202221
scopeInfo={
203222
upper:scopeInfo,
204223
uselessReturns:[],
224+
traversedTryBlockStatements:[],
205225
codePath
206226
};
207227
},
@@ -275,6 +295,14 @@ module.exports = {
275295
scopeInfo.uselessReturns.push(node);
276296
},
277297

298+
"TryStatement > BlockStatement.block:exit"(node){
299+
scopeInfo.traversedTryBlockStatements.push(node);
300+
},
301+
302+
"TryStatement:exit"(){
303+
scopeInfo.traversedTryBlockStatements.pop();
304+
},
305+
278306
/*
279307
* Registers for all statement nodes except FunctionDeclaration, BlockStatement, BreakStatement.
280308
* Removes return statements of the current segments from the useless return statement list.

‎tests/lib/rules/no-useless-return.js‎

Lines changed: 163 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ const rule = require("../../../lib/rules/no-useless-return"),
1919
construleTester=newRuleTester();
2020

2121
ruleTester.run("no-useless-return",rule,{
22-
2322
valid:[
2423
"function foo() { return 5; }",
2524
"function foo() { return null; }",
@@ -96,6 +95,26 @@ ruleTester.run("no-useless-return", rule, {
9695
}
9796
}
9897
`,
98+
`
99+
function foo() {
100+
try {
101+
bar();
102+
return;
103+
} catch (err) {}
104+
baz();
105+
}
106+
`,
107+
`
108+
function foo() {
109+
if (something) {
110+
try {
111+
bar();
112+
return;
113+
} catch (err) {}
114+
}
115+
baz();
116+
}
117+
`,
99118
`
100119
function foo() {
101120
return;
@@ -176,6 +195,19 @@ ruleTester.run("no-useless-return", rule, {
176195
}
177196
console.log(arg);
178197
}
198+
`,
199+
200+
// https://github.com/eslint/eslint/pull/16996#discussion_r1138622844
201+
`
202+
function foo() {
203+
try {
204+
bar();
205+
return;
206+
} finally {
207+
baz();
208+
}
209+
qux();
210+
}
179211
`
180212
],
181213

@@ -386,12 +418,120 @@ ruleTester.run("no-useless-return", rule, {
386418
}
387419
`
388420
},
389-
390-
/*
391-
* FIXME: Re-add this case (removed due to https://github.com/eslint/eslint/issues/7481):
392-
* https://github.com/eslint/eslint/blob/261d7287820253408ec87c344beccdba2fe829a4/tests/lib/rules/no-useless-return.js#L308-L329
393-
*/
394-
421+
{
422+
code:`
423+
function foo() {
424+
try {
425+
foo();
426+
return;
427+
} catch (err) {
428+
return 5;
429+
}
430+
}
431+
`,
432+
output:`
433+
function foo() {
434+
try {
435+
foo();
436+
437+
} catch (err) {
438+
return 5;
439+
}
440+
}
441+
`
442+
},
443+
{
444+
code:`
445+
function foo() {
446+
if (something) {
447+
try {
448+
bar();
449+
return;
450+
} catch (err) {}
451+
}
452+
}
453+
`,
454+
output:`
455+
function foo() {
456+
if (something) {
457+
try {
458+
bar();
459+
460+
} catch (err) {}
461+
}
462+
}
463+
`
464+
},
465+
{
466+
code:`
467+
function foo() {
468+
try {
469+
return;
470+
} catch (err) {
471+
foo();
472+
}
473+
}
474+
`,
475+
output:`
476+
function foo() {
477+
try {
478+
479+
} catch (err) {
480+
foo();
481+
}
482+
}
483+
`
484+
},
485+
{
486+
code:`
487+
function foo() {
488+
try {
489+
return;
490+
} finally {
491+
bar();
492+
}
493+
}
494+
`,
495+
output:`
496+
function foo() {
497+
try {
498+
499+
} finally {
500+
bar();
501+
}
502+
}
503+
`
504+
},
505+
{
506+
code:`
507+
function foo() {
508+
try {
509+
bar();
510+
} catch (e) {
511+
try {
512+
baz();
513+
return;
514+
} catch (e) {
515+
qux();
516+
}
517+
}
518+
}
519+
`,
520+
output:`
521+
function foo() {
522+
try {
523+
bar();
524+
} catch (e) {
525+
try {
526+
baz();
527+
528+
} catch (e) {
529+
qux();
530+
}
531+
}
532+
}
533+
`
534+
},
395535
{
396536
code:`
397537
function foo() {
@@ -438,11 +578,21 @@ ruleTester.run("no-useless-return", rule, {
438578
{
439579
code:"function foo() { return; return; }",
440580
output:"function foo() { return; }",
441-
errors:[{
442-
messageId:"unnecessaryReturn",
443-
type:"ReturnStatement",
444-
column:18
445-
}]
581+
errors:[
582+
{
583+
messageId:"unnecessaryReturn",
584+
type:"ReturnStatement",
585+
column:18
586+
}
587+
]
446588
}
447-
].map(invalidCase=>Object.assign({errors:[{messageId:"unnecessaryReturn",type:"ReturnStatement"}]},invalidCase))
589+
].map(invalidCase=>
590+
Object.assign(
591+
{
592+
errors:[
593+
{messageId:"unnecessaryReturn",type:"ReturnStatement"}
594+
]
595+
},
596+
invalidCase
597+
))
448598
});

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp