diff --git a/doc/TypeScript Language Specification.docx b/doc/TypeScript Language Specification.docx index 740dd2c6034..381ac186a4b 100644 Binary files a/doc/TypeScript Language Specification.docx and b/doc/TypeScript Language Specification.docx differ diff --git a/doc/TypeScript Language Specification.pdf b/doc/TypeScript Language Specification.pdf index 4263dd72dc1..049f7e06fb3 100644 Binary files a/doc/TypeScript Language Specification.pdf and b/doc/TypeScript Language Specification.pdf differ diff --git a/doc/spec.md b/doc/spec.md index e49132c61fc..5635c100a40 100644 --- a/doc/spec.md +++ b/doc/spec.md @@ -581,10 +581,10 @@ For this switch statement, the compiler will generate the following code. ```TypeScript switch (op) { - case 0 /* Operator.ADD */ : + case 0 /* Operator.ADD */: // execute add break; - case 1 /* Operator.DIV */ : + case 1 /* Operator.DIV */: // execute div break; // ... @@ -738,7 +738,7 @@ var M; return s; } M.f = f; -})(M||(M={})); +})(M || (M = {})); ``` In this case, the compiler assumes that the module object resides in global variable ‘M’, which may or may not have been initialized to the desired module object. @@ -1068,7 +1068,7 @@ Type references (section [3.6.2](#3.6.2)) to class and interface types are class ### 3.3.2 Array Types -***Array types*** represent JavaScript arrays with a common element type. Array types are named type references created from the generic interface type ‘Array’ in the global module with the array element type as a type argument. Array type literals (section [Error! Reference source not found.](#Error! Reference source not found.)) provide a shorthand notation for creating such references. +***Array types*** represent JavaScript arrays with a common element type. Array types are named type references created from the generic interface type ‘Array’ in the global module with the array element type as a type argument. Array type literals (section [3.6.4](#3.6.4)) provide a shorthand notation for creating such references. The declaration of the ‘Array’ interface includes a property ‘length’ and a numeric index signature for the element type, along with other members: diff --git a/src/services/services.ts b/src/services/services.ts index e2089e0ade7..a0481a2f926 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2121,7 +2121,7 @@ module ts { } // TODO: this is a hack for now, we need a proper walking mechanism to verify that we have the correct node - var mappedNode = getNodeAtPosition(sourceFile, TypeScript.end(node) - 1); + var mappedNode = getTouchingToken(sourceFile, TypeScript.end(node) - 1); if (isPunctuation(mappedNode.kind)) { mappedNode = mappedNode.parent; } @@ -2358,7 +2358,7 @@ module ts { fileName = TypeScript.switchToForwardSlashes(fileName); var sourceFile = getSourceFile(fileName); - var node = getNodeAtPosition(sourceFile, position); + var node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } @@ -2466,7 +2466,7 @@ module ts { fileName = TypeScript.switchToForwardSlashes(fileName); var sourceFile = getSourceFile(fileName); - var node = getNodeAtPosition(sourceFile, position); + var node = getTouchingWord(sourceFile, position); if (!node) { return undefined; } @@ -2549,7 +2549,7 @@ module ts { filename = TypeScript.switchToForwardSlashes(filename); var sourceFile = getSourceFile(filename); - var node = getNodeAtPosition(sourceFile, position); + var node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } @@ -2613,7 +2613,7 @@ module ts { filename = TypeScript.switchToForwardSlashes(filename); var sourceFile = getSourceFile(filename); - var node = getNodeAtPosition(sourceFile, position); + var node = getTouchingWord(sourceFile, position); if (!node) { return undefined; } @@ -3058,7 +3058,7 @@ module ts { filename = TypeScript.switchToForwardSlashes(filename); var sourceFile = getSourceFile(filename); - var node = getNodeAtPosition(sourceFile, position); + var node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } @@ -3241,7 +3241,7 @@ module ts { forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - var node = getNodeAtPosition(sourceFile, position); + var node = getTouchingWord(sourceFile, position); if (!node || node.getWidth() !== labelName.length) { return; } @@ -3297,7 +3297,7 @@ module ts { forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - var referenceLocation = getNodeAtPosition(sourceFile, position); + var referenceLocation = getTouchingPropertyName(sourceFile, position); if (!isValidReferencePosition(referenceLocation, searchText)) { return; } @@ -3349,7 +3349,7 @@ module ts { forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - var node = getNodeAtPosition(sourceFile, position); + var node = getTouchingWord(sourceFile, position); if (!node || node.kind !== SyntaxKind.SuperKeyword) { return; @@ -3415,7 +3415,7 @@ module ts { forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - var node = getNodeAtPosition(sourceFile, position); + var node = getTouchingWord(sourceFile, position); if (!node || node.kind !== SyntaxKind.ThisKeyword) { return; } @@ -4229,7 +4229,7 @@ module ts { var sourceFile = getCurrentSourceFile(filename); var result: TypeScript.TextSpan[] = []; - var token = getTokenAtPosition(sourceFile, position); + var token = getTouchingToken(sourceFile, position); if (token.getStart(sourceFile) === position) { var matchKind = getMatchingTokenKind(token); @@ -4513,7 +4513,7 @@ module ts { fileName = TypeScript.switchToForwardSlashes(fileName); var sourceFile = getSourceFile(fileName); - var node = getNodeAtPosition(sourceFile, position); + var node = getTouchingWord(sourceFile, position); // Can only rename an identifier. if (node && node.kind === SyntaxKind.Identifier) { @@ -4599,26 +4599,58 @@ module ts { /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where /// we have a series of divide operator. this list allows us to be more accurate by ruling out /// locations where a regexp cannot exist. - var noRegexTable: boolean[]; - if (!noRegexTable) { - noRegexTable = []; - noRegexTable[SyntaxKind.Identifier] = true; - noRegexTable[SyntaxKind.StringLiteral] = true; - noRegexTable[SyntaxKind.NumericLiteral] = true; - noRegexTable[SyntaxKind.RegularExpressionLiteral] = true; - noRegexTable[SyntaxKind.ThisKeyword] = true; - noRegexTable[SyntaxKind.PlusPlusToken] = true; - noRegexTable[SyntaxKind.MinusMinusToken] = true; - noRegexTable[SyntaxKind.CloseParenToken] = true; - noRegexTable[SyntaxKind.CloseBracketToken] = true; - noRegexTable[SyntaxKind.CloseBraceToken] = true; - noRegexTable[SyntaxKind.TrueKeyword] = true; - noRegexTable[SyntaxKind.FalseKeyword] = true; + var noRegexTable: boolean[] = []; + noRegexTable[SyntaxKind.Identifier] = true; + noRegexTable[SyntaxKind.StringLiteral] = true; + noRegexTable[SyntaxKind.NumericLiteral] = true; + noRegexTable[SyntaxKind.RegularExpressionLiteral] = true; + noRegexTable[SyntaxKind.ThisKeyword] = true; + noRegexTable[SyntaxKind.PlusPlusToken] = true; + noRegexTable[SyntaxKind.MinusMinusToken] = true; + noRegexTable[SyntaxKind.CloseParenToken] = true; + noRegexTable[SyntaxKind.CloseBracketToken] = true; + noRegexTable[SyntaxKind.CloseBraceToken] = true; + noRegexTable[SyntaxKind.TrueKeyword] = true; + noRegexTable[SyntaxKind.FalseKeyword] = true; + + function isAccessibilityModifier(kind: SyntaxKind) { + switch (kind) { + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + return true; + } + + return false; + } + + /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ + function canFollow(keyword1: SyntaxKind, keyword2: SyntaxKind) { + if (isAccessibilityModifier(keyword1)) { + if (keyword2 === SyntaxKind.GetKeyword || + keyword2 === SyntaxKind.SetKeyword || + keyword2 === SyntaxKind.ConstructorKeyword || + keyword2 === SyntaxKind.StaticKeyword) { + + // Allow things like "public get", "public constructor" and "public static". + // These are all legal. + return true; + } + + // Any other keyword following "public" is actually an identifier an not a real + // keyword. + return false; + } + + // Assume any other keyword combination is legal. This can be refined in the future + // if there are more cases we want the classifier to be better at. + return true; } function getClassificationsForLine(text: string, lexState: EndOfLineState): ClassificationResult { var offset = 0; var lastTokenOrCommentEnd = 0; + var token = SyntaxKind.Unknown; var lastNonTriviaToken = SyntaxKind.Unknown; // If we're in a string literal, then prepend: "\ @@ -4648,8 +4680,6 @@ module ts { entries: [] }; - - var token = SyntaxKind.Unknown; do { token = scanner.scan(); @@ -4662,6 +4692,13 @@ module ts { else if (lastNonTriviaToken === SyntaxKind.DotToken && isKeyword(token)) { token = SyntaxKind.Identifier; } + else if (isKeyword(lastNonTriviaToken) && isKeyword(token) && !canFollow(lastNonTriviaToken, token)) { + // We have two keywords in a row. Only treat the second as a keyword if + // it's a sequence that could legally occur in the language. Otherwise + // treat it as an identifier. This way, if someone writes "private var" + // we recognize that 'var' is actually an identifier here. + token = SyntaxKind.Identifier; + } lastNonTriviaToken = token; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 9e68ef1a7aa..caa324fcc7b 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -50,34 +50,54 @@ module ts { return -1; } - /** Get a token that contains the position. This is guaranteed to return a token, the position can be in the - * leading trivia or within the token text. - */ - export function getTokenAtPosition(sourceFile: SourceFile, position: number) { - var current: Node = sourceFile; - outer: while (true) { - // find the child that has this - for (var i = 0, n = current.getChildCount(); i < n; i++) { - var child = current.getChildAt(i); - if (child.getFullStart() <= position && position < child.getEnd()) { - current = child; - continue outer; - } - } - return current; - } + /* Gets the token whose text has range [start, end) and + * position >= start and (position < end or (position === end && token is keyword or identifier)) + */ + export function getTouchingWord(sourceFile: SourceFile, position: number): Node { + return getTouchingToken(sourceFile, position, isWord); } - /** Get the token whose text contains the position, or the containing node. */ - export function getNodeAtPosition(sourceFile: SourceFile, position: number) { + /* Gets the token whose text has range [start, end) and position >= start + * and (position < end or (position === end && token is keyword or identifier or numeric\string litera)) + */ + export function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node { + return getTouchingToken(sourceFile, position, isPropertyName); + } + + /** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */ + export function getTouchingToken(sourceFile: SourceFile, position: number, includeItemAtEndPosition?: (n: Node) => boolean): Node { + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition); + } + + /** Returns a token if position is in [start-of-leading-trivia, end) */ + export function getTokenAtPosition(sourceFile: SourceFile, position: number): Node { + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined); + } + + /** Get the token whose text contains the position */ + function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includeItemAtEndPosition: (n: Node) => boolean): Node { var current: Node = sourceFile; outer: while (true) { - // find the child that has this - for (var i = 0, n = current.getChildCount(); i < n; i++) { + if (isToken(current)) { + // exit early + return current; + } + + // find the child that contains 'position' + for (var i = 0, n = current.getChildCount(sourceFile); i < n; i++) { var child = current.getChildAt(i); - if (child.getStart() <= position && position < child.getEnd()) { - current = child; - continue outer; + var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile); + if (start <= position) { + if (position < child.getEnd()) { + current = child; + continue outer; + } + else if (includeItemAtEndPosition && child.getEnd() === position) { + var previousToken = findPrecedingToken(position, sourceFile, child); + if (previousToken && includeItemAtEndPosition(previousToken)) { + return previousToken; + } + } } } return current; @@ -130,8 +150,8 @@ module ts { } } - export function findPrecedingToken(position: number, sourceFile: SourceFile): Node { - return find(sourceFile); + export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node): Node { + return find(startNode || sourceFile); function findRightmostToken(n: Node): Node { if (isToken(n)) { @@ -167,7 +187,7 @@ module ts { } } - Debug.assert(n.kind === SyntaxKind.SourceFile); + Debug.assert(startNode || n.kind === SyntaxKind.SourceFile); // Here we know that none of child token nodes embrace the position, // the only known case is when position is at the end of the file. @@ -205,4 +225,16 @@ module ts { function isToken(n: Node): boolean { return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken; } + + function isKeyword(n: Node): boolean { + return n.kind >= SyntaxKind.FirstKeyword && n.kind <= SyntaxKind.LastKeyword; + } + + function isWord(n: Node): boolean { + return n.kind === SyntaxKind.Identifier || isKeyword(n); + } + + function isPropertyName(n: Node): boolean { + return n.kind === SyntaxKind.StringLiteral || n.kind === SyntaxKind.NumericLiteral || isWord(n); + } } \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesIfElse5.ts b/tests/cases/fourslash/getOccurrencesIfElse5.ts new file mode 100644 index 00000000000..b0519630b7b --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesIfElse5.ts @@ -0,0 +1,42 @@ +/// + +////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*/ { } + +function verifyOccurencesAtMarker(marker: string, count: number) { + goTo.marker(marker); + verify.occurrencesAtPositionCount(count); +} + +verifyOccurencesAtMarker("1", 7); +verifyOccurencesAtMarker("2", 2); +verifyOccurencesAtMarker("3", 2); +verifyOccurencesAtMarker("4", 2); +verifyOccurencesAtMarker("5", 2); +verifyOccurencesAtMarker("6", 1); +verifyOccurencesAtMarker("7", 1); +verifyOccurencesAtMarker("8", 7); +verifyOccurencesAtMarker("9", 7); +verifyOccurencesAtMarker("10", 7); +verifyOccurencesAtMarker("11", 7); +verifyOccurencesAtMarker("12", 7); +verifyOccurencesAtMarker("13", 7); diff --git a/tests/cases/fourslash/getOccurrencesIfElseNegatives.ts b/tests/cases/fourslash/getOccurrencesIfElseNegatives.ts deleted file mode 100644 index 601eba63c64..00000000000 --- a/tests/cases/fourslash/getOccurrencesIfElseNegatives.ts +++ /dev/null @@ -1,29 +0,0 @@ -/// - -////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*/ { } - - -test.markers().forEach(m => { - goTo.position(m.position, m.fileName) - verify.occurrencesAtPositionCount(0); -}); diff --git a/tests/cases/fourslash/getOccurrencesLoopBreakContinue6.ts b/tests/cases/fourslash/getOccurrencesLoopBreakContinue6.ts new file mode 100644 index 00000000000..0127245dd50 --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesLoopBreakContinue6.ts @@ -0,0 +1,70 @@ +/// + +////var arr = [1, 2, 3, 4]; +////label1: for (var n in arr) { +//// break; +//// continue; +//// break label1; +//// continue label1; +//// +//// label2: for (var i = 0; i < arr[n]; i++) { +//// break label1; +//// continue label1; +//// +//// break; +//// continue; +//// break label2; +//// continue label2; +//// +//// function foo() { +//// label3: while (true) { +//// break; +//// continue; +//// break label3; +//// continue label3; +//// +//// // these cross function boundaries +//// br/*1*/eak label1; +//// cont/*2*/inue label1; +//// bre/*3*/ak label2; +//// c/*4*/ontinue label2; +//// +//// label4: do { +//// break; +//// continue; +//// break label4; +//// continue label4; +//// +//// break label3; +//// continue label3; +//// +//// switch (10) { +//// case 1: +//// case 2: +//// break; +//// break label4; +//// default: +//// continue; +//// } +//// +//// // these cross function boundaries +//// br/*5*/eak label1; +//// co/*6*/ntinue label1; +//// br/*7*/eak label2; +//// con/*8*/tinue label2; +//// () => { b/*9*/reak; } +//// } while (true) +//// } +//// } +//// } +////} +//// +////label5: while (true) break label5; +//// +////label7: while (true) co/*10*/ntinue label5; + +test.markers().forEach(m => { + goTo.position(m.position); + + verify.occurrencesAtPositionCount(0); +}); diff --git a/tests/cases/fourslash/getOccurrencesReturnNegatives.ts b/tests/cases/fourslash/getOccurrencesReturn4.ts similarity index 52% rename from tests/cases/fourslash/getOccurrencesReturnNegatives.ts rename to tests/cases/fourslash/getOccurrencesReturn4.ts index 79cb3c659c6..4e25162f80f 100644 --- a/tests/cases/fourslash/getOccurrencesReturnNegatives.ts +++ b/tests/cases/fourslash/getOccurrencesReturn4.ts @@ -19,7 +19,15 @@ //// return/*7*/ true; ////} -test.markers().forEach(m => { - goTo.position(m.position, m.fileName) - verify.occurrencesAtPositionCount(0); -}); \ No newline at end of file +function verifyOccurencesAtMarker(marker: string, count: number) { + goTo.marker(marker); + verify.occurrencesAtPositionCount(count); +} + +verifyOccurencesAtMarker("1", 4); +verifyOccurencesAtMarker("2", 4); +verifyOccurencesAtMarker("3", 4); +verifyOccurencesAtMarker("4", 4); +verifyOccurencesAtMarker("5", 1); +verifyOccurencesAtMarker("6", 3); +verifyOccurencesAtMarker("7", 3); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts b/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts new file mode 100644 index 00000000000..162c2e1a94f --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts @@ -0,0 +1,40 @@ +/// + +////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*/: +////} + +function verifyOccurencesAtMarker(marker: string, count: number) { + goTo.marker(marker); + verify.occurrencesAtPositionCount(count); +} + +verifyOccurencesAtMarker("1", 9); +verifyOccurencesAtMarker("2", 9); +verifyOccurencesAtMarker("3", 9); +verifyOccurencesAtMarker("4", 9); +verifyOccurencesAtMarker("5", 9); +verifyOccurencesAtMarker("6", 6); +verifyOccurencesAtMarker("7", 6); +verifyOccurencesAtMarker("8", 6); +verifyOccurencesAtMarker("9", 6); +verifyOccurencesAtMarker("10", 6); +verifyOccurencesAtMarker("11", 9); +verifyOccurencesAtMarker("12", 9); +verifyOccurencesAtMarker("13", 9); +verifyOccurencesAtMarker("14", 0); + diff --git a/tests/cases/fourslash/getOccurrencesSwitchCaseDefaultNegatives.ts b/tests/cases/fourslash/getOccurrencesSwitchCaseDefaultNegatives.ts deleted file mode 100644 index cfb70b0c11a..00000000000 --- a/tests/cases/fourslash/getOccurrencesSwitchCaseDefaultNegatives.ts +++ /dev/null @@ -1,25 +0,0 @@ -/// - -////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); -} diff --git a/tests/cases/fourslash/getOccurrencesThisNegatives.ts b/tests/cases/fourslash/getOccurrencesThis6.ts similarity index 85% rename from tests/cases/fourslash/getOccurrencesThisNegatives.ts rename to tests/cases/fourslash/getOccurrencesThis6.ts index 95c676e0add..6ff779c0b46 100644 --- a/tests/cases/fourslash/getOccurrencesThisNegatives.ts +++ b/tests/cases/fourslash/getOccurrencesThis6.ts @@ -142,8 +142,14 @@ ////} -test.markers().forEach(m => { - goTo.position(m.position, m.fileName) +function verifyOccurencesAtMarker(marker: string, count: number) { + goTo.marker(marker); + verify.occurrencesAtPositionCount(count); +} - verify.occurrencesAtPositionCount(0); -}); \ No newline at end of file +verifyOccurencesAtMarker("1", 2); +verifyOccurencesAtMarker("2", 6); +verifyOccurencesAtMarker("3", 1); +verifyOccurencesAtMarker("4", 1); +verifyOccurencesAtMarker("5", 1); +verifyOccurencesAtMarker("6", 0); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts b/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts new file mode 100644 index 00000000000..dc6b0540312 --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts @@ -0,0 +1,30 @@ +/// + +////try/*1*/ { +//// try/*2*/ { +//// } +//// catch/*3*/ (x) { +//// } +//// +//// try/*4*/ { +//// } +//// finally/*5*/ {/*8*/ +//// } +////} +////catch/*6*/ (e) { +////} +////finally/*7*/ { +////} +function verifyOccurencesAtMarker(marker: string, count: number) { + goTo.marker(marker); + verify.occurrencesAtPositionCount(count); +} + +verifyOccurencesAtMarker("1", 3); +verifyOccurencesAtMarker("2", 2); +verifyOccurencesAtMarker("3", 2); +verifyOccurencesAtMarker("4", 2); +verifyOccurencesAtMarker("5", 2); +verifyOccurencesAtMarker("6", 3); +verifyOccurencesAtMarker("7", 3); +verifyOccurencesAtMarker("8", 0); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesTryCatchFinallyNegatives.ts b/tests/cases/fourslash/getOccurrencesTryCatchFinallyNegatives.ts deleted file mode 100644 index d5889ff84e9..00000000000 --- a/tests/cases/fourslash/getOccurrencesTryCatchFinallyNegatives.ts +++ /dev/null @@ -1,23 +0,0 @@ -/// - -////try/*1*/ { -//// try/*2*/ { -//// } -//// catch/*3*/ (x) { -//// } -//// -//// try/*4*/ { -//// } -//// finally/*5*/ {/*8*/ -//// } -////} -////catch/*6*/ (e) { -////} -////finally/*7*/ { -////} - - -for (var i = 1; i <= test.markers().length; i++) { - goTo.marker("" + i); - verify.occurrencesAtPositionCount(0); -} \ No newline at end of file diff --git a/tests/cases/fourslash/goToDefinitionSimple.ts b/tests/cases/fourslash/goToDefinitionSimple.ts index f931610aa2a..47c1909cf12 100644 --- a/tests/cases/fourslash/goToDefinitionSimple.ts +++ b/tests/cases/fourslash/goToDefinitionSimple.ts @@ -5,7 +5,12 @@ // @Filename: Consumption.ts //// var n = new /*1*/c(); +//// var n = new c/*3*/(); goTo.marker('1'); goTo.definition(); verify.caretAtMarker('2'); + +goTo.marker('3'); +goTo.definition(); +verify.caretAtMarker('2'); diff --git a/tests/cases/unittests/services/colorization.ts b/tests/cases/unittests/services/colorization.ts index d89cf702693..18b157f26b0 100644 --- a/tests/cases/unittests/services/colorization.ts +++ b/tests/cases/unittests/services/colorization.ts @@ -217,5 +217,19 @@ describe('Colorization', function () { keyword("var"), finalEndOfLineState(ts.EndOfLineState.Start)); }); + + it("classifies multiple keywords properly", function () { + test("public static", + ts.EndOfLineState.Start, + keyword("public"), + keyword("static"), + finalEndOfLineState(ts.EndOfLineState.Start)); + + test("public var", + ts.EndOfLineState.Start, + keyword("public"), + identifier("var"), + finalEndOfLineState(ts.EndOfLineState.Start)); + }); }); }); \ No newline at end of file