Support for switch/case/default/break in getOccs
This commit is contained in:
parent
8ab4df0e25
commit
88f37e579c
5 changed files with 210 additions and 6 deletions
|
@ -2162,22 +2162,35 @@ module ts {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
if (node.kind === SyntaxKind.Identifier ||
|
||||
isLiteralNameOfPropertyDeclarationOrIndexAccess(node) ||
|
||||
isNameOfExternalModuleImportOrDeclaration(node)) {
|
||||
if (node.kind === SyntaxKind.Identifier || isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) {
|
||||
return getReferencesForNode(node, [sourceFile]);
|
||||
}
|
||||
|
||||
var result: ReferenceEntry[];
|
||||
|
||||
// Each of these helper functions bails out if the node is undefined,
|
||||
// which is why you'll see much of this'node.parent && node.parent.parent' pattern.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.TryKeyword:
|
||||
case SyntaxKind.CatchKeyword:
|
||||
case SyntaxKind.FinallyKeyword:
|
||||
return getTryCatchFinallyOccurrences(<TryStatement>(node.parent && node.parent.parent));
|
||||
result = getTryCatchFinallyOccurrences(<TryStatement>(node.parent && node.parent.parent));
|
||||
break;
|
||||
case SyntaxKind.SwitchKeyword:
|
||||
result = getSwitchCaseDefaultOccurrences(<SwitchStatement>node.parent);
|
||||
break;
|
||||
case SyntaxKind.CaseKeyword:
|
||||
case SyntaxKind.DefaultKeyword:
|
||||
result = getSwitchCaseDefaultOccurrences(<SwitchStatement>(node.parent && node.parent.parent));
|
||||
break;
|
||||
case SyntaxKind.BreakKeyword:
|
||||
result = getBreakStatementOccurences(<BreakOrContinueStatement>node.parent);
|
||||
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return result;
|
||||
|
||||
function getTryCatchFinallyOccurrences(tryStatement: TryStatement): ReferenceEntry[]{
|
||||
function getTryCatchFinallyOccurrences(tryStatement: TryStatement): ReferenceEntry[] {
|
||||
if (!tryStatement || tryStatement.kind !== SyntaxKind.TryStatement) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -2197,6 +2210,67 @@ module ts {
|
|||
return keywordsToReferenceEntries(keywords);
|
||||
}
|
||||
|
||||
function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement) {
|
||||
if (!switchStatement || switchStatement.kind !== SyntaxKind.SwitchStatement) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var keywords: Node[] = [];
|
||||
|
||||
pushIfKeyword(keywords, switchStatement.getFirstToken());
|
||||
|
||||
// Go through each clause in the switch statement, collecting the clause keywords.
|
||||
switchStatement.clauses.forEach(clause => {
|
||||
pushIfKeyword(keywords, clause.getFirstToken());
|
||||
|
||||
// For each clause, also recursively traverse the statements where we can find analogous breaks.
|
||||
forEachChild(clause, function aggregateBreakKeywords(node: Node): void {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.BreakStatement:
|
||||
// If the break statement has a label, cannot be part of
|
||||
if (!(<BreakOrContinueStatement>node).label) {
|
||||
pushIfKeyword(keywords, node.getFirstToken());
|
||||
}
|
||||
// Fall through
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.DoStatement:
|
||||
case SyntaxKind.WhileStatement:
|
||||
case SyntaxKind.SwitchStatement:
|
||||
return;
|
||||
}
|
||||
|
||||
forEachChild(node, aggregateBreakKeywords);
|
||||
});
|
||||
});
|
||||
|
||||
return keywordsToReferenceEntries(keywords);
|
||||
}
|
||||
|
||||
function getBreakStatementOccurences(breakStatement: BreakOrContinueStatement): ReferenceEntry[]{
|
||||
if (!breakStatement || breakStatement.kind !== SyntaxKind.BreakStatement) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// TODO (drosen): Deal with labeled statements.
|
||||
if (breakStatement.label) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for (var owner = node.parent; owner; owner = owner.parent) {
|
||||
switch (owner.kind) {
|
||||
case SyntaxKind.ForStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.DoStatement:
|
||||
case SyntaxKind.WhileStatement:
|
||||
// TODO (drosen): Handle loops!
|
||||
return undefined;
|
||||
case SyntaxKind.SwitchStatement:
|
||||
return getSwitchCaseDefaultOccurrences(<SwitchStatement>owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function pushIfKeyword(keywordList: Node[], token: Node) {
|
||||
if (token && isKeyword(token.kind)) {
|
||||
keywordList.push(token);
|
||||
|
|
29
tests/cases/fourslash/getOccurrencesSwitchCaseDefault.ts
Normal file
29
tests/cases/fourslash/getOccurrencesSwitchCaseDefault.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////[|sw/*1*/itch|] (10) {
|
||||
//// [|/*2*/case|] 1:
|
||||
//// [|cas/*3*/e|] 2:
|
||||
//// [|c/*4*/ase|] 4:
|
||||
//// [|c/*5*/ase|] 8:
|
||||
//// foo: switch (20) {
|
||||
//// case 1:
|
||||
//// case 2:
|
||||
//// break;
|
||||
//// default:
|
||||
//// break foo;
|
||||
//// }
|
||||
//// [|cas/*6*/e|] 0xBEEF:
|
||||
//// [|defa/*7*/ult|]:
|
||||
//// [|bre/*9*/ak|];
|
||||
//// [|/*8*/case|] 16:
|
||||
////}
|
||||
|
||||
|
||||
for (var i = 1; i <= test.markers().length; i++) {
|
||||
goTo.marker("" + i);
|
||||
verify.occurrencesAtPositionCount(9);
|
||||
|
||||
test.ranges().forEach(range => {
|
||||
verify.occurrencesAtPositionContains(range, false);
|
||||
});
|
||||
}
|
29
tests/cases/fourslash/getOccurrencesSwitchCaseDefault2.ts
Normal file
29
tests/cases/fourslash/getOccurrencesSwitchCaseDefault2.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////switch (10) {
|
||||
//// case 1:
|
||||
//// case 2:
|
||||
//// case 4:
|
||||
//// case 8:
|
||||
//// foo: [|swi/*1*/tch|] (20) {
|
||||
//// [|/*2*/case|] 1:
|
||||
//// [|cas/*3*/e|] 2:
|
||||
//// [|b/*4*/reak|];
|
||||
//// [|defaul/*5*/t|]:
|
||||
//// break foo;
|
||||
//// }
|
||||
//// case 0xBEEF:
|
||||
//// default:
|
||||
//// break;
|
||||
//// case 16:
|
||||
////}
|
||||
|
||||
|
||||
for (var i = 1; i <= test.markers().length; i++) {
|
||||
goTo.marker("" + i);
|
||||
verify.occurrencesAtPositionCount(5);
|
||||
|
||||
test.ranges().forEach(range => {
|
||||
verify.occurrencesAtPositionContains(range, false);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////swi/*1*/tch(10) {
|
||||
//// case 1:
|
||||
//// case 2:
|
||||
//// c/*2*/ase 4:
|
||||
//// case 8:
|
||||
//// case 0xBEEF:
|
||||
//// de/*4*/fult:
|
||||
//// break;
|
||||
//// /*5*/cas 16:
|
||||
//// c/*3*/ase 12:
|
||||
////}
|
||||
|
||||
////sw/*6*/itch (10) {
|
||||
//// de/*7*/fault
|
||||
//// case 1:
|
||||
//// case 2
|
||||
|
||||
//// c/*8*/ose 4:
|
||||
//// case 8:
|
||||
//// case 0xBEEF:
|
||||
//// bre/*9*/ak;
|
||||
//// case 16:
|
||||
////}
|
||||
|
||||
for (var i = 1; i <= test.markers().length; i++) {
|
||||
goTo.marker("" + i);
|
||||
|
||||
switch (i) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
verify.occurrencesAtPositionCount(8);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 8:
|
||||
verify.occurrencesAtPositionCount(1);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
case 9:
|
||||
verify.occurrencesAtPositionCount(8);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////switch/*1*/ (10) {
|
||||
//// case/*2*/ 1:
|
||||
//// case/*3*/ 2:
|
||||
//// case/*4*/ 4:
|
||||
//// case/*5*/ 8:
|
||||
//// foo: switch/*6*/ (20) {
|
||||
//// case/*7*/ 1:
|
||||
//// case/*8*/ 2:
|
||||
//// break/*9*/;
|
||||
//// default/*10*/:
|
||||
//// break foo;
|
||||
//// }
|
||||
//// case/*11*/ 0xBEEF:
|
||||
//// default/*12*/:
|
||||
//// break/*13*/;
|
||||
//// case 16/*14*/:
|
||||
////}
|
||||
|
||||
|
||||
for (var i = 1; i <= test.markers().length; i++) {
|
||||
goTo.marker("" + i);
|
||||
verify.occurrencesAtPositionCount(0);
|
||||
}
|
Loading…
Reference in a new issue