Skip to content

Commit 88f37e5

Browse files
Support for switch/case/default/break in getOccs
1 parent 8ab4df0 commit 88f37e5

File tree

5 files changed

+210
-6
lines changed

5 files changed

+210
-6
lines changed

src/services/services.ts

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2162,22 +2162,35 @@ module ts {
21622162
return undefined;
21632163
}
21642164

2165-
if (node.kind === SyntaxKind.Identifier ||
2166-
isLiteralNameOfPropertyDeclarationOrIndexAccess(node) ||
2167-
isNameOfExternalModuleImportOrDeclaration(node)) {
2165+
if (node.kind === SyntaxKind.Identifier || isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) {
21682166
return getReferencesForNode(node, [sourceFile]);
21692167
}
21702168

2169+
var result: ReferenceEntry[];
2170+
2171+
// Each of these helper functions bails out if the node is undefined,
2172+
// which is why you'll see much of this'node.parent && node.parent.parent' pattern.
21712173
switch (node.kind) {
21722174
case SyntaxKind.TryKeyword:
21732175
case SyntaxKind.CatchKeyword:
21742176
case SyntaxKind.FinallyKeyword:
2175-
return getTryCatchFinallyOccurrences(<TryStatement>(node.parent && node.parent.parent));
2177+
result = getTryCatchFinallyOccurrences(<TryStatement>(node.parent && node.parent.parent));
2178+
break;
2179+
case SyntaxKind.SwitchKeyword:
2180+
result = getSwitchCaseDefaultOccurrences(<SwitchStatement>node.parent);
2181+
break;
2182+
case SyntaxKind.CaseKeyword:
2183+
case SyntaxKind.DefaultKeyword:
2184+
result = getSwitchCaseDefaultOccurrences(<SwitchStatement>(node.parent && node.parent.parent));
2185+
break;
2186+
case SyntaxKind.BreakKeyword:
2187+
result = getBreakStatementOccurences(<BreakOrContinueStatement>node.parent);
2188+
21762189
}
21772190

2178-
return undefined;
2191+
return result;
21792192

2180-
function getTryCatchFinallyOccurrences(tryStatement: TryStatement): ReferenceEntry[]{
2193+
function getTryCatchFinallyOccurrences(tryStatement: TryStatement): ReferenceEntry[] {
21812194
if (!tryStatement || tryStatement.kind !== SyntaxKind.TryStatement) {
21822195
return undefined;
21832196
}
@@ -2197,6 +2210,67 @@ module ts {
21972210
return keywordsToReferenceEntries(keywords);
21982211
}
21992212

2213+
function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement) {
2214+
if (!switchStatement || switchStatement.kind !== SyntaxKind.SwitchStatement) {
2215+
return undefined;
2216+
}
2217+
2218+
var keywords: Node[] = [];
2219+
2220+
pushIfKeyword(keywords, switchStatement.getFirstToken());
2221+
2222+
// Go through each clause in the switch statement, collecting the clause keywords.
2223+
switchStatement.clauses.forEach(clause => {
2224+
pushIfKeyword(keywords, clause.getFirstToken());
2225+
2226+
// For each clause, also recursively traverse the statements where we can find analogous breaks.
2227+
forEachChild(clause, function aggregateBreakKeywords(node: Node): void {
2228+
switch (node.kind) {
2229+
case SyntaxKind.BreakStatement:
2230+
// If the break statement has a label, cannot be part of
2231+
if (!(<BreakOrContinueStatement>node).label) {
2232+
pushIfKeyword(keywords, node.getFirstToken());
2233+
}
2234+
// Fall through
2235+
case SyntaxKind.ForStatement:
2236+
case SyntaxKind.ForInStatement:
2237+
case SyntaxKind.DoStatement:
2238+
case SyntaxKind.WhileStatement:
2239+
case SyntaxKind.SwitchStatement:
2240+
return;
2241+
}
2242+
2243+
forEachChild(node, aggregateBreakKeywords);
2244+
});
2245+
});
2246+
2247+
return keywordsToReferenceEntries(keywords);
2248+
}
2249+
2250+
function getBreakStatementOccurences(breakStatement: BreakOrContinueStatement): ReferenceEntry[]{
2251+
if (!breakStatement || breakStatement.kind !== SyntaxKind.BreakStatement) {
2252+
return undefined;
2253+
}
2254+
2255+
// TODO (drosen): Deal with labeled statements.
2256+
if (breakStatement.label) {
2257+
return undefined;
2258+
}
2259+
2260+
for (var owner = node.parent; owner; owner = owner.parent) {
2261+
switch (owner.kind) {
2262+
case SyntaxKind.ForStatement:
2263+
case SyntaxKind.ForInStatement:
2264+
case SyntaxKind.DoStatement:
2265+
case SyntaxKind.WhileStatement:
2266+
// TODO (drosen): Handle loops!
2267+
return undefined;
2268+
case SyntaxKind.SwitchStatement:
2269+
return getSwitchCaseDefaultOccurrences(<SwitchStatement>owner);
2270+
}
2271+
}
2272+
}
2273+
22002274
function pushIfKeyword(keywordList: Node[], token: Node) {
22012275
if (token && isKeyword(token.kind)) {
22022276
keywordList.push(token);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////[|sw/*1*/itch|] (10) {
4+
//// [|/*2*/case|] 1:
5+
//// [|cas/*3*/e|] 2:
6+
//// [|c/*4*/ase|] 4:
7+
//// [|c/*5*/ase|] 8:
8+
//// foo: switch (20) {
9+
//// case 1:
10+
//// case 2:
11+
//// break;
12+
//// default:
13+
//// break foo;
14+
//// }
15+
//// [|cas/*6*/e|] 0xBEEF:
16+
//// [|defa/*7*/ult|]:
17+
//// [|bre/*9*/ak|];
18+
//// [|/*8*/case|] 16:
19+
////}
20+
21+
22+
for (var i = 1; i <= test.markers().length; i++) {
23+
goTo.marker("" + i);
24+
verify.occurrencesAtPositionCount(9);
25+
26+
test.ranges().forEach(range => {
27+
verify.occurrencesAtPositionContains(range, false);
28+
});
29+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////switch (10) {
4+
//// case 1:
5+
//// case 2:
6+
//// case 4:
7+
//// case 8:
8+
//// foo: [|swi/*1*/tch|] (20) {
9+
//// [|/*2*/case|] 1:
10+
//// [|cas/*3*/e|] 2:
11+
//// [|b/*4*/reak|];
12+
//// [|defaul/*5*/t|]:
13+
//// break foo;
14+
//// }
15+
//// case 0xBEEF:
16+
//// default:
17+
//// break;
18+
//// case 16:
19+
////}
20+
21+
22+
for (var i = 1; i <= test.markers().length; i++) {
23+
goTo.marker("" + i);
24+
verify.occurrencesAtPositionCount(5);
25+
26+
test.ranges().forEach(range => {
27+
verify.occurrencesAtPositionContains(range, false);
28+
});
29+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////swi/*1*/tch(10) {
4+
//// case 1:
5+
//// case 2:
6+
//// c/*2*/ase 4:
7+
//// case 8:
8+
//// case 0xBEEF:
9+
//// de/*4*/fult:
10+
//// break;
11+
//// /*5*/cas 16:
12+
//// c/*3*/ase 12:
13+
////}
14+
15+
////sw/*6*/itch (10) {
16+
//// de/*7*/fault
17+
//// case 1:
18+
//// case 2
19+
20+
//// c/*8*/ose 4:
21+
//// case 8:
22+
//// case 0xBEEF:
23+
//// bre/*9*/ak;
24+
//// case 16:
25+
////}
26+
27+
for (var i = 1; i <= test.markers().length; i++) {
28+
goTo.marker("" + i);
29+
30+
switch (i) {
31+
case 1:
32+
case 2:
33+
case 3:
34+
verify.occurrencesAtPositionCount(8);
35+
break;
36+
case 4:
37+
case 5:
38+
case 8:
39+
verify.occurrencesAtPositionCount(1);
40+
break;
41+
case 6:
42+
case 7:
43+
case 9:
44+
verify.occurrencesAtPositionCount(8);
45+
break;
46+
}
47+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////switch/*1*/ (10) {
4+
//// case/*2*/ 1:
5+
//// case/*3*/ 2:
6+
//// case/*4*/ 4:
7+
//// case/*5*/ 8:
8+
//// foo: switch/*6*/ (20) {
9+
//// case/*7*/ 1:
10+
//// case/*8*/ 2:
11+
//// break/*9*/;
12+
//// default/*10*/:
13+
//// break foo;
14+
//// }
15+
//// case/*11*/ 0xBEEF:
16+
//// default/*12*/:
17+
//// break/*13*/;
18+
//// case 16/*14*/:
19+
////}
20+
21+
22+
for (var i = 1; i <= test.markers().length; i++) {
23+
goTo.marker("" + i);
24+
verify.occurrencesAtPositionCount(0);
25+
}

0 commit comments

Comments
 (0)