Added getOccs support for if/else keywords, and some tests.

This commit is contained in:
Daniel Rosenwasser 2014-08-28 17:14:57 -07:00
parent 41d8d6c4e1
commit 24f6e41de1
6 changed files with 232 additions and 12 deletions

View file

@ -2168,6 +2168,11 @@ module ts {
}
switch (node.kind) {
case SyntaxKind.IfKeyword:
case SyntaxKind.ElseKeyword:
if (hasKind(node.parent, SyntaxKind.IfStatement)) {
return getIfElseOccurrences(<IfStatement>node.parent);
}
case SyntaxKind.TryKeyword:
case SyntaxKind.CatchKeyword:
case SyntaxKind.FinallyKeyword:
@ -2195,6 +2200,65 @@ module ts {
return undefined;
function getIfElseOccurrences(ifStatement: IfStatement): ReferenceEntry[] {
var keywords: Node[] = [];
// Traverse upwards through all parent if-statements linked by their else-branches.
while (hasKind(ifStatement.parent, SyntaxKind.IfStatement) && (<IfStatement>ifStatement.parent).elseStatement === ifStatement) {
ifStatement = <IfStatement>ifStatement.parent;
}
// Now traverse back down through the else branches, aggregating if/else keywords of if-statements.
while (ifStatement) {
pushIfAndElseKeywords();
if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) {
break
}
ifStatement = <IfStatement>ifStatement.elseStatement;
}
var result: ReferenceEntry[] = [];
// Here we do a little extra.
// We'd like to make else/ifs on the same line to be highlighted together
for (var i = 0; i < keywords.length; i++) {
if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) {
var elseKeyword = keywords[i];
var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword.
// Ensure that the keywords are only separated by trivia.
if (elseKeyword.end === ifKeyword.getFullStart()) {
var elseLine = sourceFile.getLineAndCharacterFromPosition(elseKeyword.end);
var ifLine = sourceFile.getLineAndCharacterFromPosition(ifKeyword.getStart());
if (elseLine.line === ifLine.line) {
result.push(new ReferenceEntry(filename, TypeScript.TextSpan.fromBounds(elseKeyword.getStart(), ifKeyword.end), /* isWriteAccess */ false));
i++; // skip the next keyword
continue;
}
}
}
result.push(keywordToReferenceEntry(keywords[i]));
}
return result;
function pushIfAndElseKeywords() {
var children = ifStatement.getChildren();
pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword);
// Generally the 'else' keyword is second-to-last, so we traverse backwards.
for (var i = children.length - 1; i >= 0; i--) {
if (pushKeywordIf(keywords, children[i], SyntaxKind.ElseKeyword)) {
break;
}
}
}
}
function getTryCatchFinallyOccurrences(tryStatement: TryStatement): ReferenceEntry[] {
var keywords: Node[] = [];
@ -2208,7 +2272,7 @@ module ts {
pushKeywordIf(keywords, tryStatement.finallyBlock.getFirstToken(), SyntaxKind.FinallyKeyword);
}
return keywordsToReferenceEntries(keywords);
return map(keywords, keywordToReferenceEntry);
}
function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement) {
@ -2244,7 +2308,7 @@ module ts {
});
});
return keywordsToReferenceEntries(keywords);
return map(keywords, keywordToReferenceEntry);
}
function getBreakStatementOccurences(breakStatement: BreakOrContinueStatement): ReferenceEntry[]{
@ -2285,20 +2349,17 @@ module ts {
return node && node.parent;
}
function pushKeywordIf(keywordList: Node[], token: Node, ...expected: SyntaxKind[]): void {
if (!token) {
return;
function pushKeywordIf(keywordList: Node[], token: Node, ...expected: SyntaxKind[]): boolean {
if (token && contains(<SyntaxKind[]>expected, token.kind)) {
keywordList.push(token);
return true;
}
if (contains(<SyntaxKind[]>expected, token.kind)) {
keywordList.push(token);
}
return false;
}
function keywordsToReferenceEntries(keywords: Node[]): ReferenceEntry[]{
return map(keywords, keyword =>
new ReferenceEntry(filename, TypeScript.TextSpan.fromBounds(keyword.getStart(), keyword.end), /* isWriteAccess */ false)
);
function keywordToReferenceEntry(keyword: Node): ReferenceEntry {
return new ReferenceEntry(filename, TypeScript.TextSpan.fromBounds(keyword.getStart(), keyword.end), /* isWriteAccess */ false);
}
}

View file

@ -0,0 +1,36 @@
/// <reference path='fourslash.ts' />
////[|if|] (true) {
//// if (false) {
//// }
//// else {
//// }
//// if (true) {
//// }
//// else {
//// if (false)
//// if (true)
//// var x = undefined;
//// }
////}
////[|else i/**/f|] (null) {
////}
////[|else /* whar garbl */ if|] (undefined) {
////}
////[|else|]
////[|if|] (false) {
////}
////[|else|] { }
test.ranges().forEach(r => {
goTo.position(r.start);
test.ranges().forEach(range => {
verify.occurrencesAtPositionContains(range, false);
});
});
goTo.marker();
test.ranges().forEach(range => {
verify.occurrencesAtPositionContains(range, false);
});

View file

@ -0,0 +1,32 @@
/// <reference path='fourslash.ts' />
////if (true) {
//// [|if|] (false) {
//// }
//// [|else|]{
//// }
//// if (true) {
//// }
//// else {
//// if (false)
//// if (true)
//// var x = undefined;
//// }
////}
////else if (null) {
////}
////else /* whar garbl */ if (undefined) {
////}
////else
////if (false) {
////}
////else { }
test.ranges().forEach(r => {
goTo.position(r.start);
test.ranges().forEach(range => {
verify.occurrencesAtPositionContains(range, false);
});
});

View file

@ -0,0 +1,32 @@
/// <reference path='fourslash.ts' />
////if (true) {
//// if (false) {
//// }
//// else {
//// }
//// [|if|] (true) {
//// }
//// [|else|] {
//// if (false)
//// if (true)
//// var x = undefined;
//// }
////}
////else if (null) {
////}
////else /* whar garbl */ if (undefined) {
////}
////else
////if (false) {
////}
////else { }
test.ranges().forEach(r => {
goTo.position(r.start);
test.ranges().forEach(range => {
verify.occurrencesAtPositionContains(range, false);
});
});

View file

@ -0,0 +1,30 @@
/// <reference path='fourslash.ts' />
////if (true) {
//// if (false) {
//// }
//// else {
//// }
//// if (true) {
//// }
//// else {
//// /*1*/if (false)
//// /*2*/i/*3*/f (true)
//// var x = undefined;
//// }
////}
////else if (null) {
////}
////else /* whar garbl */ if (undefined) {
////}
////else
////if (false) {
////}
////else { }
for (var i = 1; i <= test.markers().length; i++) {
goTo.marker("" + i);
verify.occurrencesAtPositionCount(1);
}

View file

@ -0,0 +1,29 @@
/// <reference path='fourslash.ts' />
////if/*1*/ (true) {
//// if/*2*/ (false) {
//// }
//// else/*3*/ {
//// }
//// if/*4*/ (true) {
//// }
//// else/*5*/ {
//// if/*6*/ (false)
//// if/*7*/ (true)
//// var x = undefined;
//// }
////}
////else/*8*/ if (null) {
////}
////else/*9*/ /* whar garbl */ if/*10*/ (undefined) {
////}
////else/*11*/
////if/*12*/ (false) {
////}
////else/*13*/ { }
for (var i = 1; i <= test.markers().length; i++) {
goTo.marker("" + i);
verify.occurrencesAtPositionCount(0);
}