Skip to content

Commit 12d1ea5

Browse files
committed
Merge pull request microsoft#18165 from amcasey/GH18144
Simplify and correct PermittedJumps computation (cherry picked from commit deefb01)
1 parent 2dd647d commit 12d1ea5

File tree

3 files changed

+90
-40
lines changed

3 files changed

+90
-40
lines changed

src/harness/unittests/extractMethods.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,30 @@ 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+
testExtractRangeFailed("extractRangeFailed8",
394+
`
395+
function test(x: number) {
396+
switch (x) {
397+
case 1:
398+
[#|break;|]
399+
}
400+
}
401+
`,
402+
[
403+
"Cannot extract range containing conditional break or continue statements."
404+
]);
381405
testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, ["Select more than a single token."]);
382406

383407
testExtractMethod("extractMethod1",
@@ -561,6 +585,15 @@ namespace A {
561585
let x = 10;
562586
[#|x++;
563587
return;|]
588+
}`);
589+
// Return in finally block
590+
testExtractMethod("extractMethod22",
591+
`function test() {
592+
try {
593+
}
594+
finally {
595+
[#|return 1;|]
596+
}
564597
}`);
565598
});
566599

src/services/refactors/extractMethod.ts

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -340,45 +340,31 @@ namespace ts.refactor.extractMethod {
340340
return false;
341341
}
342342
const savedPermittedJumps = permittedJumps;
343-
if (node.parent) {
344-
switch (node.parent.kind) {
345-
case SyntaxKind.IfStatement:
346-
if ((<IfStatement>node.parent).thenStatement === node || (<IfStatement>node.parent).elseStatement === node) {
347-
// forbid all jumps inside thenStatement or elseStatement
348-
permittedJumps = PermittedJumps.None;
349-
}
350-
break;
351-
case SyntaxKind.TryStatement:
352-
if ((<TryStatement>node.parent).tryBlock === node) {
353-
// forbid all jumps inside try blocks
354-
permittedJumps = PermittedJumps.None;
355-
}
356-
else if ((<TryStatement>node.parent).finallyBlock === node) {
357-
// allow unconditional returns from finally blocks
358-
permittedJumps = PermittedJumps.Return;
359-
}
360-
break;
361-
case SyntaxKind.CatchClause:
362-
if ((<CatchClause>node.parent).block === node) {
363-
// forbid all jumps inside the block of catch clause
364-
permittedJumps = PermittedJumps.None;
365-
}
366-
break;
367-
case SyntaxKind.CaseClause:
368-
if ((<CaseClause>node).expression !== node) {
369-
// allow unlabeled break inside case clauses
370-
permittedJumps |= PermittedJumps.Break;
371-
}
372-
break;
373-
default:
374-
if (isIterationStatement(node.parent, /*lookInLabeledStatements*/ false)) {
375-
if ((<IterationStatement>node.parent).statement === node) {
376-
// allow unlabeled break/continue inside loops
377-
permittedJumps |= PermittedJumps.Break | PermittedJumps.Continue;
378-
}
379-
}
380-
break;
381-
}
343+
344+
switch (node.kind) {
345+
case SyntaxKind.IfStatement:
346+
permittedJumps = PermittedJumps.None;
347+
break;
348+
case SyntaxKind.TryStatement:
349+
// forbid all jumps inside try blocks
350+
permittedJumps = PermittedJumps.None;
351+
break;
352+
case SyntaxKind.Block:
353+
if (node.parent && node.parent.kind === SyntaxKind.TryStatement && (<TryStatement>node).finallyBlock === node) {
354+
// allow unconditional returns from finally blocks
355+
permittedJumps = PermittedJumps.Return;
356+
}
357+
break;
358+
case SyntaxKind.CaseClause:
359+
// allow unlabeled break inside case clauses
360+
permittedJumps |= PermittedJumps.Break;
361+
break;
362+
default:
363+
if (isIterationStatement(node, /*lookInLabeledStatements*/ false)) {
364+
// allow unlabeled break/continue inside loops
365+
permittedJumps |= PermittedJumps.Break | PermittedJumps.Continue;
366+
}
367+
break;
382368
}
383369

384370
switch (node.kind) {
@@ -405,7 +391,7 @@ namespace ts.refactor.extractMethod {
405391
}
406392
}
407393
else {
408-
if (!(permittedJumps & (SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) {
394+
if (!(permittedJumps & (node.kind === SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) {
409395
// attempt to break or continue in a forbidden context
410396
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements));
411397
}
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 /*RENAME*/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 /*RENAME*/newFunction();
27+
}
28+
}
29+
function newFunction() {
30+
return 1;
31+
}

0 commit comments

Comments
 (0)