mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 20:14:01 -06:00
Merge pull request #1368 from Microsoft/parseErrors
Remove all function expression allocations when speculatively parsing or looking ahead.
This commit is contained in:
commit
824edead9e
@ -869,12 +869,6 @@ module ts {
|
||||
}
|
||||
};
|
||||
|
||||
const enum LookAheadMode {
|
||||
NotLookingAhead,
|
||||
NoErrorYet,
|
||||
Error
|
||||
}
|
||||
|
||||
export interface ReferencePathMatchResult {
|
||||
fileReference?: FileReference
|
||||
diagnosticMessage?: DiagnosticMessage
|
||||
@ -960,8 +954,6 @@ module ts {
|
||||
var nodeCount = 0;
|
||||
var lineStarts: number[];
|
||||
|
||||
var lookAheadMode = LookAheadMode.NotLookingAhead;
|
||||
|
||||
// Flags that dictate what parsing context we're in. For example:
|
||||
// Whether or not we are in strict parsing mode. All that changes in strict parsing mode is
|
||||
// that some tokens that would be considered identifiers may be considered keywords. When
|
||||
@ -1005,6 +997,10 @@ module ts {
|
||||
//
|
||||
// Getting this all correct is tricky and requires careful reading of the grammar to
|
||||
// understand when these values should be changed versus when they should be inherited.
|
||||
//
|
||||
// Note: it should not be necessary to save/restore these flags during speculative/lookahead
|
||||
// parsing. These context flags are naturally stored and restored through normal recursive
|
||||
// descent parsing and unwinding.
|
||||
var contextFlags: ParserContextFlags = 0;
|
||||
|
||||
function setContextFlag(val: Boolean, flag: ParserContextFlags) {
|
||||
@ -1125,10 +1121,6 @@ module ts {
|
||||
var diagnostic = createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2);
|
||||
sourceFile.parseDiagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
if (lookAheadMode === LookAheadMode.NoErrorYet) {
|
||||
lookAheadMode = LookAheadMode.Error;
|
||||
}
|
||||
}
|
||||
|
||||
function scanError(message: DiagnosticMessage) {
|
||||
@ -1168,57 +1160,50 @@ module ts {
|
||||
return token = scanner.reScanTemplateToken();
|
||||
}
|
||||
|
||||
function lookAheadHelper<T>(callback: () => T, alwaysResetState: boolean): T {
|
||||
function speculationHelper<T>(callback: () => T, isLookAhead: boolean): T {
|
||||
// Keep track of the state we'll need to rollback to if lookahead fails (or if the
|
||||
// caller asked us to always reset our state).
|
||||
var saveToken = token;
|
||||
var saveSyntacticErrorsLength = sourceFile.parseDiagnostics.length;
|
||||
var saveParseDiagnosticsLength = sourceFile.parseDiagnostics.length;
|
||||
|
||||
// Keep track of the current look ahead mode (this matters if we have nested
|
||||
// speculative parsing).
|
||||
var saveLookAheadMode = lookAheadMode;
|
||||
// Note: it is not actually necessary to save/restore the context falgs here. That's
|
||||
// because the saving/restorating of these flags happens naturally through the recursive
|
||||
// descent nature of our parser. However, we still store this here just so we can
|
||||
// assert that that invariant holds.
|
||||
var saveContextFlags = contextFlags;
|
||||
|
||||
// Mark that we're in speculative parsing and then try to parse out whatever code
|
||||
// the callback wants.
|
||||
lookAheadMode = LookAheadMode.NoErrorYet;
|
||||
var result = callback();
|
||||
// If we're only looking ahead, then tell the scanner to only lookahead as well.
|
||||
// Otherwise, if we're actually speculatively parsing, then tell the scanner to do the
|
||||
// same.
|
||||
var result = isLookAhead
|
||||
? scanner.lookAhead(callback)
|
||||
: scanner.tryScan(callback);
|
||||
|
||||
// If we switched from 1 to -1 then a parse error occurred during the callback.
|
||||
// If that's the case, then we want to act as if we never got any result at all.
|
||||
Debug.assert(lookAheadMode === LookAheadMode.Error || lookAheadMode === LookAheadMode.NoErrorYet);
|
||||
if (lookAheadMode === LookAheadMode.Error) {
|
||||
result = undefined;
|
||||
}
|
||||
Debug.assert(saveContextFlags === contextFlags);
|
||||
|
||||
// Now restore as appropriate.
|
||||
lookAheadMode = saveLookAheadMode;
|
||||
if (!result || alwaysResetState) {
|
||||
// If our callback returned something 'falsy' or we're just looking ahead,
|
||||
// then unconditionally restore us to where we were.
|
||||
if (!result || isLookAhead) {
|
||||
token = saveToken;
|
||||
sourceFile.parseDiagnostics.length = saveSyntacticErrorsLength;
|
||||
sourceFile.parseDiagnostics.length = saveParseDiagnosticsLength;
|
||||
}
|
||||
|
||||
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.
|
||||
function lookAhead<T>(callback: () => T): T {
|
||||
var result: T;
|
||||
scanner.tryScan(() => {
|
||||
result = lookAheadHelper(callback, /*alwaysResetState:*/ true);
|
||||
|
||||
// Returning false here indicates to the scanner that it should always jump
|
||||
// back to where it started. This makes sense as 'lookahead' acts as if
|
||||
// neither the parser nor scanner was affected by the operation.
|
||||
//
|
||||
// Note: the rewinding of the parser state is already handled in lookAheadHelper
|
||||
// (because we passed 'true' for alwaysResetState).
|
||||
return false;
|
||||
});
|
||||
|
||||
return result;
|
||||
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.
|
||||
function tryParse<T>(callback: () => T): T {
|
||||
return scanner.tryScan(() => lookAheadHelper(callback, /*alwaysResetState:*/ false));
|
||||
return speculationHelper(callback, /*isLookAhead:*/ false);
|
||||
}
|
||||
|
||||
function isIdentifier(): boolean {
|
||||
@ -1320,10 +1305,6 @@ module ts {
|
||||
parseErrorAtCurrentToken(diagnosticMessage, arg0);
|
||||
}
|
||||
|
||||
return createMissingNodeWithoutError(kind);
|
||||
}
|
||||
|
||||
function createMissingNodeWithoutError(kind: SyntaxKind) {
|
||||
var result = createNode(kind, scanner.getStartPos());
|
||||
(<Identifier>result).text = "";
|
||||
return finishNode(result);
|
||||
@ -1813,7 +1794,7 @@ module ts {
|
||||
var node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
|
||||
node.typeName = parseEntityName(/*allowReservedWords*/ false, Diagnostics.Type_expected);
|
||||
if (!scanner.hasPrecedingLineBreak() && token === SyntaxKind.LessThanToken) {
|
||||
node.typeArguments = parseTypeArguments();
|
||||
node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
|
||||
}
|
||||
return finishNode(node);
|
||||
}
|
||||
@ -1927,10 +1908,11 @@ module ts {
|
||||
function fillSignature(
|
||||
returnToken: SyntaxKind,
|
||||
yieldAndGeneratorParameterContext: boolean,
|
||||
requireCompleteParameterList: boolean,
|
||||
signature: SignatureDeclaration): void {
|
||||
var returnTokenRequired = returnToken === SyntaxKind.EqualsGreaterThanToken;
|
||||
signature.typeParameters = parseTypeParameters();
|
||||
signature.parameters = parseParameterList(yieldAndGeneratorParameterContext);
|
||||
signature.parameters = parseParameterList(yieldAndGeneratorParameterContext, requireCompleteParameterList);
|
||||
|
||||
if (returnTokenRequired) {
|
||||
parseExpected(returnToken);
|
||||
@ -1945,7 +1927,7 @@ module ts {
|
||||
// have 'Yield' And 'GeneratorParameter' not in sync. i.e. any production calling
|
||||
// this FormalParameters production either always sets both to true, or always sets
|
||||
// both to false. As such we only have a single parameter to represent both.
|
||||
function parseParameterList(yieldAndGeneratorParameterContext: boolean) {
|
||||
function parseParameterList(yieldAndGeneratorParameterContext: boolean, requireCompleteParameterList: boolean) {
|
||||
// FormalParameters[Yield,GeneratorParameter] :
|
||||
// ...
|
||||
//
|
||||
@ -1968,15 +1950,23 @@ module ts {
|
||||
setGeneratorParameterContext(yieldAndGeneratorParameterContext);
|
||||
|
||||
var result = parseDelimitedList(ParsingContext.Parameters, parseParameter);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
|
||||
setYieldContext(savedYieldContext);
|
||||
setGeneratorParameterContext(savedGeneratorParameterContext);
|
||||
|
||||
if (!parseExpected(SyntaxKind.CloseParenToken) && requireCompleteParameterList) {
|
||||
// Caller insisted that we had to end with a ) We didn't. So just return
|
||||
// undefined here.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return createMissingList<ParameterDeclaration>();
|
||||
// We didn't even have an open paren. If the caller requires a complete parameter list,
|
||||
// we definitely can't provide that. However, if they're ok with an incomplete one,
|
||||
// then just return an empty set of parameters.
|
||||
return requireCompleteParameterList ? undefined : createMissingList<ParameterDeclaration>();
|
||||
}
|
||||
|
||||
function parseSignatureMember(kind: SyntaxKind): SignatureDeclaration {
|
||||
@ -1984,7 +1974,7 @@ module ts {
|
||||
if (kind === SyntaxKind.ConstructSignature) {
|
||||
parseExpected(SyntaxKind.NewKeyword);
|
||||
}
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
|
||||
parseSemicolon();
|
||||
return finishNode(node);
|
||||
}
|
||||
@ -2073,7 +2063,7 @@ module ts {
|
||||
|
||||
// Method signatues don't exist in expression contexts. So they have neither
|
||||
// [Yield] nor [GeneratorParameter]
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, method);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, method);
|
||||
|
||||
parseSemicolon();
|
||||
return finishNode(method);
|
||||
@ -2174,7 +2164,7 @@ module ts {
|
||||
if (kind === SyntaxKind.ConstructorType) {
|
||||
parseExpected(SyntaxKind.NewKeyword);
|
||||
}
|
||||
fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext:*/ false, node);
|
||||
fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@ -2671,7 +2661,18 @@ module ts {
|
||||
function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): FunctionExpression {
|
||||
var node = <FunctionExpression>createNode(SyntaxKind.ArrowFunction);
|
||||
// Arrow functions are never generators.
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node);
|
||||
//
|
||||
// If we're speculatively parsing a signature for a parenthesized arrow function, then
|
||||
// we have to have a complete parameter list. Otherwise we might see something like
|
||||
// a => (b => c)
|
||||
// And think that "(b =>" was actually a parenthesized arrow function with a missing
|
||||
// close paren.
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ !allowAmbiguity, node);
|
||||
|
||||
// If we couldn't get parameters, we definitely could not parse out an arrow function.
|
||||
if (!node.parameters) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Parsing a signature isn't enough.
|
||||
// Parenthesized arrow signatures often look like other valid expressions.
|
||||
@ -3042,8 +3043,11 @@ module ts {
|
||||
expression = parseMemberExpressionRest(expression);
|
||||
|
||||
if (token === SyntaxKind.LessThanToken) {
|
||||
// Might be arithmetic, or it might be a type argument list.
|
||||
var typeArguments = tryParse(parseTypeArgumentsAndOpenParen);
|
||||
// See if this is the start of a generic invocation. If so, consume it and
|
||||
// keep checking for postfix expressions. Otherwise, it's just a '<' that's
|
||||
// part of an arithmetic expression. Break out so we consume it higher in the
|
||||
// stack.
|
||||
var typeArguments = tryParse(parseTypeArgumentsInExpression);
|
||||
if (!typeArguments) {
|
||||
return expression;
|
||||
}
|
||||
@ -3051,18 +3055,14 @@ module ts {
|
||||
var callExpr = <CallExpression>createNode(SyntaxKind.CallExpression, expression.pos);
|
||||
callExpr.expression = expression;
|
||||
callExpr.typeArguments = typeArguments;
|
||||
callExpr.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
callExpr.arguments = parseArgumentList();
|
||||
expression = finishNode(callExpr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token === SyntaxKind.OpenParenToken) {
|
||||
else if (token === SyntaxKind.OpenParenToken) {
|
||||
var callExpr = <CallExpression>createNode(SyntaxKind.CallExpression, expression.pos);
|
||||
callExpr.expression = expression;
|
||||
parseExpected(SyntaxKind.OpenParenToken);
|
||||
callExpr.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
callExpr.arguments = parseArgumentList();
|
||||
expression = finishNode(callExpr);
|
||||
continue;
|
||||
}
|
||||
@ -3071,33 +3071,64 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function parseTypeArgumentsAndOpenParen(): NodeArray<TypeNode> {
|
||||
var result = parseTypeArguments();
|
||||
function parseArgumentList() {
|
||||
parseExpected(SyntaxKind.OpenParenToken);
|
||||
var result = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseTypeArguments(): NodeArray<TypeNode> {
|
||||
// We pass parseSingleTypeArgument instead of parseType as the element parser
|
||||
// because parseSingleTypeArgument knows how to parse a missing type argument.
|
||||
// This is useful for signature help. parseType has the disadvantage that when
|
||||
// it sees a missing type, it changes the LookAheadMode to Error, and the result
|
||||
// is a broken binary expression, which breaks signature help.
|
||||
return parseBracketedList(ParsingContext.TypeArguments, parseSingleTypeArgument, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
|
||||
}
|
||||
|
||||
function parseSingleTypeArgument(): TypeNode {
|
||||
// Be resilient to something like: Foo<,,>();
|
||||
// We want to parse this out as a type argument list (esp. for signature help), and we
|
||||
// don't want to rollback just because we were missing a type arg. The grammar checker
|
||||
// will report the actual error later on.
|
||||
if (token === SyntaxKind.CommaToken) {
|
||||
var result = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
|
||||
result.typeName = <Identifier>createMissingNodeWithoutError(SyntaxKind.Identifier);
|
||||
return finishNode(result);
|
||||
function parseTypeArgumentsInExpression() {
|
||||
if (!parseOptional(SyntaxKind.LessThanToken)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return parseType();
|
||||
var typeArguments = parseDelimitedList(ParsingContext.TypeArguments, parseType);
|
||||
if (!parseExpected(SyntaxKind.GreaterThanToken)) {
|
||||
// If it doesn't have the closing > then it's definitely not an type argument list.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// If we have a '<', then only parse this as a arugment list if the type arguments
|
||||
// are complete and we have an open paren. if we don't, rewind and return nothing.
|
||||
return typeArguments && canFollowTypeArgumentsInExpression()
|
||||
? typeArguments
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function canFollowTypeArgumentsInExpression(): boolean {
|
||||
switch (token) {
|
||||
case SyntaxKind.OpenParenToken: // foo<x>(
|
||||
// this case are the only case where this token can legally follow a type argument
|
||||
// list. So we definitely want to treat this as a type arg list.
|
||||
|
||||
case SyntaxKind.DotToken: // foo<x>.
|
||||
case SyntaxKind.CloseParenToken: // foo<x>)
|
||||
case SyntaxKind.CloseBracketToken: // foo<x>]
|
||||
case SyntaxKind.ColonToken: // foo<x>:
|
||||
case SyntaxKind.SemicolonToken: // foo<x>;
|
||||
case SyntaxKind.CommaToken: // foo<x>,
|
||||
case SyntaxKind.QuestionToken: // foo<x>?
|
||||
case SyntaxKind.EqualsEqualsToken: // foo<x> ==
|
||||
case SyntaxKind.EqualsEqualsEqualsToken: // foo<x> ===
|
||||
case SyntaxKind.ExclamationEqualsToken: // foo<x> !=
|
||||
case SyntaxKind.ExclamationEqualsEqualsToken: // foo<x> !==
|
||||
case SyntaxKind.AmpersandAmpersandToken: // foo<x> &&
|
||||
case SyntaxKind.BarBarToken: // foo<x> ||
|
||||
case SyntaxKind.CaretToken: // foo<x> ^
|
||||
case SyntaxKind.AmpersandToken: // foo<x> &
|
||||
case SyntaxKind.BarToken: // foo<x> |
|
||||
case SyntaxKind.CloseBraceToken: // foo<x> }
|
||||
case SyntaxKind.EndOfFileToken: // foo<x>
|
||||
// these cases can't legally follow a type arg list. However, they're not legal
|
||||
// expressions either. The user is probably in the middle of a generic type. So
|
||||
// treat it as such.
|
||||
return true;
|
||||
|
||||
default:
|
||||
// Anything else treat as an expression.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function parsePrimaryExpression(): PrimaryExpression {
|
||||
@ -3224,7 +3255,7 @@ module ts {
|
||||
parseExpected(SyntaxKind.FunctionKeyword);
|
||||
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
|
||||
node.name = node.asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier();
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, node);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, /*requireCompleteParameterList:*/ false, node);
|
||||
node.body = parseFunctionBlock(/*allowYield:*/ !!node.asteriskToken, /* ignoreMissingOpenBrace */ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
@ -3237,14 +3268,11 @@ module ts {
|
||||
var node = <NewExpression>createNode(SyntaxKind.NewExpression);
|
||||
parseExpected(SyntaxKind.NewKeyword);
|
||||
node.expression = parseMemberExpressionOrHigher();
|
||||
if (token === SyntaxKind.LessThanToken) {
|
||||
node.typeArguments = tryParse(parseTypeArgumentsAndOpenParen);
|
||||
node.typeArguments = tryParse(parseTypeArgumentsInExpression);
|
||||
if (node.typeArguments || token === SyntaxKind.OpenParenToken) {
|
||||
node.arguments = parseArgumentList();
|
||||
}
|
||||
|
||||
if (node.typeArguments || parseOptional(SyntaxKind.OpenParenToken)) {
|
||||
node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
}
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@ -3699,7 +3727,7 @@ module ts {
|
||||
parseExpected(SyntaxKind.FunctionKeyword);
|
||||
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
|
||||
node.name = parseIdentifier();
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, node);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, /*requireCompleteParameterList:*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(!!node.asteriskToken);
|
||||
return finishNode(node);
|
||||
}
|
||||
@ -3708,7 +3736,7 @@ module ts {
|
||||
var node = <ConstructorDeclaration>createNode(SyntaxKind.Constructor, pos);
|
||||
setModifiers(node, modifiers);
|
||||
parseExpected(SyntaxKind.ConstructorKeyword);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
@ -3719,7 +3747,7 @@ module ts {
|
||||
method.asteriskToken = asteriskToken;
|
||||
method.name = name;
|
||||
method.questionToken = questionToken;
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, method);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, /*requireCompleteParameterList:*/ false, method);
|
||||
method.body = requireBlock ? parseFunctionBlock(!!asteriskToken, /*ignoreMissingOpenBrace:*/ false) : parseFunctionBlockOrSemicolon(!!asteriskToken);
|
||||
return finishNode(method);
|
||||
}
|
||||
@ -3754,7 +3782,7 @@ module ts {
|
||||
var node = <AccessorDeclaration>createNode(kind, fullStart);
|
||||
setModifiers(node, modifiers);
|
||||
node.name = parsePropertyName();
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false);
|
||||
return finishNode(node);
|
||||
}
|
||||
@ -4612,8 +4640,7 @@ module ts {
|
||||
|
||||
function checkTypeArguments(typeArguments: NodeArray<TypeNode>) {
|
||||
return checkForDisallowedTrailingComma(typeArguments) ||
|
||||
checkForAtLeastOneTypeArgument(typeArguments) ||
|
||||
checkForMissingTypeArgument(typeArguments);
|
||||
checkForAtLeastOneTypeArgument(typeArguments);
|
||||
}
|
||||
|
||||
function checkForOmittedArgument(arguments: NodeArray<Expression>) {
|
||||
@ -4627,17 +4654,6 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkForMissingTypeArgument(typeArguments: NodeArray<TypeNode>) {
|
||||
if (typeArguments) {
|
||||
for (var i = 0, n = typeArguments.length; i < n; i++) {
|
||||
var arg = typeArguments[i];
|
||||
if (arg.kind === SyntaxKind.TypeReference && getFullWidth((<TypeReferenceNode>arg).typeName) === 0) {
|
||||
return grammarErrorAtPos(arg.pos, 0, Diagnostics.Type_expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkForAtLeastOneTypeArgument(typeArguments: NodeArray<TypeNode>) {
|
||||
if (typeArguments && typeArguments.length === 0) {
|
||||
var start = typeArguments.pos - "<".length;
|
||||
|
||||
@ -29,6 +29,15 @@ module ts {
|
||||
scan(): SyntaxKind;
|
||||
setText(text: string): void;
|
||||
setTextPos(textPos: number): void;
|
||||
// Invokes the provided callback then unconditionally restores the scanner to the state it
|
||||
// was in immediately prior to invoking the callback. The result of invoking the callback
|
||||
// is returned from this function.
|
||||
lookAhead<T>(callback: () => T): T;
|
||||
|
||||
// Invokes the provided callback. If the callback returns something falsy, then it restores
|
||||
// the scanner to the state it was in immediately prior to invoking the callback. If the
|
||||
// callback returns something truthy, then the scanner state is not rolled back. The result
|
||||
// of invoking the callback is returned from this function.
|
||||
tryScan<T>(callback: () => T): T;
|
||||
}
|
||||
|
||||
@ -1174,7 +1183,7 @@ module ts {
|
||||
return token = scanTemplateAndSetTokenValue();
|
||||
}
|
||||
|
||||
function tryScan<T>(callback: () => T): T {
|
||||
function speculationHelper<T>(callback: () => T, isLookahead: boolean): T {
|
||||
var savePos = pos;
|
||||
var saveStartPos = startPos;
|
||||
var saveTokenPos = tokenPos;
|
||||
@ -1182,7 +1191,10 @@ module ts {
|
||||
var saveTokenValue = tokenValue;
|
||||
var savePrecedingLineBreak = precedingLineBreak;
|
||||
var result = callback();
|
||||
if (!result) {
|
||||
|
||||
// If our callback returned something 'falsy' or we're just looking ahead,
|
||||
// then unconditionally restore us to where we were.
|
||||
if (!result || isLookahead) {
|
||||
pos = savePos;
|
||||
startPos = saveStartPos;
|
||||
tokenPos = saveTokenPos;
|
||||
@ -1193,6 +1205,14 @@ module ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function lookAhead<T>(callback: () => T): T {
|
||||
return speculationHelper(callback, /*isLookahead:*/ true);
|
||||
}
|
||||
|
||||
function tryScan<T>(callback: () => T): T {
|
||||
return speculationHelper(callback, /*isLookahead:*/ false);
|
||||
}
|
||||
|
||||
function setText(newText: string) {
|
||||
text = newText || "";
|
||||
len = text.length;
|
||||
@ -1228,6 +1248,7 @@ module ts {
|
||||
setText,
|
||||
setTextPos,
|
||||
tryScan,
|
||||
lookAhead,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,12): error TS1005: ',' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,14): error TS1005: ';' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,10): error TS2304: Cannot find name 'a'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,14): error TS1110: Type expected.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts(1,13): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts (3 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction3.ts (2 errors) ====
|
||||
var v = (a): => {
|
||||
~
|
||||
!!! error TS1005: ',' expected.
|
||||
~~
|
||||
!!! error TS1005: ';' expected.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'a'.
|
||||
!!! error TS1110: Type expected.
|
||||
|
||||
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement.
|
||||
|
||||
};
|
||||
@ -1,19 +1,10 @@
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts(1,9): error TS1127: Invalid character.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts(1,1): error TS2304: Cannot find name 'Foo'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts(1,5): error TS2304: Cannot find name 'A'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts(1,7): error TS2304: Cannot find name 'B'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts(1,11): error TS2304: Cannot find name 'C'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts (5 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/TypeArgumentList1.ts (2 errors) ====
|
||||
Foo<A,B,\ C>(4, 5, 6);
|
||||
|
||||
!!! error TS1127: Invalid character.
|
||||
~~~
|
||||
!!! error TS2304: Cannot find name 'Foo'.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'A'.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'B'.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'C'.
|
||||
!!! error TS2304: Cannot find name 'Foo'.
|
||||
@ -1,19 +1,13 @@
|
||||
tests/cases/compiler/genericCallWithoutArgs.ts(4,17): error TS1109: Expression expected.
|
||||
tests/cases/compiler/genericCallWithoutArgs.ts(4,18): error TS1003: Identifier expected.
|
||||
tests/cases/compiler/genericCallWithoutArgs.ts(4,3): error TS2304: Cannot find name 'number'.
|
||||
tests/cases/compiler/genericCallWithoutArgs.ts(4,10): error TS2304: Cannot find name 'string'.
|
||||
tests/cases/compiler/genericCallWithoutArgs.ts(4,17): error TS1005: '(' expected.
|
||||
tests/cases/compiler/genericCallWithoutArgs.ts(4,18): error TS1005: ')' expected.
|
||||
|
||||
|
||||
==== tests/cases/compiler/genericCallWithoutArgs.ts (4 errors) ====
|
||||
==== tests/cases/compiler/genericCallWithoutArgs.ts (2 errors) ====
|
||||
function f<X, Y>(x: X, y: Y) {
|
||||
}
|
||||
|
||||
f<number,string>.
|
||||
~
|
||||
!!! error TS1109: Expression expected.
|
||||
!!! error TS1005: '(' expected.
|
||||
|
||||
!!! error TS1003: Identifier expected.
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'number'.
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'string'.
|
||||
!!! error TS1005: ')' expected.
|
||||
@ -1,24 +1,18 @@
|
||||
tests/cases/compiler/genericCallsWithoutParens.ts(2,18): error TS1109: Expression expected.
|
||||
tests/cases/compiler/genericCallsWithoutParens.ts(7,22): error TS1109: Expression expected.
|
||||
tests/cases/compiler/genericCallsWithoutParens.ts(2,11): error TS2304: Cannot find name 'number'.
|
||||
tests/cases/compiler/genericCallsWithoutParens.ts(7,15): error TS2304: Cannot find name 'number'.
|
||||
tests/cases/compiler/genericCallsWithoutParens.ts(2,18): error TS1005: '(' expected.
|
||||
tests/cases/compiler/genericCallsWithoutParens.ts(7,22): error TS1005: '(' expected.
|
||||
|
||||
|
||||
==== tests/cases/compiler/genericCallsWithoutParens.ts (4 errors) ====
|
||||
==== tests/cases/compiler/genericCallsWithoutParens.ts (2 errors) ====
|
||||
function f<T>() { }
|
||||
var r = f<number>; // parse error
|
||||
~
|
||||
!!! error TS1109: Expression expected.
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'number'.
|
||||
!!! error TS1005: '(' expected.
|
||||
|
||||
class C<T> {
|
||||
foo: T;
|
||||
}
|
||||
var c = new C<number>; // parse error
|
||||
~
|
||||
!!! error TS1109: Expression expected.
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'number'.
|
||||
!!! error TS1005: '(' expected.
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
tests/cases/compiler/genericConstructExpressionWithoutArgs.ts(10,1): error TS1109: Expression expected.
|
||||
tests/cases/compiler/genericConstructExpressionWithoutArgs.ts(9,16): error TS2304: Cannot find name 'number'.
|
||||
tests/cases/compiler/genericConstructExpressionWithoutArgs.ts(10,1): error TS1005: '(' expected.
|
||||
|
||||
|
||||
==== tests/cases/compiler/genericConstructExpressionWithoutArgs.ts (2 errors) ====
|
||||
==== tests/cases/compiler/genericConstructExpressionWithoutArgs.ts (1 errors) ====
|
||||
class B { }
|
||||
var b = new B; // no error
|
||||
|
||||
@ -12,8 +11,6 @@ tests/cases/compiler/genericConstructExpressionWithoutArgs.ts(9,16): error TS230
|
||||
|
||||
var c = new C // C<any>
|
||||
var c2 = new C<number> // error, type params are actually part of the arg list so you need both
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'number'.
|
||||
|
||||
|
||||
!!! error TS1109: Expression expected.
|
||||
!!! error TS1005: '(' expected.
|
||||
@ -1,8 +1,7 @@
|
||||
tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts(6,26): error TS1109: Expression expected.
|
||||
tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts(6,19): error TS2304: Cannot find name 'number'.
|
||||
tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts(6,26): error TS1005: '(' expected.
|
||||
|
||||
|
||||
==== tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts (2 errors) ====
|
||||
==== tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts (1 errors) ====
|
||||
class SS<T>{
|
||||
|
||||
}
|
||||
@ -10,9 +9,7 @@ tests/cases/compiler/genericObjectCreationWithoutTypeArgs.ts(6,19): error TS2304
|
||||
var x1 = new SS<number>(); // OK
|
||||
var x2 = new SS < number>; // Correctly give error
|
||||
~
|
||||
!!! error TS1109: Expression expected.
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'number'.
|
||||
!!! error TS1005: '(' expected.
|
||||
var x3 = new SS(); // OK
|
||||
var x4 = new SS; // Should be allowed, but currently give error ('supplied parameters do not match any signature of the call target')
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(27,16): error TS1005: ',' expected.
|
||||
tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(32,23): error TS1109: Expression expected.
|
||||
tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(32,16): error TS2304: Cannot find name 'string'.
|
||||
tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(32,23): error TS1005: '(' expected.
|
||||
tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(37,9): error TS2350: Only a void function can be called with the 'new' keyword.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts (4 errors) ====
|
||||
==== tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts (3 errors) ====
|
||||
|
||||
class C0 {
|
||||
|
||||
@ -40,9 +39,7 @@ tests/cases/conformance/expressions/newOperator/newOperatorErrorCases.ts(37,9):
|
||||
var c1: T<{}>;
|
||||
var c2 = new T<string>; // Parse error
|
||||
~
|
||||
!!! error TS1109: Expression expected.
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'string'.
|
||||
!!! error TS1005: '(' expected.
|
||||
|
||||
|
||||
// Construct expression of non-void returning function
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts(1,12): error TS1109: Expression expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts(1,12): error TS1005: '(' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts(1,1): error TS2346: Supplied parameters do not match any signature of call target.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts(1,10): error TS2304: Cannot find name 'A'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts (2 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/Generics/parserConstructorAmbiguity3.ts (3 errors) ====
|
||||
new Date<A>
|
||||
|
||||
!!! error TS1109: Expression expected.
|
||||
!!! error TS1005: '(' expected.
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2346: Supplied parameters do not match any signature of call target.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'A'.
|
||||
@ -1,14 +1,16 @@
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(3,7): error TS1109: Expression expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(4,7): error TS1109: Expression expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(3,7): error TS1005: '(' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(3,13): error TS1005: ')' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(4,7): error TS1005: '(' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(4,16): error TS1005: ')' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(1,1): error TS2304: Cannot find name 'Foo'.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(2,1): error TS2304: Cannot find name 'Foo'.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(3,1): error TS2304: Cannot find name 'Foo'.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(3,5): error TS2304: Cannot find name 'T'.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(3,8): error TS2304: Cannot find name 'Bar'.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(4,1): error TS2304: Cannot find name 'Foo'.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(4,5): error TS2304: Cannot find name 'T'.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts(4,8): error TS2304: Cannot find name 'Bar'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts (8 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression1.ts (10 errors) ====
|
||||
Foo<T>();
|
||||
~~~
|
||||
!!! error TS2304: Cannot find name 'Foo'.
|
||||
@ -17,16 +19,20 @@ tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessExpression
|
||||
!!! error TS2304: Cannot find name 'Foo'.
|
||||
Foo<T>.Bar();
|
||||
~
|
||||
!!! error TS1109: Expression expected.
|
||||
!!! error TS1005: '(' expected.
|
||||
~
|
||||
!!! error TS1005: ')' expected.
|
||||
~~~
|
||||
!!! error TS2304: Cannot find name 'Foo'.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'T'.
|
||||
~~~
|
||||
!!! error TS2304: Cannot find name 'Bar'.
|
||||
Foo<T>.Bar<T>();
|
||||
~
|
||||
!!! error TS1109: Expression expected.
|
||||
!!! error TS1005: '(' expected.
|
||||
~
|
||||
!!! error TS1005: ')' expected.
|
||||
~~~
|
||||
!!! error TS2304: Cannot find name 'Foo'.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'T'.
|
||||
~~~
|
||||
!!! error TS2304: Cannot find name 'Bar'.
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessOffOfGenericType1.ts(1,21): error TS1109: Expression expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessOffOfGenericType1.ts(1,21): error TS1005: '(' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessOffOfGenericType1.ts(1,33): error TS1005: ')' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessOffOfGenericType1.ts(1,9): error TS2304: Cannot find name 'List'.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessOffOfGenericType1.ts(1,14): error TS2304: Cannot find name 'number'.
|
||||
tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessOffOfGenericType1.ts(1,22): error TS2304: Cannot find name 'makeChild'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessOffOfGenericType1.ts (3 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/Generics/parserMemberAccessOffOfGenericType1.ts (4 errors) ====
|
||||
var v = List<number>.makeChild();
|
||||
~
|
||||
!!! error TS1109: Expression expected.
|
||||
!!! error TS1005: '(' expected.
|
||||
~
|
||||
!!! error TS1005: ')' expected.
|
||||
~~~~
|
||||
!!! error TS2304: Cannot find name 'List'.
|
||||
~~~~~~
|
||||
!!! error TS2304: Cannot find name 'number'.
|
||||
~~~~~~~~~
|
||||
!!! error TS2304: Cannot find name 'makeChild'.
|
||||
@ -1,15 +1,12 @@
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction3.ts(1,12): error TS1005: ',' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction3.ts(1,14): error TS1005: ';' expected.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction3.ts(1,10): error TS2304: Cannot find name 'a'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction3.ts(1,14): error TS1110: Type expected.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction3.ts(1,13): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction3.ts (3 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction3.ts (2 errors) ====
|
||||
var v = (a): => {
|
||||
~
|
||||
!!! error TS1005: ',' expected.
|
||||
~~
|
||||
!!! error TS1005: ';' expected.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'a'.
|
||||
!!! error TS1110: Type expected.
|
||||
|
||||
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement.
|
||||
|
||||
};
|
||||
@ -1,19 +1,10 @@
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/parserX_TypeArgumentList1.ts(1,9): error TS1127: Invalid character.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/parserX_TypeArgumentList1.ts(1,1): error TS2304: Cannot find name 'Foo'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/parserX_TypeArgumentList1.ts(1,5): error TS2304: Cannot find name 'A'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/parserX_TypeArgumentList1.ts(1,7): error TS2304: Cannot find name 'B'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/parserX_TypeArgumentList1.ts(1,11): error TS2304: Cannot find name 'C'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/parserX_TypeArgumentList1.ts (5 errors) ====
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/TypeArgumentLists/parserX_TypeArgumentList1.ts (2 errors) ====
|
||||
Foo<A,B,\ C>(4, 5, 6);
|
||||
|
||||
!!! error TS1127: Invalid character.
|
||||
~~~
|
||||
!!! error TS2304: Cannot find name 'Foo'.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'A'.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'B'.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'C'.
|
||||
!!! error TS2304: Cannot find name 'Foo'.
|
||||
Loading…
x
Reference in New Issue
Block a user