Skip to content

Commit deefb01

Browse files
authored
Merge pull request #18165 from amcasey/GH18144
Simplify and correct PermittedJumps computation
2 parents d4e3e19 + baefdd2 commit deefb01

File tree

3 files changed

+92
-40
lines changed

3 files changed

+92
-40
lines changed

src/harness/unittests/extractMethods.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,32 @@ namespace A {
378378
"Cannot extract range containing conditional return statement."
379379
]);
380380

381+
testExtractRangeFailed("extractRangeFailed7",
382+
`
383+
function test(x: number) {
384+
while (x) {
385+
x--;
386+
[#|break;|]
387+
}
388+
}
389+
`,
390+
[
391+
"Cannot extract range containing conditional break or continue statements."
392+
]);
393+
394+
testExtractRangeFailed("extractRangeFailed8",
395+
`
396+
function test(x: number) {
397+
switch (x) {
398+
case 1:
399+
[#|break;|]
400+
}
401+
}
402+
`,
403+
[
404+
"Cannot extract range containing conditional break or continue statements."
405+
]);
406+
381407
testExtractMethod("extractMethod1",
382408
`namespace A {
383409
let x = 1;
@@ -620,6 +646,15 @@ namespace A {
620646
let x = 10;
621647
[#|x++;
622648
return;|]
649+
}`);
650+
// Return in finally block
651+
testExtractMethod("extractMethod22",
652+
`function test() {
653+
try {
654+
}
655+
finally {
656+
[#|return 1;|]
657+
}
623658
}`);
624659
});
625660

src/services/refactors/extractMethod.ts

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -352,45 +352,31 @@ namespace ts.refactor.extractMethod {
352352
return false;
353353
}
354354
const savedPermittedJumps = permittedJumps;
355-
if (node.parent) {
356-
switch (node.parent.kind) {
357-
case SyntaxKind.IfStatement:
358-
if ((<IfStatement>node.parent).thenStatement === node || (<IfStatement>node.parent).elseStatement === node) {
359-
// forbid all jumps inside thenStatement or elseStatement
360-
permittedJumps = PermittedJumps.None;
361-
}
362-
break;
363-
case SyntaxKind.TryStatement:
364-
if ((<TryStatement>node.parent).tryBlock === node) {
365-
// forbid all jumps inside try blocks
366-
permittedJumps = PermittedJumps.None;
367-
}
368-
else if ((<TryStatement>node.parent).finallyBlock === node) {
369-
// allow unconditional returns from finally blocks
370-
permittedJumps = PermittedJumps.Return;
371-
}
372-
break;
373-
case SyntaxKind.CatchClause:
374-
if ((<CatchClause>node.parent).block === node) {
375-
// forbid all jumps inside the block of catch clause
376-
permittedJumps = PermittedJumps.None;
377-
}
378-
break;
379-
case SyntaxKind.CaseClause:
380-
if ((<CaseClause>node).expression !== node) {
381-
// allow unlabeled break inside case clauses
382-
permittedJumps |= PermittedJumps.Break;
383-
}
384-
break;
385-
default:
386-
if (isIterationStatement(node.parent, /*lookInLabeledStatements*/ false)) {
387-
if ((<IterationStatement>node.parent).statement === node) {
388-
// allow unlabeled break/continue inside loops
389-
permittedJumps |= PermittedJumps.Break | PermittedJumps.Continue;
390-
}
391-
}
392-
break;
393-
}
355+
356+
switch (node.kind) {
357+
case SyntaxKind.IfStatement:
358+
permittedJumps = PermittedJumps.None;
359+
break;
360+
case SyntaxKind.TryStatement:
361+
// forbid all jumps inside try blocks
362+
permittedJumps = PermittedJumps.None;
363+
break;
364+
case SyntaxKind.Block:
365+
if (node.parent && node.parent.kind === SyntaxKind.TryStatement && (<TryStatement>node).finallyBlock === node) {
366+
// allow unconditional returns from finally blocks
367+
permittedJumps = PermittedJumps.Return;
368+
}
369+
break;
370+
case SyntaxKind.CaseClause:
371+
// allow unlabeled break inside case clauses
372+
permittedJumps |= PermittedJumps.Break;
373+
break;
374+
default:
375+
if (isIterationStatement(node, /*lookInLabeledStatements*/ false)) {
376+
// allow unlabeled break/continue inside loops
377+
permittedJumps |= PermittedJumps.Break | PermittedJumps.Continue;
378+
}
379+
break;
394380
}
395381

396382
switch (node.kind) {
@@ -417,7 +403,7 @@ namespace ts.refactor.extractMethod {
417403
}
418404
}
419405
else {
420-
if (!(permittedJumps & (SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) {
406+
if (!(permittedJumps & (node.kind === SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) {
421407
// attempt to break or continue in a forbidden context
422408
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements));
423409
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// ==ORIGINAL==
2+
function test() {
3+
try {
4+
}
5+
finally {
6+
return 1;
7+
}
8+
}
9+
// ==SCOPE::function 'test'==
10+
function test() {
11+
try {
12+
}
13+
finally {
14+
return newFunction();
15+
}
16+
17+
function newFunction() {
18+
return 1;
19+
}
20+
}
21+
// ==SCOPE::global scope==
22+
function test() {
23+
try {
24+
}
25+
finally {
26+
return newFunction();
27+
}
28+
}
29+
function newFunction() {
30+
return 1;
31+
}

0 commit comments

Comments
 (0)