From af7df838253b7b8489fcd9137e8f4220786d2be5 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 8 Dec 2015 08:57:10 -0800 Subject: [PATCH] Parse type predicates only in return types. --- src/compiler/parser.ts | 53 +++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index e4262458d30..10d4a47c3df 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -908,17 +908,19 @@ namespace ts { return result; } - // Invokes the provided callback then unconditionally restores the parser to the state it - // was in immediately prior to invoking the callback. The result of invoking the callback - // is returned from this function. + /** Invokes the provided callback then unconditionally restores the parser to the state it + * was in immediately prior to invoking the callback. The result of invoking the callback + * is returned from this function. + */ function lookAhead(callback: () => T): T { return speculationHelper(callback, /*isLookAhead*/ true); } - // Invokes the provided callback. If the callback returns something falsy, then it restores - // the parser to the state it was in immediately prior to invoking the callback. If the - // callback returns something truthy, then the parser state is not rolled back. The result - // of invoking the callback is returned from this function. + /** Invokes the provided callback. If the callback returns something falsy, then it restores + * the parser to the state it was in immediately prior to invoking the callback. If the + * callback returns something truthy, then the parser state is not rolled back. The result + * of invoking the callback is returned from this function. + */ function tryParse(callback: () => T): T { return speculationHelper(callback, /*isLookAhead*/ false); } @@ -1960,15 +1962,8 @@ namespace ts { // TYPES - function parseTypeReferenceOrTypePredicate(): TypeReferenceNode | TypePredicateNode { + function parseTypeReference(): TypeReferenceNode { const typeName = parseEntityName(/*allowReservedWords*/ false, Diagnostics.Type_expected); - if (typeName.kind === SyntaxKind.Identifier && token === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { - nextToken(); - const node = createNode(SyntaxKind.TypePredicate, typeName.pos); - node.parameterName = typeName; - node.type = parseType(); - return finishNode(node); - } const node = createNode(SyntaxKind.TypeReference, typeName.pos); node.typeName = typeName; if (!scanner.hasPrecedingLineBreak() && token === SyntaxKind.LessThanToken) { @@ -2100,10 +2095,10 @@ namespace ts { if (returnTokenRequired) { parseExpected(returnToken); - signature.type = parseType(); + signature.type = parseTypeOrTypePredicate(); } else if (parseOptional(returnToken)) { - signature.type = parseType(); + signature.type = parseTypeOrTypePredicate(); } } @@ -2419,7 +2414,7 @@ namespace ts { case SyntaxKind.SymbolKeyword: // If these are followed by a dot, then parse these out as a dotted type reference instead. const node = tryParse(parseKeywordAndNoDot); - return node || parseTypeReferenceOrTypePredicate(); + return node || parseTypeReference(); case SyntaxKind.StringLiteral: return parseStringLiteralTypeNode(); case SyntaxKind.VoidKeyword: @@ -2435,7 +2430,7 @@ namespace ts { case SyntaxKind.OpenParenToken: return parseParenthesizedType(); default: - return parseTypeReferenceOrTypePredicate(); + return parseTypeReference(); } } @@ -2541,6 +2536,26 @@ namespace ts { } return false; } + + function parseTypeOrTypePredicate(): TypeNode { + const typePredicateVariable = tryParse(() => { + const id = parseIdentifier(); + if (token === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { + nextToken(); + return id; + } + }); + const t = parseType(); + if(typePredicateVariable) { + const node = createNode(SyntaxKind.TypePredicate, typePredicateVariable.pos); + node.parameterName = typePredicateVariable; + node.type = t; + return finishNode(node); + } + else { + return t; + } + } function parseType(): TypeNode { // The rules about 'yield' only apply to actual code/expression contexts. They don't