Parse type predicates only in return types.

This commit is contained in:
Nathan Shively-Sanders
2015-12-08 08:57:10 -08:00
parent 64681394d8
commit af7df83825
+34 -19
View File
@@ -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<T>(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<T>(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 = <TypePredicateNode>createNode(SyntaxKind.TypePredicate, typeName.pos);
node.parameterName = <Identifier>typeName;
node.type = parseType();
return finishNode(node);
}
const node = <TypeReferenceNode>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 = <TypePredicateNode>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