Skip to content

Commit 0c763ed

Browse files
authored
Merge pull request microsoft#21370 from amcasey/GH20559
Handle case clause corner cases in extract symbol
2 parents d4b3bd1 + 2f3b06a commit 0c763ed

5 files changed

Lines changed: 97 additions & 0 deletions

File tree

src/harness/unittests/extractConstants.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,13 @@ let i: I = [#|{ a: 1 }|];
273273
const myObj: { member(x: number, y: string): void } = {
274274
member: [#|(x, y) => x + y|],
275275
}
276+
`);
277+
278+
testExtractConstant("extractConstant_CaseClauseExpression", `
279+
switch (1) {
280+
case [#|1|]:
281+
break;
282+
}
276283
`);
277284
});
278285

src/harness/unittests/extractRanges.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,52 @@ switch (x) {
365365
refactor.extractSymbol.Messages.cannotExtractRange.message
366366
]);
367367

368+
testExtractRangeFailed("extractRangeFailed14",
369+
`
370+
switch(1) {
371+
case [#|1:
372+
break;|]
373+
}
374+
`,
375+
[
376+
refactor.extractSymbol.Messages.cannotExtractRange.message
377+
]);
378+
379+
testExtractRangeFailed("extractRangeFailed15",
380+
`
381+
switch(1) {
382+
case [#|1:
383+
break|];
384+
}
385+
`,
386+
[
387+
refactor.extractSymbol.Messages.cannotExtractRange.message
388+
]);
389+
390+
// Documentation only - it would be nice if the result were [$|1|]
391+
testExtractRangeFailed("extractRangeFailed16",
392+
`
393+
switch(1) {
394+
[#|case 1|]:
395+
break;
396+
}
397+
`,
398+
[
399+
refactor.extractSymbol.Messages.cannotExtractRange.message
400+
]);
401+
402+
// Documentation only - it would be nice if the result were [$|1|]
403+
testExtractRangeFailed("extractRangeFailed17",
404+
`
405+
switch(1) {
406+
[#|case 1:|]
407+
break;
408+
}
409+
`,
410+
[
411+
refactor.extractSymbol.Messages.cannotExtractRange.message
412+
]);
413+
368414
testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [refactor.extractSymbol.Messages.cannotExtractIdentifier.message]);
369415
});
370416
}

src/services/refactors/extractSymbol.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,17 @@ namespace ts.refactor.extractSymbol {
235235
break;
236236
}
237237
}
238+
239+
if (!statements.length) {
240+
// https://github.com/Microsoft/TypeScript/issues/20559
241+
// Ranges like [|case 1: break;|] will fail to populate `statements` because
242+
// they will never find `start` in `start.parent.statements`.
243+
// Consider: We could support ranges like [|case 1:|] by refining them to just
244+
// the expression.
245+
Debug.assert(isCaseClause(start.parent) && span.start < start.parent.expression.end);
246+
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
247+
}
248+
238249
return { targetRange: { range: statements, facts: rangeFacts, declarations } };
239250
}
240251

@@ -1321,6 +1332,13 @@ namespace ts.refactor.extractSymbol {
13211332
}
13221333
prevStatement = statement;
13231334
}
1335+
1336+
if (!prevStatement && isCaseClause(curr)) {
1337+
// We must have been in the expression of the case clause.
1338+
Debug.assert(isSwitchStatement(curr.parent.parent));
1339+
return curr.parent.parent;
1340+
}
1341+
13241342
// There must be at least one statement since we started in one.
13251343
Debug.assert(prevStatement !== undefined);
13261344
return prevStatement;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// ==ORIGINAL==
2+
3+
switch (1) {
4+
case /*[#|*/1/*|]*/:
5+
break;
6+
}
7+
8+
// ==SCOPE::Extract to constant in enclosing scope==
9+
const newLocal = 1;
10+
switch (1) {
11+
case /*RENAME*/newLocal:
12+
break;
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// ==ORIGINAL==
2+
3+
switch (1) {
4+
case /*[#|*/1/*|]*/:
5+
break;
6+
}
7+
8+
// ==SCOPE::Extract to constant in enclosing scope==
9+
const newLocal = 1;
10+
switch (1) {
11+
case /*RENAME*/newLocal:
12+
break;
13+
}

0 commit comments

Comments
 (0)