From f8a4fb0a15959bb0bfa1e9617402173e76dc4329 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 19:19:50 -0800 Subject: [PATCH 01/10] Put semantically relevant tokens in the tree. --- src/compiler/checker.ts | 14 +++++++------- src/compiler/emitter.ts | 2 +- src/compiler/parser.ts | 19 ++++++++++--------- src/compiler/types.ts | 2 +- src/services/breakpoints.ts | 2 +- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a663b03884431..2f765e556cb15 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1437,7 +1437,7 @@ module ts { } function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) { - if (getDeclarationFlagsFromSymbol(p) & NodeFlags.Rest) { + if (hasDotDotDotToken(p.valueDeclaration)) { writePunctuation(writer, SyntaxKind.DotDotDotToken); } appendSymbolNameOnly(p, writer); @@ -1711,7 +1711,7 @@ module ts { } // Rest parameters default to type any[], other parameters default to type any - var type = declaration.flags & NodeFlags.Rest ? createArrayType(anyType) : anyType; + var type = hasDotDotDotToken(declaration) ? createArrayType(anyType) : anyType; checkImplicitAny(type); return type; @@ -1733,9 +1733,9 @@ module ts { var diagnostic = Diagnostics.Member_0_implicitly_has_an_1_type; break; case SyntaxKind.Parameter: - var diagnostic = declaration.flags & NodeFlags.Rest ? - Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : - Diagnostics.Parameter_0_implicitly_has_an_1_type; + var diagnostic = hasDotDotDotToken(declaration) + ? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type + : Diagnostics.Parameter_0_implicitly_has_an_1_type; break; default: var diagnostic = Diagnostics.Variable_0_implicitly_has_an_1_type; @@ -2527,7 +2527,7 @@ module ts { hasStringLiterals = true; } if (minArgumentCount < 0) { - if (param.initializer || param.flags & (NodeFlags.QuestionMark | NodeFlags.Rest)) { + if (param.initializer || param.flags & NodeFlags.QuestionMark || param.dotDotDotToken) { minArgumentCount = i; } } @@ -6673,7 +6673,7 @@ module ts { !(parameterDeclaration.parent.kind === SyntaxKind.Constructor && (parameterDeclaration.parent).body)) { error(parameterDeclaration, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); } - if (parameterDeclaration.flags & NodeFlags.Rest) { + if (parameterDeclaration.dotDotDotToken) { if (!isArrayType(getTypeOfSymbol(parameterDeclaration.symbol))) { error(parameterDeclaration, Diagnostics.A_rest_parameter_must_be_of_an_array_type); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index fab0433890a9c..75454aa980778 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1252,7 +1252,7 @@ module ts { function emitParameterDeclaration(node: ParameterDeclaration) { increaseIndent(); emitJsDocComments(node); - if (node.flags & NodeFlags.Rest) { + if (node.dotDotDotToken) { write("..."); } writeTextOfNode(currentSourceFile, node.name); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 687eab878f36e..733c28d267ed6 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -608,8 +608,12 @@ module ts { return node.kind === SyntaxKind.ImportDeclaration && (node).moduleReference.kind !== SyntaxKind.ExternalModuleReference; } + export function hasDotDotDotToken(node: Node) { + return node && node.kind === SyntaxKind.Parameter && (node).dotDotDotToken !== undefined; + } + export function hasRestParameters(s: SignatureDeclaration): boolean { - return s.parameters.length > 0 && (s.parameters[s.parameters.length - 1].flags & NodeFlags.Rest) !== 0; + return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined; } export function isLiteralKind(kind: SyntaxKind): boolean { @@ -1812,11 +1816,8 @@ module ts { function parseParameter(): ParameterDeclaration { var node = createNode(SyntaxKind.Parameter); - var modifiers = parseModifiers(); - setModifiers(node, modifiers); - if (parseOptional(SyntaxKind.DotDotDotToken)) { - node.flags |= NodeFlags.Rest; - } + setModifiers(node, parseModifiers()); + node.dotDotDotToken = token === SyntaxKind.DotDotDotToken ? parseTokenNode() : undefined; // SingleNameBinding[Yield,GeneratorParameter] : See 13.2.3 // [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt @@ -4803,7 +4804,7 @@ module ts { return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_exactly_one_parameter); } } - else if (parameter.flags & NodeFlags.Rest) { + else if (parameter.dotDotDotToken) { return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_cannot_have_a_rest_parameter); } else if (parameter.flags & NodeFlags.Modifier) { @@ -5160,7 +5161,7 @@ module ts { for (var i = 0; i < parameterCount; i++) { var parameter = parameters[i]; - if (parameter.flags & NodeFlags.Rest) { + if (parameter.dotDotDotToken) { if (i !== (parameterCount - 1)) { return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); } @@ -5298,7 +5299,7 @@ module ts { } else { var parameter = accessor.parameters[0]; - if (parameter.flags & NodeFlags.Rest) { + if (parameter.dotDotDotToken) { return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_rest_parameter); } else if (parameter.flags & NodeFlags.Modifier) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 277e2cce5ff3f..fba331fdd3ce7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -273,7 +273,6 @@ module ts { Export = 0x00000001, // Declarations Ambient = 0x00000002, // Declarations QuestionMark = 0x00000004, // Parameter/Property/Method - Rest = 0x00000008, // Parameter Public = 0x00000010, // Property/Method Private = 0x00000020, // Property/Method Protected = 0x00000040, // Property/Method @@ -369,6 +368,7 @@ module ts { } export interface ParameterDeclaration extends Declaration { + dotDotDotToken?: Node; name: Identifier; type?: TypeNode | StringLiteralExpression; initializer?: Expression; diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 6cf775487fa1d..eb9c88088aa67 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -297,7 +297,7 @@ module ts.BreakpointResolver { function canHaveSpanInParameterDeclaration(parameter: ParameterDeclaration): boolean { // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier - return !!parameter.initializer || !!(parameter.flags & NodeFlags.Rest) || + return !!parameter.initializer || parameter.dotDotDotToken !== undefined || !!(parameter.flags & NodeFlags.Public) || !!(parameter.flags & NodeFlags.Private); } From 8ad4a0a5b873c4b7705e926595775bac0cce3ea9 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 20:45:29 -0800 Subject: [PATCH 02/10] Traverse into all nodes when walking the tree. --- src/compiler/parser.ts | 49 ++++++++++++++++++++++++++-------------- src/compiler/types.ts | 2 +- src/services/services.ts | 4 ++-- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 733c28d267ed6..8e6f0fda47946 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -216,13 +216,16 @@ module ts { return child((node).name) || child((node).constraint); case SyntaxKind.Parameter: - return child((node).name) || + return children(node.modifiers) || + child((node).dotDotDotToken) || + child((node).name) || child((node).type) || child((node).initializer); case SyntaxKind.Property: case SyntaxKind.PropertyAssignment: case SyntaxKind.ShorthandPropertyAssignment: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || child((node).type) || child((node).initializer); case SyntaxKind.FunctionType: @@ -230,7 +233,8 @@ module ts { case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: - return children((node).typeParameters) || + return children(node.modifiers) || + children((node).typeParameters) || children((node).parameters) || child((node).type); case SyntaxKind.Method: @@ -240,7 +244,8 @@ module ts { case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: case SyntaxKind.ArrowFunction: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || children((node).typeParameters) || children((node).parameters) || child((node).type) || @@ -308,7 +313,8 @@ module ts { case SyntaxKind.SourceFile: return children((node).statements); case SyntaxKind.VariableStatement: - return children((node).declarations); + return children(node.modifiers) || + children((node).declarations); case SyntaxKind.ExpressionStatement: return child((node).expression); case SyntaxKind.IfStatement: @@ -360,36 +366,44 @@ module ts { return child((node).variable) || children((node).statements); case SyntaxKind.VariableDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || child((node).type) || child((node).initializer); case SyntaxKind.ClassDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || children((node).typeParameters) || children((node).heritageClauses) || children((node).members); case SyntaxKind.InterfaceDeclaration: - return child((node).name) || - children((node).typeParameters) || - children((node).heritageClauses) || + return children(node.modifiers) || + child((node).name) || + children((node).typeParameters) || + children((node).heritageClauses) || children((node).members); case SyntaxKind.TypeAliasDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || child((node).type); case SyntaxKind.EnumDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || children((node).members); case SyntaxKind.EnumMember: return child((node).name) || child((node).initializer); case SyntaxKind.ModuleDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || child((node).body); case SyntaxKind.ImportDeclaration: - return child((node).name) || + return children(node.modifiers) || + child((node).name) || child((node).moduleReference); case SyntaxKind.ExportAssignment: - return child((node).exportName); + return children(node.modifiers) || + child((node).exportName); case SyntaxKind.TemplateExpression: return child((node).head) || children((node).templateSpans); case SyntaxKind.TemplateSpan: @@ -3759,7 +3773,7 @@ module ts { var flags = 0; var modifiers: ModifiersArray; while (true) { - var modifierStart = scanner.getTokenPos(); + var modifierStart = scanner.getStartPos(); var modifierKind = token; if (!parseAnyContextualModifier()) { @@ -3768,12 +3782,14 @@ module ts { if (!modifiers) { modifiers = []; + modifiers.pos = modifierStart; } flags |= modifierToFlag(modifierKind); modifiers.push(finishNode(createNode(modifierKind, modifierStart))); } if (modifiers) { modifiers.flags = flags; + modifiers.end = scanner.getStartPos(); } return modifiers; } @@ -4049,7 +4065,6 @@ module ts { switch (token) { case SyntaxKind.VarKeyword: case SyntaxKind.LetKeyword: - return parseVariableStatement(fullStart, modifiers); case SyntaxKind.ConstKeyword: return parseVariableStatement(fullStart, modifiers); case SyntaxKind.FunctionKeyword: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index fba331fdd3ce7..8436399f74f7d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -317,7 +317,7 @@ module ts { hasTrailingComma?: boolean; } - export interface ModifiersArray extends Array { + export interface ModifiersArray extends NodeArray { flags: number; } diff --git a/src/services/services.ts b/src/services/services.ts index 8bbc03aad6fc9..7e9e84cd7af48 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3836,8 +3836,8 @@ module ts { } forEach(nodes, node => { - if (node.flags & modifierFlag) { - forEach(node.getChildren(), child => pushKeywordIf(keywords, child, modifier)); + if (node.modifiers && node.flags & modifierFlag) { + forEach(node.modifiers, child => pushKeywordIf(keywords, child, modifier)); } }); From db89584a862bce6432ef7030ba79cf39732e2efe Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 22:03:41 -0800 Subject: [PATCH 03/10] Put semantically relevant tokens in the tree. --- src/compiler/checker.ts | 46 +++++--- src/compiler/emitter.ts | 6 +- src/compiler/parser.ts | 111 +++++++++--------- src/compiler/types.ts | 5 +- src/services/signatureHelp.ts | 2 +- .../accessorWithRestParam.errors.txt | 8 +- ...rowfunctionsOptionalArgsErrors1.errors.txt | 4 +- .../functionOverloadErrorsSyntax.errors.txt | 4 +- .../indexSignatureTypeCheck.errors.txt | 8 +- .../indexSignatureTypeCheck2.errors.txt | 8 +- .../reference/indexerAsOptional.errors.txt | 8 +- .../indexerSignatureWithRestParam.errors.txt | 8 +- .../parserIndexSignature1.errors.txt | 4 +- .../parserIndexSignature3.errors.txt | 4 +- ...rserMemberAccessorDeclaration17.errors.txt | 4 +- ...rserMemberAccessorDeclaration18.errors.txt | 4 +- .../reference/parserParameterList1.errors.txt | 4 +- .../parserParameterList11.errors.txt | 4 +- .../reference/parserParameterList9.errors.txt | 4 +- .../reference/restParamAsOptional.errors.txt | 4 +- .../reference/restParameterNotLast.errors.txt | 4 +- ...eterWithoutAnnotationIsAnyArray.errors.txt | 12 +- .../restParametersOfNonArrayTypes.errors.txt | 12 +- .../restParametersOfNonArrayTypes2.errors.txt | 24 ++-- ...ametersWithArrayTypeAnnotations.errors.txt | 24 ++-- 25 files changed, 175 insertions(+), 151 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2f765e556cb15..9fca10b734176 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -756,7 +756,7 @@ module ts { // // x is an optional parameter, but it is a required property. return propertySymbol.valueDeclaration && - propertySymbol.valueDeclaration.flags & NodeFlags.QuestionMark && + hasQuestionToken(propertySymbol.valueDeclaration) && propertySymbol.valueDeclaration.kind !== SyntaxKind.Parameter; } @@ -1441,7 +1441,7 @@ module ts { writePunctuation(writer, SyntaxKind.DotDotDotToken); } appendSymbolNameOnly(p, writer); - if (p.valueDeclaration.flags & NodeFlags.QuestionMark || (p.valueDeclaration).initializer) { + if (hasQuestionToken(p.valueDeclaration) || (p.valueDeclaration).initializer) { writePunctuation(writer, SyntaxKind.QuestionToken); } writePunctuation(writer, SyntaxKind.ColonToken); @@ -2527,7 +2527,7 @@ module ts { hasStringLiterals = true; } if (minArgumentCount < 0) { - if (param.initializer || param.flags & NodeFlags.QuestionMark || param.dotDotDotToken) { + if (param.initializer || param.questionToken || param.dotDotDotToken) { minArgumentCount = i; } } @@ -7020,20 +7020,23 @@ module ts { return; } + function getCanonicalOverload(overloads: Declaration[], implementation: FunctionLikeDeclaration) { + // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration + // Error on all deviations from this canonical set of flags + // The caveat is that if some overloads are defined in lib.d.ts, we don't want to + // report the errors on those. To achieve this, we will say that the implementation is + // the canonical signature only if it is in the same container as the first overload + var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent; + return implementationSharesContainerWithFirstOverload ? implementation : overloads[0]; + } + function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, flagsToCheck: NodeFlags, someOverloadFlags: NodeFlags, allOverloadFlags: NodeFlags): void { // Error if some overloads have a flag that is not shared by all overloads. To find the // deviations, we XOR someOverloadFlags with allOverloadFlags var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; if (someButNotAllOverloadFlags !== 0) { - // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration - // Error on all deviations from this canonical set of flags - // The caveat is that if some overloads are defined in lib.d.ts, we don't want to - // report the errors on those. To achieve this, we will say that the implementation is - // the canonical signature only if it is in the same container as the first overload - var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent; - var canonicalFlags = implementationSharesContainerWithFirstOverload - ? getEffectiveDeclarationFlags(implementation, flagsToCheck) - : getEffectiveDeclarationFlags(overloads[0], flagsToCheck); + var canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck); + forEach(overloads, o => { var deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags; if (deviation & NodeFlags.Export) { @@ -7045,16 +7048,27 @@ module ts { else if (deviation & (NodeFlags.Private | NodeFlags.Protected)) { error(o.name, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); } - else if (deviation & NodeFlags.QuestionMark) { + }); + } + } + + function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void { + if (someHaveQuestionToken !== allHaveQuestionToken) { + var canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation)); + forEach(overloads, o => { + var deviation = hasQuestionToken(o) !== canonicalHasQuestionToken; + if (deviation) { error(o.name, Diagnostics.Overload_signatures_must_all_be_optional_or_required); } }); } } - var flagsToCheck: NodeFlags = NodeFlags.Export | NodeFlags.Ambient | NodeFlags.Private | NodeFlags.Protected | NodeFlags.QuestionMark; + var flagsToCheck: NodeFlags = NodeFlags.Export | NodeFlags.Ambient | NodeFlags.Private | NodeFlags.Protected; var someNodeFlags: NodeFlags = 0; var allNodeFlags = flagsToCheck; + var someHaveQuestionToken = false; + var allHaveQuestionToken = true; var hasOverloads = false; var bodyDeclaration: FunctionLikeDeclaration; var lastSeenNonAmbientDeclaration: FunctionLikeDeclaration; @@ -7128,6 +7142,8 @@ module ts { var currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck); someNodeFlags |= currentNodeFlags; allNodeFlags &= currentNodeFlags; + someHaveQuestionToken = someHaveQuestionToken || hasQuestionToken(node); + allHaveQuestionToken = allHaveQuestionToken && hasQuestionToken(node); if (node.body && bodyDeclaration) { if (isConstructor) { @@ -7176,6 +7192,8 @@ module ts { if (hasOverloads) { checkFlagAgreementBetweenOverloads(declarations, bodyDeclaration, flagsToCheck, someNodeFlags, allNodeFlags); + checkQuestionTokenAgreementBetweenOverloads(declarations, bodyDeclaration, someHaveQuestionToken, allHaveQuestionToken); + if (bodyDeclaration) { var signatures = getSignaturesOfSymbol(symbol); var bodySignature = getSignatureFromDeclaration(bodyDeclaration); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 75454aa980778..ff52209ba69cf 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -943,7 +943,7 @@ module ts { if (node.kind !== SyntaxKind.VariableDeclaration || resolver.isDeclarationVisible(node)) { writeTextOfNode(currentSourceFile, node.name); // If optional property emit ? - if (node.kind === SyntaxKind.Property && (node.flags & NodeFlags.QuestionMark)) { + if (node.kind === SyntaxKind.Property && hasQuestionToken(node)) { write("?"); } if (node.kind === SyntaxKind.Property && node.parent.kind === SyntaxKind.TypeLiteral) { @@ -1124,7 +1124,7 @@ module ts { } else { writeTextOfNode(currentSourceFile, node.name); - if (node.flags & NodeFlags.QuestionMark) { + if (hasQuestionToken(node)) { write("?"); } } @@ -1256,7 +1256,7 @@ module ts { write("..."); } writeTextOfNode(currentSourceFile, node.name); - if (node.initializer || (node.flags & NodeFlags.QuestionMark)) { + if (node.initializer || hasQuestionToken(node)) { write("?"); } decreaseIndent(); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 8e6f0fda47946..97b973eb8d09e 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -219,6 +219,7 @@ module ts { return children(node.modifiers) || child((node).dotDotDotToken) || child((node).name) || + child((node).questionToken) || child((node).type) || child((node).initializer); case SyntaxKind.Property: @@ -226,6 +227,7 @@ module ts { case SyntaxKind.ShorthandPropertyAssignment: return children(node.modifiers) || child((node).name) || + child((node).questionToken) || child((node).type) || child((node).initializer); case SyntaxKind.FunctionType: @@ -246,6 +248,7 @@ module ts { case SyntaxKind.ArrowFunction: return children(node.modifiers) || child((node).name) || + child((node).questionToken) || children((node).typeParameters) || children((node).parameters) || child((node).type) || @@ -626,6 +629,23 @@ module ts { return node && node.kind === SyntaxKind.Parameter && (node).dotDotDotToken !== undefined; } + export function hasQuestionToken(node: Node) { + if (node) { + switch (node.kind) { + case SyntaxKind.Parameter: + return (node).questionToken !== undefined; + case SyntaxKind.Method: + return (node).questionToken !== undefined; + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.Property: + return (node).questionToken !== undefined; + } + } + + return false; + } + export function hasRestParameters(s: SignatureDeclaration): boolean { return s.parameters.length > 0 && s.parameters[s.parameters.length - 1].dotDotDotToken !== undefined; } @@ -1853,9 +1873,7 @@ module ts { nextToken(); } - if (parseOptional(SyntaxKind.QuestionToken)) { - node.flags |= NodeFlags.QuestionMark; - } + node.questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; node.type = parseParameterType(); node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) @@ -2020,15 +2038,12 @@ module ts { function parsePropertyOrMethod(): Declaration { var fullStart = scanner.getStartPos(); var name = parsePropertyName(); - var flags = 0; - if (parseOptional(SyntaxKind.QuestionToken)) { - flags = NodeFlags.QuestionMark; - } + var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { var method = createNode(SyntaxKind.Method, fullStart); method.name = name; - method.flags = flags; + method.questionToken = questionToken; // Method signatues don't exist in expression contexts. So they have neither // [Yield] nor [GeneratorParameter] @@ -2040,7 +2055,7 @@ module ts { else { var property = createNode(SyntaxKind.Property, fullStart); property.name = name; - property.flags = flags; + property.questionToken = questionToken; property.type = parseTypeAnnotation(); parseSemicolon(); return finishNode(property); @@ -3125,28 +3140,24 @@ module ts { return finishNode(node); } - var flags: NodeFlags = 0; - // Disallowing of optional property assignments happens in the grammar checker. - if (token === SyntaxKind.QuestionToken) { - flags |= NodeFlags.QuestionMark; - nextToken(); - } + var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; // Parse to check if it is short-hand property assignment or normal property assignment if ((token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken) && tokenIsIdentifier) { - node = createNode(SyntaxKind.ShorthandPropertyAssignment, nodePos); - node.name = propertyName; + var shorthandDeclaration = createNode(SyntaxKind.ShorthandPropertyAssignment, nodePos); + shorthandDeclaration.name = propertyName; + shorthandDeclaration.questionToken = questionToken; + return finishNode(shorthandDeclaration); } else { - node = createNode(SyntaxKind.PropertyAssignment, nodePos); - node.name = propertyName; + var propertyDeclaration = createNode(SyntaxKind.PropertyAssignment, nodePos); + propertyDeclaration.name = propertyName; + propertyDeclaration.questionToken = questionToken; parseExpected(SyntaxKind.ColonToken); - (node).initializer = allowInAnd(parseAssignmentExpressionOrHigher); + propertyDeclaration.initializer = allowInAnd(parseAssignmentExpressionOrHigher); + return finishNode(propertyDeclaration); } - - node.flags = flags; - return finishNode(node); } function parseObjectLiteralMember(): Declaration { @@ -3671,23 +3682,18 @@ module ts { } function parsePropertyMemberDeclaration(fullStart: number, modifiers: ModifiersArray): ClassElement { - var flags = modifiers ? modifiers.flags : 0; var asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); var name = parsePropertyName(); - if (parseOptional(SyntaxKind.QuestionToken)) { - // Note: this is not legal as per the grammar. But we allow it in the parser and - // report an error in the grammar checker. - flags |= NodeFlags.QuestionMark; - } + // Note: this is not legal as per the grammar. But we allow it in the parser and + // report an error in the grammar checker. + var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; if (asteriskToken || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { var method = createNode(SyntaxKind.Method, fullStart); setModifiers(method, modifiers); - if (flags) { - method.flags = flags; - } method.asteriskToken = asteriskToken; method.name = name; + method.questionToken = questionToken; fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, method); method.body = parseFunctionBlockOrSemicolon(!!asteriskToken); return finishNode(method); @@ -3695,10 +3701,8 @@ module ts { else { var property = createNode(SyntaxKind.Property, fullStart); setModifiers(property, modifiers); - if (flags) { - property.flags = flags; - } property.name = name; + property.questionToken = questionToken; property.type = parseTypeAnnotation(); property.initializer = allowInAnd(() => parseInitializer(/*inParameter*/ false)); parseSemicolon(); @@ -4820,13 +4824,13 @@ module ts { } } else if (parameter.dotDotDotToken) { - return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_cannot_have_a_rest_parameter); + return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.An_index_signature_cannot_have_a_rest_parameter); } else if (parameter.flags & NodeFlags.Modifier) { return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier); } - else if (parameter.flags & NodeFlags.QuestionMark) { - return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark); + else if (parameter.questionToken) { + return grammarErrorOnNode(parameter.questionToken, Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark); } else if (parameter.initializer) { return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_initializer); @@ -4878,7 +4882,7 @@ module ts { return true; } if (node.parent.kind === SyntaxKind.ClassDeclaration) { - if (checkForInvalidQuestionMark(node, Diagnostics.A_class_member_cannot_be_declared_optional)) { + if (checkForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional)) { return true; } // Technically, computed properties in ambient contexts is disallowed @@ -5178,21 +5182,21 @@ module ts { var parameter = parameters[i]; if (parameter.dotDotDotToken) { if (i !== (parameterCount - 1)) { - return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); + return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); } - if (parameter.flags & NodeFlags.QuestionMark) { - return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_be_optional); + if (parameter.questionToken) { + return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_rest_parameter_cannot_be_optional); } if (parameter.initializer) { return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_have_an_initializer); } } - else if (parameter.flags & NodeFlags.QuestionMark || parameter.initializer) { + else if (parameter.questionToken || parameter.initializer) { seenOptionalParameter = true; - if (parameter.flags & NodeFlags.QuestionMark && parameter.initializer) { + if (parameter.questionToken && parameter.initializer) { return grammarErrorOnNode(parameter.name, Diagnostics.Parameter_cannot_have_question_mark_and_initializer); } } @@ -5226,7 +5230,7 @@ module ts { function checkProperty(node: PropertyDeclaration) { if (node.parent.kind === SyntaxKind.ClassDeclaration) { - if (checkForInvalidQuestionMark(node, Diagnostics.A_class_member_cannot_be_declared_optional) || + if (checkForInvalidQuestionMark(node, node.questionToken, Diagnostics.A_class_member_cannot_be_declared_optional) || checkForDisallowedComputedProperty(node.name, Diagnostics.Computed_property_names_are_not_allowed_in_class_property_declarations)) { return true; } @@ -5267,13 +5271,12 @@ module ts { } function checkPropertyAssignment(node: PropertyDeclaration) { - return checkForInvalidQuestionMark(node, Diagnostics.An_object_member_cannot_be_declared_optional); + return checkForInvalidQuestionMark(node, node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional); } - function checkForInvalidQuestionMark(node: Declaration, message: DiagnosticMessage) { - if (node.flags & NodeFlags.QuestionMark) { - var pos = skipTrivia(sourceText, node.name.end); - return grammarErrorAtPos(pos, "?".length, message); + function checkForInvalidQuestionMark(node: Declaration, questionToken: Node, message: DiagnosticMessage) { + if (questionToken) { + return grammarErrorOnNode(questionToken, message); } } @@ -5315,13 +5318,13 @@ module ts { else { var parameter = accessor.parameters[0]; if (parameter.dotDotDotToken) { - return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_rest_parameter); + return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_set_accessor_cannot_have_rest_parameter); } else if (parameter.flags & NodeFlags.Modifier) { return grammarErrorOnNode(accessor.name, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); } - else if (parameter.flags & NodeFlags.QuestionMark) { - return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter); + else if (parameter.questionToken) { + return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter); } else if (parameter.initializer) { return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer); @@ -5368,7 +5371,7 @@ module ts { } function checkShorthandPropertyAssignment(node: ShortHandPropertyDeclaration): boolean { - return checkForInvalidQuestionMark(node, Diagnostics.An_object_member_cannot_be_declared_optional); + return checkForInvalidQuestionMark(node, node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional); } function checkSwitchStatement(node: SwitchStatement) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8436399f74f7d..c2810e01acb07 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -272,7 +272,6 @@ module ts { export const enum NodeFlags { Export = 0x00000001, // Declarations Ambient = 0x00000002, // Declarations - QuestionMark = 0x00000004, // Parameter/Property/Method Public = 0x00000010, // Property/Method Private = 0x00000020, // Property/Method Protected = 0x00000040, // Property/Method @@ -370,11 +369,13 @@ module ts { export interface ParameterDeclaration extends Declaration { dotDotDotToken?: Node; name: Identifier; + questionToken?: Node; type?: TypeNode | StringLiteralExpression; initializer?: Expression; } export interface PropertyDeclaration extends Declaration, ClassElement { + questionToken?: Node; type?: TypeNode; initializer?: Expression; } @@ -384,6 +385,7 @@ module ts { export interface ShortHandPropertyDeclaration extends Declaration { name: Identifier; + questionToken?: Node; } /** @@ -398,6 +400,7 @@ module ts { _functionLikeDeclarationBrand: any; asteriskToken?: Node; + questionToken?: Node; body?: Block | Expression; } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index f3604b3dfdd43..93363b4676bd3 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -524,7 +524,7 @@ module ts.SignatureHelp { var displayParts = mapToDisplayParts(writer => typeInfoResolver.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation)); - var isOptional = !!(parameter.valueDeclaration.flags & NodeFlags.QuestionMark); + var isOptional = hasQuestionToken(parameter.valueDeclaration); return { name: parameter.name, diff --git a/tests/baselines/reference/accessorWithRestParam.errors.txt b/tests/baselines/reference/accessorWithRestParam.errors.txt index 6162d5a823840..c6f3ef70563c3 100644 --- a/tests/baselines/reference/accessorWithRestParam.errors.txt +++ b/tests/baselines/reference/accessorWithRestParam.errors.txt @@ -1,14 +1,14 @@ -tests/cases/compiler/accessorWithRestParam.ts(3,9): error TS1053: A 'set' accessor cannot have rest parameter. -tests/cases/compiler/accessorWithRestParam.ts(4,16): error TS1053: A 'set' accessor cannot have rest parameter. +tests/cases/compiler/accessorWithRestParam.ts(3,11): error TS1053: A 'set' accessor cannot have rest parameter. +tests/cases/compiler/accessorWithRestParam.ts(4,18): error TS1053: A 'set' accessor cannot have rest parameter. ==== tests/cases/compiler/accessorWithRestParam.ts (2 errors) ==== class C { set X(...v) { } - ~ + ~~~ !!! error TS1053: A 'set' accessor cannot have rest parameter. static set X(...v2) { } - ~ + ~~~ !!! error TS1053: A 'set' accessor cannot have rest parameter. } \ No newline at end of file diff --git a/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors1.errors.txt b/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors1.errors.txt index 309e731e54f85..5934ab52ccfeb 100644 --- a/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors1.errors.txt +++ b/tests/baselines/reference/fatarrowfunctionsOptionalArgsErrors1.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(1,9): error TS1016: A required parameter cannot follow an optional parameter. -tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(2,5): error TS1047: A rest parameter cannot be optional. +tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(2,8): error TS1047: A rest parameter cannot be optional. tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(4,5): error TS1048: A rest parameter cannot have an initializer. tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(7,12): error TS1016: A required parameter cannot follow an optional parameter. @@ -9,7 +9,7 @@ tests/cases/compiler/fatarrowfunctionsOptionalArgsErrors1.ts(7,12): error TS1016 ~~~~ !!! error TS1016: A required parameter cannot follow an optional parameter. (...arg?) => 102; - ~~~ + ~ !!! error TS1047: A rest parameter cannot be optional. (...arg) => 103; (...arg:number [] = []) => 104; diff --git a/tests/baselines/reference/functionOverloadErrorsSyntax.errors.txt b/tests/baselines/reference/functionOverloadErrorsSyntax.errors.txt index 98e7f4cd7146c..7c83759d02d41 100644 --- a/tests/baselines/reference/functionOverloadErrorsSyntax.errors.txt +++ b/tests/baselines/reference/functionOverloadErrorsSyntax.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts(2,27): error TS1016: A required parameter cannot follow an optional parameter. tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts(5,38): error TS1016: A required parameter cannot follow an optional parameter. -tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts(9,28): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts(9,25): error TS1014: A rest parameter must be last in a parameter list. ==== tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts (3 errors) ==== @@ -17,7 +17,7 @@ tests/cases/conformance/functions/functionOverloadErrorsSyntax.ts(9,28): error T //Function overload signature with rest param followed by non-optional parameter function fn5(x: string, ...y: any[], z: string); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. function fn5() { } \ No newline at end of file diff --git a/tests/baselines/reference/indexSignatureTypeCheck.errors.txt b/tests/baselines/reference/indexSignatureTypeCheck.errors.txt index 1cc69f6294b6a..8a020fde5c64b 100644 --- a/tests/baselines/reference/indexSignatureTypeCheck.errors.txt +++ b/tests/baselines/reference/indexSignatureTypeCheck.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/indexSignatureTypeCheck.ts(14,6): error TS1019: An index signature parameter cannot have a question mark. -tests/cases/compiler/indexSignatureTypeCheck.ts(15,9): error TS1017: An index signature cannot have a rest parameter. +tests/cases/compiler/indexSignatureTypeCheck.ts(14,8): error TS1019: An index signature parameter cannot have a question mark. +tests/cases/compiler/indexSignatureTypeCheck.ts(15,6): error TS1017: An index signature cannot have a rest parameter. tests/cases/compiler/indexSignatureTypeCheck.ts(16,6): error TS1096: An index signature must have exactly one parameter. tests/cases/compiler/indexSignatureTypeCheck.ts(17,6): error TS1096: An index signature must have exactly one parameter. @@ -19,10 +19,10 @@ tests/cases/compiler/indexSignatureTypeCheck.ts(17,6): error TS1096: An index si interface indexErrors { [p2?: string]; - ~~ + ~ !!! error TS1019: An index signature parameter cannot have a question mark. [...p3: any[]]; - ~~ + ~~~ !!! error TS1017: An index signature cannot have a rest parameter. [p4: string, p5?: string]; ~~ diff --git a/tests/baselines/reference/indexSignatureTypeCheck2.errors.txt b/tests/baselines/reference/indexSignatureTypeCheck2.errors.txt index 25e3ab942800d..0fd594268c5f9 100644 --- a/tests/baselines/reference/indexSignatureTypeCheck2.errors.txt +++ b/tests/baselines/reference/indexSignatureTypeCheck2.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/indexSignatureTypeCheck2.ts(10,6): error TS1019: An index signature parameter cannot have a question mark. -tests/cases/compiler/indexSignatureTypeCheck2.ts(11,9): error TS1017: An index signature cannot have a rest parameter. +tests/cases/compiler/indexSignatureTypeCheck2.ts(10,8): error TS1019: An index signature parameter cannot have a question mark. +tests/cases/compiler/indexSignatureTypeCheck2.ts(11,6): error TS1017: An index signature cannot have a rest parameter. tests/cases/compiler/indexSignatureTypeCheck2.ts(12,6): error TS1096: An index signature must have exactly one parameter. tests/cases/compiler/indexSignatureTypeCheck2.ts(13,6): error TS1096: An index signature must have exactly one parameter. @@ -15,10 +15,10 @@ tests/cases/compiler/indexSignatureTypeCheck2.ts(13,6): error TS1096: An index s interface indexErrors { [p2?: string]; - ~~ + ~ !!! error TS1019: An index signature parameter cannot have a question mark. [...p3: any[]]; - ~~ + ~~~ !!! error TS1017: An index signature cannot have a rest parameter. [p4: string, p5?: string]; ~~ diff --git a/tests/baselines/reference/indexerAsOptional.errors.txt b/tests/baselines/reference/indexerAsOptional.errors.txt index 101c03acccdc9..cfd2d08cef9ce 100644 --- a/tests/baselines/reference/indexerAsOptional.errors.txt +++ b/tests/baselines/reference/indexerAsOptional.errors.txt @@ -1,18 +1,18 @@ -tests/cases/compiler/indexerAsOptional.ts(3,6): error TS1019: An index signature parameter cannot have a question mark. -tests/cases/compiler/indexerAsOptional.ts(8,6): error TS1019: An index signature parameter cannot have a question mark. +tests/cases/compiler/indexerAsOptional.ts(3,9): error TS1019: An index signature parameter cannot have a question mark. +tests/cases/compiler/indexerAsOptional.ts(8,9): error TS1019: An index signature parameter cannot have a question mark. ==== tests/cases/compiler/indexerAsOptional.ts (2 errors) ==== interface indexSig { //Index signatures can't be optional [idx?: number]: any; //err - ~~~ + ~ !!! error TS1019: An index signature parameter cannot have a question mark. } class indexSig2 { //Index signatures can't be optional [idx?: number]: any //err - ~~~ + ~ !!! error TS1019: An index signature parameter cannot have a question mark. } \ No newline at end of file diff --git a/tests/baselines/reference/indexerSignatureWithRestParam.errors.txt b/tests/baselines/reference/indexerSignatureWithRestParam.errors.txt index 4743ed8e91ca5..08c658164167f 100644 --- a/tests/baselines/reference/indexerSignatureWithRestParam.errors.txt +++ b/tests/baselines/reference/indexerSignatureWithRestParam.errors.txt @@ -1,16 +1,16 @@ -tests/cases/compiler/indexerSignatureWithRestParam.ts(2,9): error TS1017: An index signature cannot have a rest parameter. -tests/cases/compiler/indexerSignatureWithRestParam.ts(6,9): error TS1017: An index signature cannot have a rest parameter. +tests/cases/compiler/indexerSignatureWithRestParam.ts(2,6): error TS1017: An index signature cannot have a rest parameter. +tests/cases/compiler/indexerSignatureWithRestParam.ts(6,6): error TS1017: An index signature cannot have a rest parameter. ==== tests/cases/compiler/indexerSignatureWithRestParam.ts (2 errors) ==== interface I { [...x]: string; - ~ + ~~~ !!! error TS1017: An index signature cannot have a rest parameter. } class C { [...x]: string - ~ + ~~~ !!! error TS1017: An index signature cannot have a rest parameter. } \ No newline at end of file diff --git a/tests/baselines/reference/parserIndexSignature1.errors.txt b/tests/baselines/reference/parserIndexSignature1.errors.txt index 74f5d0e09213e..cde7259c7bd58 100644 --- a/tests/baselines/reference/parserIndexSignature1.errors.txt +++ b/tests/baselines/reference/parserIndexSignature1.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature1.ts(2,7): error TS1017: An index signature cannot have a rest parameter. +tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature1.ts(2,4): error TS1017: An index signature cannot have a rest parameter. ==== tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature1.ts (1 errors) ==== interface I { [...a] - ~ + ~~~ !!! error TS1017: An index signature cannot have a rest parameter. } \ No newline at end of file diff --git a/tests/baselines/reference/parserIndexSignature3.errors.txt b/tests/baselines/reference/parserIndexSignature3.errors.txt index bc552fd6a1dad..27310e4d0a417 100644 --- a/tests/baselines/reference/parserIndexSignature3.errors.txt +++ b/tests/baselines/reference/parserIndexSignature3.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature3.ts(2,4): error TS1019: An index signature parameter cannot have a question mark. +tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature3.ts(2,5): error TS1019: An index signature parameter cannot have a question mark. ==== tests/cases/conformance/parser/ecmascript5/IndexSignatures/parserIndexSignature3.ts (1 errors) ==== interface I { [a?] - ~ + ~ !!! error TS1019: An index signature parameter cannot have a question mark. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration17.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration17.errors.txt index 6edb9b98b7b17..2d7f6e3be3093 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration17.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration17.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration17.ts(2,8): error TS1051: A 'set' accessor cannot have an optional parameter. +tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration17.ts(2,13): error TS1051: A 'set' accessor cannot have an optional parameter. ==== tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration17.ts (1 errors) ==== class C { set Foo(a?: number) { } - ~~~ + ~ !!! error TS1051: A 'set' accessor cannot have an optional parameter. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration18.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration18.errors.txt index 54d39a6d663df..8296a087bab48 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration18.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration18.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration18.ts(2,8): error TS1053: A 'set' accessor cannot have rest parameter. +tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration18.ts(2,12): error TS1053: A 'set' accessor cannot have rest parameter. ==== tests/cases/conformance/parser/ecmascript5/MemberAccessorDeclarations/parserMemberAccessorDeclaration18.ts (1 errors) ==== class C { set Foo(...a) { } - ~~~ + ~~~ !!! error TS1053: A 'set' accessor cannot have rest parameter. } \ No newline at end of file diff --git a/tests/baselines/reference/parserParameterList1.errors.txt b/tests/baselines/reference/parserParameterList1.errors.txt index 3b01ee02168ec..a7e9a533f6390 100644 --- a/tests/baselines/reference/parserParameterList1.errors.txt +++ b/tests/baselines/reference/parserParameterList1.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList1.ts(2,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList1.ts(2,6): error TS1014: A rest parameter must be last in a parameter list. ==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList1.ts (1 errors) ==== class C { F(...A, B) { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. } \ No newline at end of file diff --git a/tests/baselines/reference/parserParameterList11.errors.txt b/tests/baselines/reference/parserParameterList11.errors.txt index 1fcede6c3984c..2cb8def201d30 100644 --- a/tests/baselines/reference/parserParameterList11.errors.txt +++ b/tests/baselines/reference/parserParameterList11.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList11.ts(1,5): error TS1047: A rest parameter cannot be optional. +tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList11.ts(1,8): error TS1047: A rest parameter cannot be optional. ==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList11.ts (1 errors) ==== (...arg?) => 102; - ~~~ + ~ !!! error TS1047: A rest parameter cannot be optional. \ No newline at end of file diff --git a/tests/baselines/reference/parserParameterList9.errors.txt b/tests/baselines/reference/parserParameterList9.errors.txt index 2db96373cd046..5f670148faadd 100644 --- a/tests/baselines/reference/parserParameterList9.errors.txt +++ b/tests/baselines/reference/parserParameterList9.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList9.ts(2,11): error TS1047: A rest parameter cannot be optional. +tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList9.ts(2,14): error TS1047: A rest parameter cannot be optional. ==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList9.ts (1 errors) ==== class C { foo(...bar?) { } - ~~~ + ~ !!! error TS1047: A rest parameter cannot be optional. } \ No newline at end of file diff --git a/tests/baselines/reference/restParamAsOptional.errors.txt b/tests/baselines/reference/restParamAsOptional.errors.txt index ac061e5d98e0f..9ab684f09443e 100644 --- a/tests/baselines/reference/restParamAsOptional.errors.txt +++ b/tests/baselines/reference/restParamAsOptional.errors.txt @@ -1,10 +1,10 @@ -tests/cases/compiler/restParamAsOptional.ts(1,15): error TS1047: A rest parameter cannot be optional. +tests/cases/compiler/restParamAsOptional.ts(1,16): error TS1047: A rest parameter cannot be optional. tests/cases/compiler/restParamAsOptional.ts(2,16): error TS1048: A rest parameter cannot have an initializer. ==== tests/cases/compiler/restParamAsOptional.ts (2 errors) ==== function f(...x?) { } - ~ + ~ !!! error TS1047: A rest parameter cannot be optional. function f2(...x = []) { } ~ diff --git a/tests/baselines/reference/restParameterNotLast.errors.txt b/tests/baselines/reference/restParameterNotLast.errors.txt index a5b91d0579525..0d69ef154ba30 100644 --- a/tests/baselines/reference/restParameterNotLast.errors.txt +++ b/tests/baselines/reference/restParameterNotLast.errors.txt @@ -1,7 +1,7 @@ -tests/cases/compiler/restParameterNotLast.ts(1,15): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/compiler/restParameterNotLast.ts(1,12): error TS1014: A rest parameter must be last in a parameter list. ==== tests/cases/compiler/restParameterNotLast.ts (1 errors) ==== function f(...x, y) { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. \ No newline at end of file diff --git a/tests/baselines/reference/restParameterWithoutAnnotationIsAnyArray.errors.txt b/tests/baselines/reference/restParameterWithoutAnnotationIsAnyArray.errors.txt index e021204341e25..0177f1e9a1cc4 100644 --- a/tests/baselines/reference/restParameterWithoutAnnotationIsAnyArray.errors.txt +++ b/tests/baselines/reference/restParameterWithoutAnnotationIsAnyArray.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(5,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(13,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(23,24): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(5,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(13,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts(23,21): error TS1014: A rest parameter must be last in a parameter list. ==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWithoutAnnotationIsAnyArray.ts (3 errors) ==== @@ -9,7 +9,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWith function foo(...x) { } var f = function foo(...x) { } var f2 = (...x, ...y) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. class C { @@ -19,7 +19,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWith interface I { (...x); foo(...x, ...y); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. } @@ -31,7 +31,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParameterWith var b = { foo(...x) { }, a: function foo(...x, ...y) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. b: (...x) => { } } diff --git a/tests/baselines/reference/restParametersOfNonArrayTypes.errors.txt b/tests/baselines/reference/restParametersOfNonArrayTypes.errors.txt index 2c7db9973d94e..12cbd865d1c4a 100644 --- a/tests/baselines/reference/restParametersOfNonArrayTypes.errors.txt +++ b/tests/baselines/reference/restParametersOfNonArrayTypes.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(5,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(13,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(23,24): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(5,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(13,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(23,21): error TS1014: A rest parameter must be last in a parameter list. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(3,14): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(4,22): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes.ts(5,11): error TS2370: A rest parameter must be of an array type. @@ -27,7 +27,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. var f2 = (...x: Date, ...y: boolean) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -45,7 +45,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. foo(...x: number, ...y: number); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -67,7 +67,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. a: function foo(...x: number, ...y: Date) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. diff --git a/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt b/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt index 592993076fd81..eef052e5cdf68 100644 --- a/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt +++ b/tests/baselines/reference/restParametersOfNonArrayTypes2.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(17,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(27,24): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(36,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(44,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(54,24): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(17,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(27,21): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(36,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(44,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(54,21): error TS1014: A rest parameter must be last in a parameter list. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(7,14): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(8,22): error TS2370: A rest parameter must be of an array type. tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,11): error TS2370: A rest parameter must be of an array type. @@ -48,7 +48,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. var f2 = (...x: MyThing, ...y: MyThing) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -66,7 +66,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. foo(...x: MyThing, ...y: MyThing); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -88,7 +88,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. a: function foo(...x: MyThing, ...y: MyThing) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -109,7 +109,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. var f4 = (...x: MyThing2, ...y: MyThing2) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -127,7 +127,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. foo(...x: MyThing2, ...y: MyThing2); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. @@ -149,7 +149,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. a: function foo(...x: MyThing2, ...y: MyThing2) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2370: A rest parameter must be of an array type. diff --git a/tests/baselines/reference/restParametersWithArrayTypeAnnotations.errors.txt b/tests/baselines/reference/restParametersWithArrayTypeAnnotations.errors.txt index 65afe52efa173..06b2caefb9d7b 100644 --- a/tests/baselines/reference/restParametersWithArrayTypeAnnotations.errors.txt +++ b/tests/baselines/reference/restParametersWithArrayTypeAnnotations.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(5,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(13,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(23,24): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(32,14): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(40,12): error TS1014: A rest parameter must be last in a parameter list. -tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(50,24): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(5,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(13,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(23,21): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(32,11): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(40,9): error TS1014: A rest parameter must be last in a parameter list. +tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts(50,21): error TS1014: A rest parameter must be last in a parameter list. ==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWithArrayTypeAnnotations.ts (6 errors) ==== @@ -12,7 +12,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit function foo(...x: number[]) { } var f = function foo(...x: number[]) { } var f2 = (...x: number[], ...y: number[]) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. class C { @@ -22,7 +22,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit interface I { (...x: number[]); foo(...x: number[], ...y: number[]); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. } @@ -34,7 +34,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit var b = { foo(...x: number[]) { }, a: function foo(...x: number[], ...y: number[]) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. b: (...x: number[]) => { } } @@ -45,7 +45,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit function foo2(...x: Array) { } var f3 = function foo(...x: Array) { } var f4 = (...x: Array, ...y: Array) => { } - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. class C2 { @@ -55,7 +55,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit interface I2 { (...x: Array); foo(...x: Array, ...y: Array); - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. } @@ -67,7 +67,7 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersWit var b2 = { foo(...x: Array) { }, a: function foo(...x: Array, ...y: Array) { }, - ~ + ~~~ !!! error TS1014: A rest parameter must be last in a parameter list. b: (...x: Array) => { } } \ No newline at end of file From 2459632a6234d871ae0d34519a7345d5d95254cb Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 22:20:03 -0800 Subject: [PATCH 04/10] Simplifying the signature parsing code. --- src/compiler/parser.ts | 64 ++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 97b973eb8d09e..5809eb8d7716a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1894,22 +1894,17 @@ module ts { return parseInitializer(/*inParameter*/ true); } - function parseSignature(kind: SyntaxKind, returnToken: SyntaxKind, returnTokenRequired: boolean, yieldAndGeneratorParameterContext: boolean): ParsedSignature { + function parseSignature(yieldAndGeneratorParameterContext: boolean): ParsedSignature { var signature = {}; - fillSignature(kind, returnToken, returnTokenRequired, yieldAndGeneratorParameterContext, signature); + fillSignature(SyntaxKind.ColonToken, yieldAndGeneratorParameterContext, signature); return signature; } function fillSignature( - kind: SyntaxKind, returnToken: SyntaxKind, - returnTokenRequired: boolean, yieldAndGeneratorParameterContext: boolean, signature: ParsedSignature): void { - - if (kind === SyntaxKind.ConstructSignature) { - parseExpected(SyntaxKind.NewKeyword); - } + var returnTokenRequired = returnToken === SyntaxKind.EqualsGreaterThanToken; signature.typeParameters = parseTypeParameters(); signature.parameters = parseParameterList(yieldAndGeneratorParameterContext); @@ -1960,9 +1955,12 @@ module ts { return createMissingList(); } - function parseSignatureMember(kind: SyntaxKind, returnToken: SyntaxKind): SignatureDeclaration { + function parseSignatureMember(kind: SyntaxKind): SignatureDeclaration { var node = createNode(kind); - fillSignature(kind, returnToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ false, node); + if (kind === SyntaxKind.ConstructSignature) { + parseExpected(SyntaxKind.NewKeyword); + } + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node); parseSemicolon(); return finishNode(node); } @@ -2047,7 +2045,7 @@ module ts { // Method signatues don't exist in expression contexts. So they have neither // [Yield] nor [GeneratorParameter] - fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ false, method); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, method); parseSemicolon(); return finishNode(method); @@ -2069,8 +2067,12 @@ module ts { case SyntaxKind.OpenBracketToken: // Both for indexers and computed properties return true; default: - return isLiteralPropertyName() && lookAhead(() => nextToken() === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken || token === SyntaxKind.QuestionToken || - token === SyntaxKind.ColonToken || canParseSemicolon()); + return isLiteralPropertyName() && lookAhead(() => + nextToken() === SyntaxKind.OpenParenToken || + token === SyntaxKind.LessThanToken || + token === SyntaxKind.QuestionToken || + token === SyntaxKind.ColonToken || + canParseSemicolon()); } } @@ -2078,13 +2080,13 @@ module ts { switch (token) { case SyntaxKind.OpenParenToken: case SyntaxKind.LessThanToken: - return parseSignatureMember(SyntaxKind.CallSignature, SyntaxKind.ColonToken); + return parseSignatureMember(SyntaxKind.CallSignature); case SyntaxKind.OpenBracketToken: // Indexer or computed property return isIndexSignature() ? parseIndexSignatureDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined) : parsePropertyOrMethod(); case SyntaxKind.NewKeyword: if (lookAhead(() => nextToken() === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken)) { - return parseSignatureMember(SyntaxKind.ConstructSignature, SyntaxKind.ColonToken); + return parseSignatureMember(SyntaxKind.ConstructSignature); } case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: @@ -2098,11 +2100,11 @@ module ts { function parseTypeLiteral(): TypeLiteralNode { var node = createNode(SyntaxKind.TypeLiteral); - node.members = parseObjectType(); + node.members = parseObjectTypeMembers(); return finishNode(node); } - function parseObjectType(): NodeArray { + function parseObjectTypeMembers(): NodeArray { var members: NodeArray; if (parseExpected(SyntaxKind.OpenBraceToken)) { members = parseList(ParsingContext.TypeMembers, /*checkForStrictMode*/ false, parseTypeMember); @@ -2129,10 +2131,12 @@ module ts { return finishNode(node); } - function parseFunctionType(typeKind: SyntaxKind): FunctionOrConstructorTypeNode { - var node = createNode(typeKind); - fillSignature(typeKind === SyntaxKind.FunctionType ? SyntaxKind.CallSignature : SyntaxKind.ConstructSignature, - SyntaxKind.EqualsGreaterThanToken, /* returnTokenRequired */ true, /*yieldAndGeneratorParameterContext:*/ false, node); + function parseFunctionType(kind: SyntaxKind): FunctionOrConstructorTypeNode { + var node = createNode(kind); + if (kind === SyntaxKind.ConstructorType) { + parseExpected(SyntaxKind.NewKeyword); + } + fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext:*/ false, node); return finishNode(node); } @@ -2510,7 +2514,7 @@ module ts { if (triState === Tristate.True) { // Arrow function are never generators. - var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /*returnTokenRequired:*/ false, /*yieldAndGeneratorParameterContext:*/ false); + var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ false); // If we have an arrow, then try to parse the body. // Even if not, try to parse if we have an opening brace, just in case we're in an error state. @@ -2614,7 +2618,7 @@ module ts { function tryParseSignatureIfArrowOrBraceFollows(): ParsedSignature { return tryParse(() => { // Arrow functions are never generators. - var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ false); + var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ false); // Parsing a signature isn't enough. // Parenthesized arrow signatures often look like other valid expressions. @@ -3128,7 +3132,7 @@ module ts { if (asteriskToken || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { node = createNode(SyntaxKind.PropertyAssignment, nodePos); node.name = propertyName; - var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken); + var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ !!asteriskToken); var body = parseFunctionBlock(!!asteriskToken, /* ignoreMissingOpenBrace */ false); // do not propagate property name as name for function expression @@ -3192,7 +3196,7 @@ module ts { parseExpected(SyntaxKind.FunctionKeyword); var asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); var name = asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier(); - var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken); + var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ !!asteriskToken); var body = parseFunctionBlock(/*allowYield:*/ !!asteriskToken, /* ignoreMissingOpenBrace */ false); return makeFunctionExpression(SyntaxKind.FunctionExpression, pos, asteriskToken, name, sig, body); @@ -3667,7 +3671,7 @@ module ts { parseExpected(SyntaxKind.FunctionKeyword); node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); node.name = parseIdentifier(); - fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, node); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, node); node.body = parseFunctionBlockOrSemicolon(!!node.asteriskToken); return finishNode(node); } @@ -3676,7 +3680,7 @@ module ts { var node = createNode(SyntaxKind.Constructor, pos); setModifiers(node, modifiers); parseExpected(SyntaxKind.ConstructorKeyword); - fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ false, node); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node); node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false); return finishNode(node); } @@ -3694,7 +3698,7 @@ module ts { method.asteriskToken = asteriskToken; method.name = name; method.questionToken = questionToken; - fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, method); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, method); method.body = parseFunctionBlockOrSemicolon(!!asteriskToken); return finishNode(method); } @@ -3714,7 +3718,7 @@ module ts { var node = createNode(kind, fullStart); setModifiers(node, modifiers); node.name = parsePropertyName(); - fillSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false, /*yieldAndGeneratorParameterContext:*/ false, node); + fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node); node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false); return finishNode(node); } @@ -3893,7 +3897,7 @@ module ts { node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause:*/ false); - node.members = parseObjectType(); + node.members = parseObjectTypeMembers(); return finishNode(node); } From af62715e8dc372114ff43e99c6aa383c3156bf03 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 22:30:22 -0800 Subject: [PATCH 05/10] Use helper function. Rename some functions to be clearer. --- src/compiler/parser.ts | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5809eb8d7716a..6549b86122d94 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1851,7 +1851,7 @@ module ts { function parseParameter(): ParameterDeclaration { var node = createNode(SyntaxKind.Parameter); setModifiers(node, parseModifiers()); - node.dotDotDotToken = token === SyntaxKind.DotDotDotToken ? parseTokenNode() : undefined; + node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); // SingleNameBinding[Yield,GeneratorParameter] : See 13.2.3 // [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt @@ -1873,7 +1873,7 @@ module ts { nextToken(); } - node.questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; + node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken); node.type = parseParameterType(); node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) @@ -2036,7 +2036,7 @@ module ts { function parsePropertyOrMethod(): Declaration { var fullStart = scanner.getStartPos(); var name = parsePropertyName(); - var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; + var questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { var method = createNode(SyntaxKind.Method, fullStart); @@ -2123,7 +2123,7 @@ module ts { return finishNode(node); } - function parseParenType(): ParenthesizedTypeNode { + function parseParenthesizedType(): ParenthesizedTypeNode { var node = createNode(SyntaxKind.ParenthesizedType); parseExpected(SyntaxKind.OpenParenToken); node.type = parseType(); @@ -2131,7 +2131,7 @@ module ts { return finishNode(node); } - function parseFunctionType(kind: SyntaxKind): FunctionOrConstructorTypeNode { + function parseFunctionOrConstructorType(kind: SyntaxKind): FunctionOrConstructorTypeNode { var node = createNode(kind); if (kind === SyntaxKind.ConstructorType) { parseExpected(SyntaxKind.NewKeyword); @@ -2163,7 +2163,7 @@ module ts { case SyntaxKind.OpenBracketToken: return parseTupleType(); case SyntaxKind.OpenParenToken: - return parseParenType(); + return parseParenthesizedType(); default: return parseTypeReference(); } @@ -2194,7 +2194,7 @@ module ts { } } - function parsePrimaryType(): TypeNode { + function parseArrayTypeOrHigher(): TypeNode { var type = parseNonArrayType(); while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { parseExpected(SyntaxKind.CloseBracketToken); @@ -2205,13 +2205,13 @@ module ts { return type; } - function parseUnionType(): TypeNode { - var type = parsePrimaryType(); + function parseUnionTypeOrHigher(): TypeNode { + var type = parseArrayTypeOrHigher(); if (token === SyntaxKind.BarToken) { var types = >[type]; types.pos = type.pos; while (parseOptional(SyntaxKind.BarToken)) { - types.push(parsePrimaryType()); + types.push(parseArrayTypeOrHigher()); } types.end = getNodeEnd(); var node = createNode(SyntaxKind.UnionType, type.pos); @@ -2272,12 +2272,12 @@ module ts { function parseTypeWorker(): TypeNode { if (isStartOfFunctionType()) { - return parseFunctionType(SyntaxKind.FunctionType); + return parseFunctionOrConstructorType(SyntaxKind.FunctionType); } if (token === SyntaxKind.NewKeyword) { - return parseFunctionType(SyntaxKind.ConstructorType); + return parseFunctionOrConstructorType(SyntaxKind.ConstructorType); } - return parseUnionType(); + return parseUnionTypeOrHigher(); } function parseTypeAnnotation(): TypeNode { @@ -2486,9 +2486,8 @@ module ts { function parseSimpleArrowFunctionExpression(identifier: Identifier): Expression { Debug.assert(token === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); - parseExpected(SyntaxKind.EqualsGreaterThanToken); - var parameter = createNode(SyntaxKind.Parameter, identifier.pos); + parseExpected(SyntaxKind.EqualsGreaterThanToken); parameter.name = identifier; finishNode(parameter); @@ -2497,7 +2496,7 @@ module ts { parameters.pos = parameter.pos; parameters.end = parameter.end; - var signature = { parameters: parameters }; + var signature = { parameters: parameters }; return parseArrowExpressionTail(identifier.pos, signature); } @@ -3145,7 +3144,7 @@ module ts { } // Disallowing of optional property assignments happens in the grammar checker. - var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; + var questionToken = parseOptionalToken(SyntaxKind.QuestionToken); // Parse to check if it is short-hand property assignment or normal property assignment if ((token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken) && tokenIsIdentifier) { @@ -3691,7 +3690,7 @@ module ts { // Note: this is not legal as per the grammar. But we allow it in the parser and // report an error in the grammar checker. - var questionToken = token === SyntaxKind.QuestionToken ? parseTokenNode() : undefined; + var questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (asteriskToken || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { var method = createNode(SyntaxKind.Method, fullStart); setModifiers(method, modifiers); From b5c3cd8d4a73033d9dc7f575e41aeca5d9fa1f4d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 22:39:10 -0800 Subject: [PATCH 06/10] Simplify code. --- src/compiler/parser.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6549b86122d94..a89a8fd52fb99 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2763,9 +2763,8 @@ module ts { function parsePrefixUnaryExpression() { var node = createNode(SyntaxKind.PrefixUnaryExpression); - var operator = token; + node.operator = token; nextToken(); - node.operator = operator; node.operand = parseUnaryExpressionOrHigher(); return finishNode(node); } @@ -2859,13 +2858,9 @@ module ts { // the last two CallExpression productions. Or we have a MemberExpression which either // completes the LeftHandSideExpression, or starts the beginning of the first four // CallExpression productions. - var expression: MemberExpression; - if (token === SyntaxKind.SuperKeyword) { - expression = parseSuperExpression(); - } - else { - expression = parseMemberExpressionOrHigher(); - } + var expression = token === SyntaxKind.SuperKeyword + ? parseSuperExpression() + : parseMemberExpressionOrHigher(); // Now, we *may* be complete. However, we might have consumed the start of a // CallExpression. As such, we need to consume the rest of it here to be complete. From 44627f859f99c2b8b211a6871726bdab13d8af16 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 22:50:03 -0800 Subject: [PATCH 07/10] Simplify parsing code. --- src/compiler/checker.ts | 7 ++++--- src/compiler/emitter.ts | 2 +- src/compiler/parser.ts | 21 ++++++++++++--------- src/compiler/types.ts | 8 +++++++- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9fca10b734176..64ed5f25bcaca 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7743,13 +7743,14 @@ module ts { function checkSwitchStatement(node: SwitchStatement) { var expressionType = checkExpression(node.expression); forEach(node.clauses, clause => { - if (fullTypeCheck && clause.expression) { + if (fullTypeCheck && clause.kind === SyntaxKind.CaseClause) { + var caseClause = clause; // TypeScript 1.0 spec (April 2014):5.9 // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. - var caseType = checkExpression(clause.expression); + var caseType = checkExpression(caseClause.expression); if (!isTypeAssignableTo(expressionType, caseType)) { // check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails - checkTypeAssignableTo(caseType, expressionType, clause.expression, /*headMessage*/ undefined); + checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); } } forEach(clause.statements, checkSourceElement); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index ff52209ba69cf..b065287b7d24c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2624,7 +2624,7 @@ module ts { function emitCaseOrDefaultClause(node: CaseOrDefaultClause) { if (node.kind === SyntaxKind.CaseClause) { write("case "); - emit(node.expression); + emit((node).expression); write(":"); } else { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a89a8fd52fb99..a45de6309d477 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -353,9 +353,10 @@ module ts { return child((node).expression) || children((node).clauses); case SyntaxKind.CaseClause: + return child((node).expression) || + children((node).statements); case SyntaxKind.DefaultClause: - return child((node).expression) || - children((node).statements); + return children((node).statements); case SyntaxKind.LabeledStatement: return child((node).label) || child((node).statement); @@ -3215,7 +3216,11 @@ module ts { var node = createNode(SyntaxKind.NewExpression); parseExpected(SyntaxKind.NewKeyword); node.expression = parseMemberExpressionOrHigher(); - if (parseOptional(SyntaxKind.OpenParenToken) || (token === SyntaxKind.LessThanToken && (node.typeArguments = tryParse(parseTypeArgumentsAndOpenParen)))) { + if (token === SyntaxKind.LessThanToken) { + node.typeArguments = tryParse(parseTypeArgumentsAndOpenParen); + } + + if (node.typeArguments || parseOptional(SyntaxKind.OpenParenToken)) { node.arguments = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression); parseExpected(SyntaxKind.CloseParenToken); } @@ -3381,8 +3386,8 @@ module ts { return finishNode(node); } - function parseCaseClause(): CaseOrDefaultClause { - var node = createNode(SyntaxKind.CaseClause); + function parseCaseClause(): CaseClause { + var node = createNode(SyntaxKind.CaseClause); parseExpected(SyntaxKind.CaseKeyword); node.expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.ColonToken); @@ -3390,8 +3395,8 @@ module ts { return finishNode(node); } - function parseDefaultClause(): CaseOrDefaultClause { - var node = createNode(SyntaxKind.DefaultClause); + function parseDefaultClause(): DefaultClause { + var node = createNode(SyntaxKind.DefaultClause); parseExpected(SyntaxKind.DefaultKeyword); parseExpected(SyntaxKind.ColonToken); node.statements = parseList(ParsingContext.SwitchClauseStatements, /*checkForStrictMode*/ false, parseStatement); @@ -3409,9 +3414,7 @@ module ts { node.expression = allowInAnd(parseExpression); parseExpected(SyntaxKind.CloseParenToken); parseExpected(SyntaxKind.OpenBraceToken); - node.clauses = parseList(ParsingContext.SwitchClauses, /*checkForStrictMode*/ false, parseCaseOrDefaultClause); - parseExpected(SyntaxKind.CloseBraceToken); return finishNode(node); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c2810e01acb07..a042ceae14de5 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -671,11 +671,17 @@ module ts { clauses: NodeArray; } - export interface CaseOrDefaultClause extends Node { + export interface CaseClause extends Node { expression?: Expression; statements: NodeArray; } + export interface DefaultClause extends Node { + statements: NodeArray; + } + + export type CaseOrDefaultClause = CaseClause | DefaultClause; + export interface LabeledStatement extends Statement { label: Identifier; statement: Statement; From 03a2d0197bebac728f22f597e0f5c78a12331c48 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 23:17:34 -0800 Subject: [PATCH 08/10] Make 'CatchClause' have-a block, instead of be-a block. --- src/compiler/binder.ts | 10 ++--- src/compiler/checker.ts | 16 +++---- src/compiler/emitter.ts | 18 ++++---- src/compiler/parser.ts | 45 +++++++++---------- src/compiler/types.ts | 12 +++-- src/services/breakpoints.ts | 6 ++- src/services/formatting.ts | 6 +-- src/services/formatting/rules.ts | 5 +-- src/services/outliningElementsCollector.ts | 4 +- src/services/services.ts | 14 +++--- src/services/smartIndenter.ts | 4 +- .../sourceMapValidationStatements.js.map | 2 +- ...ourceMapValidationStatements.sourcemap.txt | 20 ++++----- .../sourceMapValidationTryCatchFinally.js.map | 2 +- ...MapValidationTryCatchFinally.sourcemap.txt | 22 ++++----- 15 files changed, 94 insertions(+), 92 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 469a794d13d56..a45561e7ed667 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -348,8 +348,8 @@ module ts { bindChildren(node, symbolKind, isBlockScopeContainer); } - function bindCatchVariableDeclaration(node: CatchBlock) { - var symbol = createSymbol(SymbolFlags.FunctionScopedVariable, node.variable.text || "__missing"); + function bindCatchVariableDeclaration(node: CatchClause) { + var symbol = createSymbol(SymbolFlags.FunctionScopedVariable, node.name.text || "__missing"); addDeclarationToSymbol(symbol, node, SymbolFlags.FunctionScopedVariable); var saveParent = parent; var savedBlockScopeContainer = blockScopeContainer; @@ -444,8 +444,8 @@ module ts { case SyntaxKind.ArrowFunction: bindAnonymousDeclaration(node, SymbolFlags.Function, "__function", /*isBlockScopeContainer*/ true); break; - case SyntaxKind.CatchBlock: - bindCatchVariableDeclaration(node); + case SyntaxKind.CatchClause: + bindCatchVariableDeclaration(node); break; case SyntaxKind.ClassDeclaration: bindDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes, /*isBlockScopeContainer*/ false); @@ -478,7 +478,7 @@ module ts { case SyntaxKind.Block: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: case SyntaxKind.ForStatement: case SyntaxKind.ForInStatement: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 64ed5f25bcaca..c6c58347b1901 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -415,8 +415,8 @@ module ts { break loop; } break; - case SyntaxKind.CatchBlock: - var id = (location).variable; + case SyntaxKind.CatchClause: + var id = (location).name; if (name === id.text) { result = location.symbol; break loop; @@ -1753,7 +1753,7 @@ module ts { } // Handle catch clause variables var declaration = symbol.valueDeclaration; - if (declaration.kind === SyntaxKind.CatchBlock) { + if (declaration.kind === SyntaxKind.CatchClause) { return links.type = anyType; } // Handle variable, parameter or property @@ -4375,7 +4375,7 @@ module ts { case SyntaxKind.ThrowStatement: case SyntaxKind.TryStatement: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: return forEachChild(node, isAssignedIn); } @@ -7767,7 +7767,7 @@ module ts { function checkTryStatement(node: TryStatement) { checkBlock(node.tryBlock); - if (node.catchBlock) checkBlock(node.catchBlock); + if (node.catchClause) checkBlock(node.catchClause.block); if (node.finallyBlock) checkBlock(node.finallyBlock); } @@ -8605,7 +8605,7 @@ module ts { case SyntaxKind.ThrowStatement: case SyntaxKind.TryStatement: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: case SyntaxKind.VariableDeclaration: case SyntaxKind.ClassDeclaration: @@ -8767,8 +8767,8 @@ module ts { copySymbol(location.symbol, meaning); } break; - case SyntaxKind.CatchBlock: - if ((location).variable.text) { + case SyntaxKind.CatchClause: + if ((location).name.text) { copySymbol(location.symbol, meaning); } break; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index b065287b7d24c..53914ac4c6295 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2142,8 +2142,8 @@ module ts { return false; case SyntaxKind.LabeledStatement: return (node.parent).label === node; - case SyntaxKind.CatchBlock: - return (node.parent).variable === node; + case SyntaxKind.CatchClause: + return (node.parent).name === node; } } @@ -2650,7 +2650,7 @@ module ts { function emitTryStatement(node: TryStatement) { write("try "); emit(node.tryBlock); - emit(node.catchBlock); + emit(node.catchClause); if (node.finallyBlock) { writeLine(); write("finally "); @@ -2658,15 +2658,15 @@ module ts { } } - function emitCatchBlock(node: CatchBlock) { + function emitCatchClause(node: CatchClause) { writeLine(); var endPos = emitToken(SyntaxKind.CatchKeyword, node.pos); write(" "); emitToken(SyntaxKind.OpenParenToken, endPos); - emit(node.variable); - emitToken(SyntaxKind.CloseParenToken, node.variable.end); + emit(node.name); + emitToken(SyntaxKind.CloseParenToken, node.name.end); write(" "); - emitBlock(node); + emitBlock(node.block); } function emitDebuggerStatement(node: Node) { @@ -3599,8 +3599,8 @@ module ts { return emitThrowStatement(node); case SyntaxKind.TryStatement: return emitTryStatement(node); - case SyntaxKind.CatchBlock: - return emitCatchBlock(node); + case SyntaxKind.CatchClause: + return emitCatchClause(node); case SyntaxKind.DebuggerStatement: return emitDebuggerStatement(node); case SyntaxKind.VariableDeclaration: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a45de6309d477..553d51b1bd2b2 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -364,11 +364,12 @@ module ts { return child((node).expression); case SyntaxKind.TryStatement: return child((node).tryBlock) || - child((node).catchBlock) || + child((node).catchClause) || child((node).finallyBlock); - case SyntaxKind.CatchBlock: - return child((node).variable) || - children((node).statements); + case SyntaxKind.CatchClause: + return child((node).name) || + child((node).type) || + child((node).block); case SyntaxKind.VariableDeclaration: return children(node.modifiers) || child((node).name) || @@ -445,7 +446,7 @@ module ts { case SyntaxKind.LabeledStatement: case SyntaxKind.TryStatement: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: return forEachChild(node, traverse); } @@ -733,8 +734,8 @@ module ts { return (parent).name === name; } - if (parent.kind === SyntaxKind.CatchBlock) { - return (parent).variable === name; + if (parent.kind === SyntaxKind.CatchClause) { + return (parent).name === name; } return false; @@ -3439,11 +3440,11 @@ module ts { function parseTryStatement(): TryStatement { var node = createNode(SyntaxKind.TryStatement); node.tryBlock = parseTokenAndBlock(SyntaxKind.TryKeyword); - node.catchBlock = token === SyntaxKind.CatchKeyword ? parseCatchBlock() : undefined; + node.catchClause = token === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined; // If we don't have a catch clause, then we must have a finally clause. Try to parse // one out no matter what. - node.finallyBlock = !node.catchBlock || token === SyntaxKind.FinallyKeyword + node.finallyBlock = !node.catchClause || token === SyntaxKind.FinallyKeyword ? parseTokenAndBlock(SyntaxKind.FinallyKeyword) : undefined; return finishNode(node); @@ -3459,19 +3460,15 @@ module ts { return result; } - function parseCatchBlock(): CatchBlock { - var pos = getNodePos(); + function parseCatchClause(): CatchClause { + var result = createNode(SyntaxKind.CatchClause); parseExpected(SyntaxKind.CatchKeyword); parseExpected(SyntaxKind.OpenParenToken); - var variable = parseIdentifier(); - var typeAnnotation = parseTypeAnnotation(); + result.name = parseIdentifier(); + result.type = parseTypeAnnotation(); parseExpected(SyntaxKind.CloseParenToken); - var result = parseBlock(SyntaxKind.CatchBlock, /* ignoreMissingOpenBrace */ false, /*checkForStrictMode*/ false); - result.pos = pos; - result.variable = variable; - result.type = typeAnnotation; - - return result; + result.block = parseBlock(SyntaxKind.Block, /* ignoreMissingOpenBrace */ false, /*checkForStrictMode*/ false); + return finishNode(result); } function parseDebuggerStatement(): Statement { @@ -4325,7 +4322,7 @@ module ts { case SyntaxKind.EnumDeclaration: return checkEnumDeclaration(node); case SyntaxKind.BinaryExpression: return checkBinaryExpression(node); - case SyntaxKind.CatchBlock: return checkCatchBlock(node); + case SyntaxKind.CatchClause: return checkCatchClause(node); case SyntaxKind.ClassDeclaration: return checkClassDeclaration(node); case SyntaxKind.ComputedPropertyName: return checkComputedPropertyName(node); case SyntaxKind.Constructor: return checkConstructor(node); @@ -4583,15 +4580,15 @@ module ts { } } - function checkCatchBlock(node: CatchBlock) { + function checkCatchClause(node: CatchClause) { if (node.type) { - var colonStart = skipTrivia(sourceText, node.variable.end); + var colonStart = skipTrivia(sourceText, node.name.end); return grammarErrorAtPos(colonStart, ":".length, Diagnostics.Catch_clause_parameter_cannot_have_a_type_annotation); } - if (node.parserContextFlags & ParserContextFlags.StrictMode && isEvalOrArgumentsIdentifier(node.variable)) { + if (node.parserContextFlags & ParserContextFlags.StrictMode && isEvalOrArgumentsIdentifier(node.name)) { // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the // Catch production is eval or arguments - return reportInvalidUseInStrictMode(node.variable); + return reportInvalidUseInStrictMode(node.name); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a042ceae14de5..d8cbf204ebc08 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -208,7 +208,6 @@ module ts { ThrowStatement, TryStatement, TryBlock, - CatchBlock, FinallyBlock, DebuggerStatement, VariableDeclaration, @@ -222,12 +221,16 @@ module ts { ModuleBlock, ImportDeclaration, ExportAssignment, + // Module references ExternalModuleReference, + // Clauses CaseClause, DefaultClause, HeritageClause, + CatchClause, + // Property assignments PropertyAssignment, ShorthandPropertyAssignment, @@ -693,13 +696,14 @@ module ts { export interface TryStatement extends Statement { tryBlock: Block; - catchBlock?: CatchBlock; + catchClause?: CatchClause; finallyBlock?: Block; } - export interface CatchBlock extends Block, Declaration { - variable: Identifier; + export interface CatchClause extends Declaration { + name: Identifier; type?: TypeNode; + block: Block; } export interface ModuleElement extends Node { diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index eb9c88088aa67..a67a89dd82fa4 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -106,11 +106,13 @@ module ts.BreakpointResolver { case SyntaxKind.Block: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: return spanInBlock(node); + case SyntaxKind.CatchClause: + return spanInBlock((node).block); + case SyntaxKind.ExpressionStatement: // span on the expression return textSpan((node).expression); @@ -420,7 +422,7 @@ module ts.BreakpointResolver { case SyntaxKind.Block: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: return spanInNode((node.parent).statements[(node.parent).statements.length - 1]);; diff --git a/src/services/formatting.ts b/src/services/formatting.ts index 741b853b7ba51..3322ea1e65b0c 100644 --- a/src/services/formatting.ts +++ b/src/services/formatting.ts @@ -155,10 +155,11 @@ module ts.formatting { case SyntaxKind.SourceFile: case SyntaxKind.Block: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: - return rangeContainsRange((parent).statements, node) + return rangeContainsRange((parent).statements, node); + case SyntaxKind.CatchClause: + return rangeContainsRange((parent).block.statements, node); } return false; @@ -898,7 +899,6 @@ module ts.formatting { case SyntaxKind.Block: case SyntaxKind.FunctionBlock: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: return true; diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 7de7baee6ca67..2723b50af7bb3 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -525,7 +525,6 @@ module ts.formatting { case SyntaxKind.SwitchStatement: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: @@ -581,7 +580,7 @@ module ts.formatting { case SyntaxKind.EnumDeclaration: case SyntaxKind.Block: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: @@ -603,7 +602,7 @@ module ts.formatting { case SyntaxKind.WithStatement: // TODO // case SyntaxKind.ElseClause: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: return true; diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 7f071e5c22470..68f30bee781a9 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -79,7 +79,8 @@ module ts { parent.kind === SyntaxKind.ForStatement || parent.kind === SyntaxKind.IfStatement || parent.kind === SyntaxKind.WhileStatement || - parent.kind === SyntaxKind.WithStatement) { + parent.kind === SyntaxKind.WithStatement || + parent.kind === SyntaxKind.CatchClause) { addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n)); } @@ -100,7 +101,6 @@ module ts { case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); diff --git a/src/services/services.ts b/src/services/services.ts index 7e9e84cd7af48..b20067887b319 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2576,7 +2576,7 @@ module ts { isFunction(containingNodeKind); case SyntaxKind.OpenParenToken: - return containingNodeKind === SyntaxKind.CatchBlock || + return containingNodeKind === SyntaxKind.CatchClause || isFunction(containingNodeKind); case SyntaxKind.OpenBraceToken: @@ -3567,8 +3567,8 @@ module ts { else if (node.kind === SyntaxKind.TryStatement) { var tryStatement = node; - if (tryStatement.catchBlock) { - aggregate(tryStatement.catchBlock); + if (tryStatement.catchClause) { + aggregate(tryStatement.catchClause); } else { // Exceptions thrown within a try block lacking a catch clause @@ -3607,7 +3607,7 @@ module ts { if (parent.kind === SyntaxKind.TryStatement) { var tryStatement = parent; - if (tryStatement.tryBlock === child && tryStatement.catchBlock) { + if (tryStatement.tryBlock === child && tryStatement.catchClause) { return child; } } @@ -3623,8 +3623,8 @@ module ts { pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword); - if (tryStatement.catchBlock) { - pushKeywordIf(keywords, tryStatement.catchBlock.getFirstToken(), SyntaxKind.CatchKeyword); + if (tryStatement.catchClause) { + pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), SyntaxKind.CatchKeyword); } if (tryStatement.finallyBlock) { @@ -4738,7 +4738,7 @@ module ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - case SyntaxKind.CatchBlock: + case SyntaxKind.CatchClause: return SemanticMeaning.Value; case SyntaxKind.TypeParameter: diff --git a/src/services/smartIndenter.ts b/src/services/smartIndenter.ts index 4e32522040ed6..82226449b9661 100644 --- a/src/services/smartIndenter.ts +++ b/src/services/smartIndenter.ts @@ -328,7 +328,6 @@ module ts.formatting { case SyntaxKind.Block: case SyntaxKind.FunctionBlock: case SyntaxKind.TryBlock: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: case SyntaxKind.ObjectLiteralExpression: @@ -404,12 +403,13 @@ module ts.formatting { case SyntaxKind.EnumDeclaration: case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.Block: - case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: case SyntaxKind.SwitchStatement: return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile); + case SyntaxKind.CatchClause: + return isCompletedNode((n).block, sourceFile); case SyntaxKind.ParenthesizedExpression: case SyntaxKind.CallSignature: case SyntaxKind.CallExpression: diff --git a/tests/baselines/reference/sourceMapValidationStatements.js.map b/tests/baselines/reference/sourceMapValidationStatements.js.map index 02b5c0bb80665..8eb9994491424 100644 --- a/tests/baselines/reference/sourceMapValidationStatements.js.map +++ b/tests/baselines/reference/sourceMapValidationStatements.js.map @@ -1,2 +1,2 @@ //// [sourceMapValidationStatements.js.map] -{"version":3,"file":"sourceMapValidationStatements.js","sourceRoot":"","sources":["sourceMapValidationStatements.ts"],"names":["f"],"mappings":"AAAA,SAAS,CAAC;IACNA,IAAIA,CAACA,CAACA;IACNA,IAAIA,CAACA,GAAGA,CAACA,CAACA;IACVA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,CAACA,EAAEA,CAACA,GAAGA,EAAEA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;QAC1BA,CAACA,IAAIA,CAACA,CAACA;QACPA,CAACA,IAAIA,CAACA,CAACA;IACXA,CAACA;IACDA,EAAEA,CAACA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA;QACTA,CAACA,IAAIA,CAACA,CAACA;IACXA,CAACA;IAACA,IAAIA,CAACA,CAACA;QACJA,CAACA,IAAIA,EAAEA,CAACA;QACRA,CAACA,EAAEA,CAACA;IACRA,CAACA;IACDA,IAAIA,CAACA,GAAGA;QACJA,CAACA;QACDA,CAACA;QACDA,CAACA;KACJA,CAACA;IACFA,IAAIA,GAAGA,GAAGA;QACNA,CAACA,EAAEA,CAACA;QACJA,CAACA,EAAEA,OAAOA;KACbA,CAACA;IACFA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,IAAIA,CAACA,CAACA,CAACA,CAACA;QACdA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA,CAACA;QACbA,IAAIA,CAACA,GAAGA,EAAEA,CAACA;IACfA,CAACA;IACDA,IAAAA,CAACA;QACGA,GAAGA,CAACA,CAACA,GAAGA,MAAMA,CAACA;IACnBA,CAAEA;IAAAA,KAAKA,CAACA,CAACA,CAACA,CAACA,CAATA,CAACA;QACCA,EAAEA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA;YACbA,GAAGA,CAACA,CAACA,GAAGA,EAAEA,CAACA;QACfA,CAACA;QAACA,IAAIA,CAACA,CAACA;YACJA,GAAGA,CAACA,CAACA,GAAGA,KAAKA,CAACA;QAClBA,CAACA;IACLA,CAACA;IACDA,IAAAA,CAACA;QACGA,MAAMA,IAAIA,KAAKA,EAAEA,CAACA;IACtBA,CAAEA;IAAAA,KAAKA,CAACA,CAACA,EAAEA,CAACA,CAAVA,CAACA;QACCA,IAAIA,CAACA,GAAGA,EAAEA,CAACA;IACfA,CAACA;YAACA,CAACA;QACCA,CAACA,GAAGA,EAAEA,CAACA;IACXA,CAACA;IACDA,MAAMA,GAAGA,EAAEA,CAACA;QACRA,CAACA,GAAGA,CAACA,CAACA;QACNA,CAACA,GAAGA,EAAEA,CAACA;IACXA,CAACA;IACDA,MAAMA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA,CAACA;QACZA,KAAKA,CAACA,EAAEA,CAACA;YACLA,CAACA,EAAEA,CAACA;YACJA,KAAKA,CAACA;QAEVA,CAACA;QACDA,KAAKA,CAACA,EAAEA,CAACA;YACLA,CAACA,EAAEA,CAACA;YACJA,KAAKA,CAACA;QAEVA,CAACA;QACDA,SAASA,CAACA;YACNA,CAACA,IAAIA,CAACA,CAACA;YACPA,CAACA,GAAGA,EAAEA,CAACA;YACPA,KAAKA,CAACA;QAEVA,CAACA;IACLA,CAACA;IACDA,OAAOA,CAACA,GAAGA,EAAEA,EAAEA,CAACA;QACZA,CAACA,EAAEA,CAACA;IACRA,CAACA;IACDA,GAAGA,CAACA;QACAA,CAACA,EAAEA,CAACA;IACRA,CAACA,QAAQA,CAACA,GAAGA,CAACA,EAACA;IACfA,CAACA,GAAGA,CAACA,CAACA;IACNA,IAAIA,CAACA,GAAGA,CAACA,CAACA,IAAIA,CAACA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;IACjCA,CAACA,CAACA,IAAIA,CAACA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;IACzBA,CAACA,KAAKA,CAACA,CAACA;IACRA,CAACA,GAAGA,CAACA,GAAGA,EAAEA,CAACA;IACXA,IAAIA,CAACA,GAAGA,CAACA,CAACA;IACVA,MAAMA,CAACA;AACXA,CAACA;AACD,IAAI,CAAC,GAAG;IACJ,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC,CAAC;AACF,CAAC,EAAE,CAAC"} \ No newline at end of file +{"version":3,"file":"sourceMapValidationStatements.js","sourceRoot":"","sources":["sourceMapValidationStatements.ts"],"names":["f"],"mappings":"AAAA,SAAS,CAAC;IACNA,IAAIA,CAACA,CAACA;IACNA,IAAIA,CAACA,GAAGA,CAACA,CAACA;IACVA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,CAACA,EAAEA,CAACA,GAAGA,EAAEA,EAAEA,CAACA,EAAEA,EAAEA,CAACA;QAC1BA,CAACA,IAAIA,CAACA,CAACA;QACPA,CAACA,IAAIA,CAACA,CAACA;IACXA,CAACA;IACDA,EAAEA,CAACA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA;QACTA,CAACA,IAAIA,CAACA,CAACA;IACXA,CAACA;IAACA,IAAIA,CAACA,CAACA;QACJA,CAACA,IAAIA,EAAEA,CAACA;QACRA,CAACA,EAAEA,CAACA;IACRA,CAACA;IACDA,IAAIA,CAACA,GAAGA;QACJA,CAACA;QACDA,CAACA;QACDA,CAACA;KACJA,CAACA;IACFA,IAAIA,GAAGA,GAAGA;QACNA,CAACA,EAAEA,CAACA;QACJA,CAACA,EAAEA,OAAOA;KACbA,CAACA;IACFA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,IAAIA,CAACA,CAACA,CAACA,CAACA;QACdA,GAAGA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA,CAACA;QACbA,IAAIA,CAACA,GAAGA,EAAEA,CAACA;IACfA,CAACA;IACDA,IAAAA,CAACA;QACGA,GAAGA,CAACA,CAACA,GAAGA,MAAMA,CAACA;IACnBA,CAAEA;IAAAA,KAAKA,CAACA,CAACA,CAACA,CAACA,CAACA,CAACA;QACTA,EAAEA,CAACA,CAACA,GAAGA,CAACA,CAACA,GAAGA,EAAEA,CAACA,CAACA,CAACA;YACbA,GAAGA,CAACA,CAACA,GAAGA,EAAEA,CAACA;QACfA,CAACA;QAACA,IAAIA,CAACA,CAACA;YACJA,GAAGA,CAACA,CAACA,GAAGA,KAAKA,CAACA;QAClBA,CAACA;IACLA,CAACA;IACDA,IAAAA,CAACA;QACGA,MAAMA,IAAIA,KAAKA,EAAEA,CAACA;IACtBA,CAAEA;IAAAA,KAAKA,CAACA,CAACA,EAAEA,CAACA,CAACA,CAACA;QACVA,IAAIA,CAACA,GAAGA,EAAEA,CAACA;IACfA,CAACA;YAACA,CAACA;QACCA,CAACA,GAAGA,EAAEA,CAACA;IACXA,CAACA;IACDA,MAAMA,GAAGA,EAAEA,CAACA;QACRA,CAACA,GAAGA,CAACA,CAACA;QACNA,CAACA,GAAGA,EAAEA,CAACA;IACXA,CAACA;IACDA,MAAMA,CAACA,CAACA,GAAGA,CAACA,CAACA,CAACA,CAACA,CAACA;QACZA,KAAKA,CAACA,EAAEA,CAACA;YACLA,CAACA,EAAEA,CAACA;YACJA,KAAKA,CAACA;QAEVA,CAACA;QACDA,KAAKA,CAACA,EAAEA,CAACA;YACLA,CAACA,EAAEA,CAACA;YACJA,KAAKA,CAACA;QAEVA,CAACA;QACDA,SAASA,CAACA;YACNA,CAACA,IAAIA,CAACA,CAACA;YACPA,CAACA,GAAGA,EAAEA,CAACA;YACPA,KAAKA,CAACA;QAEVA,CAACA;IACLA,CAACA;IACDA,OAAOA,CAACA,GAAGA,EAAEA,EAAEA,CAACA;QACZA,CAACA,EAAEA,CAACA;IACRA,CAACA;IACDA,GAAGA,CAACA;QACAA,CAACA,EAAEA,CAACA;IACRA,CAACA,QAAQA,CAACA,GAAGA,CAACA,EAACA;IACfA,CAACA,GAAGA,CAACA,CAACA;IACNA,IAAIA,CAACA,GAAGA,CAACA,CAACA,IAAIA,CAACA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;IACjCA,CAACA,CAACA,IAAIA,CAACA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,GAAGA,CAACA,CAACA;IACzBA,CAACA,KAAKA,CAACA,CAACA;IACRA,CAACA,GAAGA,CAACA,GAAGA,EAAEA,CAACA;IACXA,IAAIA,CAACA,GAAGA,CAACA,CAACA;IACVA,MAAMA,CAACA;AACXA,CAACA;AACD,IAAI,CAAC,GAAG;IACJ,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC,CAAC;AACF,CAAC,EAAE,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/sourceMapValidationStatements.sourcemap.txt b/tests/baselines/reference/sourceMapValidationStatements.sourcemap.txt index 1a288e3a830f8..ef7aef275c094 100644 --- a/tests/baselines/reference/sourceMapValidationStatements.sourcemap.txt +++ b/tests/baselines/reference/sourceMapValidationStatements.sourcemap.txt @@ -557,16 +557,16 @@ sourceFile:sourceMapValidationStatements.ts 4 > ( 5 > e 6 > ) -7 > -8 > c +7 > +8 > { 1->Emitted(31, 5) Source(29, 7) + SourceIndex(0) name (f) 2 >Emitted(31, 10) Source(29, 12) + SourceIndex(0) name (f) 3 >Emitted(31, 11) Source(29, 13) + SourceIndex(0) name (f) 4 >Emitted(31, 12) Source(29, 14) + SourceIndex(0) name (f) 5 >Emitted(31, 13) Source(29, 15) + SourceIndex(0) name (f) 6 >Emitted(31, 14) Source(29, 16) + SourceIndex(0) name (f) -7 >Emitted(31, 15) Source(29, 7) + SourceIndex(0) name (f) -8 >Emitted(31, 16) Source(29, 8) + SourceIndex(0) name (f) +7 >Emitted(31, 15) Source(29, 17) + SourceIndex(0) name (f) +8 >Emitted(31, 16) Source(29, 18) + SourceIndex(0) name (f) --- >>> if (obj.z < 10) { 1->^^^^^^^^ @@ -581,7 +581,7 @@ sourceFile:sourceMapValidationStatements.ts 10> ^ 11> ^ 12> ^ -1->atch (e) { +1-> > 2 > if 3 > @@ -759,16 +759,16 @@ sourceFile:sourceMapValidationStatements.ts 4 > ( 5 > e1 6 > ) -7 > -8 > c +7 > +8 > { 1->Emitted(42, 5) Source(38, 7) + SourceIndex(0) name (f) 2 >Emitted(42, 10) Source(38, 12) + SourceIndex(0) name (f) 3 >Emitted(42, 11) Source(38, 13) + SourceIndex(0) name (f) 4 >Emitted(42, 12) Source(38, 14) + SourceIndex(0) name (f) 5 >Emitted(42, 14) Source(38, 16) + SourceIndex(0) name (f) 6 >Emitted(42, 15) Source(38, 17) + SourceIndex(0) name (f) -7 >Emitted(42, 16) Source(38, 7) + SourceIndex(0) name (f) -8 >Emitted(42, 17) Source(38, 8) + SourceIndex(0) name (f) +7 >Emitted(42, 16) Source(38, 18) + SourceIndex(0) name (f) +8 >Emitted(42, 17) Source(38, 19) + SourceIndex(0) name (f) --- >>> var b = e1; 1->^^^^^^^^ @@ -777,7 +777,7 @@ sourceFile:sourceMapValidationStatements.ts 4 > ^^^ 5 > ^^ 6 > ^ -1->atch (e1) { +1-> > 2 > var 3 > b diff --git a/tests/baselines/reference/sourceMapValidationTryCatchFinally.js.map b/tests/baselines/reference/sourceMapValidationTryCatchFinally.js.map index 24b7b84a3d0ff..897168075382c 100644 --- a/tests/baselines/reference/sourceMapValidationTryCatchFinally.js.map +++ b/tests/baselines/reference/sourceMapValidationTryCatchFinally.js.map @@ -1,2 +1,2 @@ //// [sourceMapValidationTryCatchFinally.js.map] -{"version":3,"file":"sourceMapValidationTryCatchFinally.js","sourceRoot":"","sources":["sourceMapValidationTryCatchFinally.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,EAAE,CAAC;AACX,IAAA,CAAC;IACG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAE;AAAA,KAAK,CAAC,CAAC,CAAC,CAAC,CAAT,CAAC;IACC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;QAAC,CAAC;IACC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AACf,CAAC;AACD,IAAA,CAAC;IAEG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,IAAI,KAAK,EAAE,CAAC;AACtB,CACA;AAAA,KAAK,CAAC,CAAC,CAAC,CAAC,CAAT,CAAC;IAEG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;QACD,CAAC;IAEG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AACf,CAAC"} \ No newline at end of file +{"version":3,"file":"sourceMapValidationTryCatchFinally.js","sourceRoot":"","sources":["sourceMapValidationTryCatchFinally.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,EAAE,CAAC;AACX,IAAA,CAAC;IACG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAE;AAAA,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACT,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;QAAC,CAAC;IACC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AACf,CAAC;AACD,IAAA,CAAC;IAEG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,IAAI,KAAK,EAAE,CAAC;AACtB,CACA;AAAA,KAAK,CAAC,CAAC,CAAC,CAAC,CACT,CAAC;IACG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;QACD,CAAC;IAEG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;AACf,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/sourceMapValidationTryCatchFinally.sourcemap.txt b/tests/baselines/reference/sourceMapValidationTryCatchFinally.sourcemap.txt index aa0b846ece8fb..25dee4fbc45c4 100644 --- a/tests/baselines/reference/sourceMapValidationTryCatchFinally.sourcemap.txt +++ b/tests/baselines/reference/sourceMapValidationTryCatchFinally.sourcemap.txt @@ -91,16 +91,16 @@ sourceFile:sourceMapValidationTryCatchFinally.ts 4 > ( 5 > e 6 > ) -7 > -8 > c +7 > +8 > { 1->Emitted(5, 1) Source(4, 3) + SourceIndex(0) 2 >Emitted(5, 6) Source(4, 8) + SourceIndex(0) 3 >Emitted(5, 7) Source(4, 9) + SourceIndex(0) 4 >Emitted(5, 8) Source(4, 10) + SourceIndex(0) 5 >Emitted(5, 9) Source(4, 11) + SourceIndex(0) 6 >Emitted(5, 10) Source(4, 12) + SourceIndex(0) -7 >Emitted(5, 11) Source(4, 3) + SourceIndex(0) -8 >Emitted(5, 12) Source(4, 4) + SourceIndex(0) +7 >Emitted(5, 11) Source(4, 13) + SourceIndex(0) +8 >Emitted(5, 12) Source(4, 14) + SourceIndex(0) --- >>> x = x - 1; 1->^^^^ @@ -110,7 +110,7 @@ sourceFile:sourceMapValidationTryCatchFinally.ts 5 > ^^^ 6 > ^ 7 > ^ -1->atch (e) { +1-> > 2 > x 3 > = @@ -266,16 +266,17 @@ sourceFile:sourceMapValidationTryCatchFinally.ts 4 > ( 5 > e 6 > ) -7 > -8 > c +7 > + > +8 > { 1->Emitted(15, 1) Source(14, 1) + SourceIndex(0) 2 >Emitted(15, 6) Source(14, 6) + SourceIndex(0) 3 >Emitted(15, 7) Source(14, 7) + SourceIndex(0) 4 >Emitted(15, 8) Source(14, 8) + SourceIndex(0) 5 >Emitted(15, 9) Source(14, 9) + SourceIndex(0) 6 >Emitted(15, 10) Source(14, 10) + SourceIndex(0) -7 >Emitted(15, 11) Source(14, 1) + SourceIndex(0) -8 >Emitted(15, 12) Source(14, 2) + SourceIndex(0) +7 >Emitted(15, 11) Source(15, 1) + SourceIndex(0) +8 >Emitted(15, 12) Source(15, 2) + SourceIndex(0) --- >>> x = x - 1; 1->^^^^ @@ -285,8 +286,7 @@ sourceFile:sourceMapValidationTryCatchFinally.ts 5 > ^^^ 6 > ^ 7 > ^ -1->atch (e) - >{ +1-> > 2 > x 3 > = From 581ef9f2b093ec51a28d2c31a4da654dc5df25ec Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Mon, 1 Dec 2014 23:39:44 -0800 Subject: [PATCH 09/10] Remove arrow allocations from the parser in a few places. --- src/compiler/parser.ts | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 553d51b1bd2b2..4198ad50221a0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3551,7 +3551,7 @@ module ts { case SyntaxKind.StaticKeyword: // When followed by an identifier or keyword, these do not start a statement but // might instead be following type members - if (lookAhead(() => nextToken() >= SyntaxKind.Identifier)) { + if (lookAhead(() => nextToken() >= SyntaxKind.Identifier && !scanner.hasPrecedingLineBreak())) { return false; } default: @@ -3702,12 +3702,16 @@ module ts { property.name = name; property.questionToken = questionToken; property.type = parseTypeAnnotation(); - property.initializer = allowInAnd(() => parseInitializer(/*inParameter*/ false)); + property.initializer = allowInAnd(parseNonParameterInitializer); parseSemicolon(); return finishNode(property); } } + function parseNonParameterInitializer() { + return parseInitializer(/*inParameter*/ false); + } + function parseMemberAccessorDeclaration(kind: SyntaxKind, fullStart: number, modifiers: ModifiersArray): MethodDeclaration { var node = createNode(kind, fullStart); setModifiers(node, modifiers); @@ -3913,11 +3917,11 @@ module ts { function parseEnumMember(): EnumMember { var node = createNode(SyntaxKind.EnumMember, scanner.getStartPos()); node.name = parsePropertyName(); - node.initializer = allowInAnd(() => parseInitializer(/*inParameter*/ false)); + node.initializer = allowInAnd(parseNonParameterInitializer); return finishNode(node); } - function parseAndCheckEnumDeclaration(fullStart: number, modifiers: ModifiersArray, flags: NodeFlags): EnumDeclaration { + function parseEnumDeclaration(fullStart: number, modifiers: ModifiersArray): EnumDeclaration { var node = createNode(SyntaxKind.EnumDeclaration, fullStart); setModifiers(node, modifiers); parseExpected(SyntaxKind.EnumKeyword); @@ -3935,7 +3939,7 @@ module ts { function parseModuleBlock(): ModuleBlock { var node = createNode(SyntaxKind.ModuleBlock, scanner.getStartPos()); if (parseExpected(SyntaxKind.OpenBraceToken)) { - node.statements = parseList(ParsingContext.ModuleElements, /*checkForStrictMode*/ false, parseModuleElement); + node.statements = parseList(ParsingContext.ModuleElements, /*checkForStrictMode*/false, parseModuleElement); parseExpected(SyntaxKind.CloseBraceToken); } else { @@ -3955,20 +3959,19 @@ module ts { return finishNode(node); } - function parseAmbientExternalModuleDeclaration(fullStart: number, modifiers: ModifiersArray, flags: NodeFlags): ModuleDeclaration { + function parseAmbientExternalModuleDeclaration(fullStart: number, modifiers: ModifiersArray): ModuleDeclaration { var node = createNode(SyntaxKind.ModuleDeclaration, fullStart); setModifiers(node, modifiers); - node.flags |= flags; node.name = parseLiteralNode(/*internName:*/ true); node.body = parseModuleBlock(); return finishNode(node); } - function parseModuleDeclaration(fullStart: number, modifiers: ModifiersArray, flags: NodeFlags): ModuleDeclaration { + function parseModuleDeclaration(fullStart: number, modifiers: ModifiersArray): ModuleDeclaration { parseExpected(SyntaxKind.ModuleKeyword); return token === SyntaxKind.StringLiteral - ? parseAmbientExternalModuleDeclaration(fullStart, modifiers, flags) - : parseInternalModuleTail(fullStart, modifiers, flags); + ? parseAmbientExternalModuleDeclaration(fullStart, modifiers) + : parseInternalModuleTail(fullStart, modifiers, modifiers? modifiers.flags : 0); } function isExternalModuleReference() { @@ -4063,7 +4066,6 @@ module ts { } } - var flags = modifiers ? modifiers.flags : 0; switch (token) { case SyntaxKind.VarKeyword: case SyntaxKind.LetKeyword: @@ -4078,9 +4080,9 @@ module ts { case SyntaxKind.TypeKeyword: return parseTypeAliasDeclaration(fullStart, modifiers); case SyntaxKind.EnumKeyword: - return parseAndCheckEnumDeclaration(fullStart, modifiers, flags); + return parseEnumDeclaration(fullStart, modifiers); case SyntaxKind.ModuleKeyword: - return parseModuleDeclaration(fullStart, modifiers, flags); + return parseModuleDeclaration(fullStart, modifiers); case SyntaxKind.ImportKeyword: return parseImportDeclaration(fullStart, modifiers); default: From deca94427c0f160899e4e9bc14ee89fe46f427d6 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Dec 2014 00:02:15 -0800 Subject: [PATCH 10/10] Reduce arrow function allocations in the parser. --- src/compiler/parser.ts | 409 ++++++++++++++++++++++++----------------- 1 file changed, 244 insertions(+), 165 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 4198ad50221a0..9397661839dc5 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1347,11 +1347,11 @@ module ts { } function parseIdentifierName(): Identifier { - return createIdentifier(token >= SyntaxKind.Identifier); + return createIdentifier(isIdentifierOrKeyword()); } function isLiteralPropertyName(): boolean { - return token >= SyntaxKind.Identifier || + return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral; } @@ -1439,7 +1439,9 @@ module ts { case ParsingContext.ObjectLiteralMembers: return token === SyntaxKind.OpenBracketToken || token === SyntaxKind.AsteriskToken || isLiteralPropertyName(); case ParsingContext.TypeReferences: - return isIdentifier() && ((token !== SyntaxKind.ExtendsKeyword && token !== SyntaxKind.ImplementsKeyword) || !lookAhead(() => (nextToken(), isIdentifier()))); + // We want to make sure that the "extends" in "extends foo" or the "implements" in + // "implements foo" is not considered a type name. + return isIdentifier() && !isNotHeritageClauseTypeName(); case ParsingContext.VariableDeclarations: case ParsingContext.TypeParameters: return isIdentifier(); @@ -1459,6 +1461,21 @@ module ts { Debug.fail("Non-exhaustive case in 'isListElement'."); } + function nextTokenIsIdentifier() { + nextToken(); + return isIdentifier(); + } + + function isNotHeritageClauseTypeName(): boolean { + if (token === SyntaxKind.ImplementsKeyword || + token === SyntaxKind.ExtendsKeyword) { + + return lookAhead(nextTokenIsIdentifier); + } + + return false; + } + // True if positioned at a list terminator function isListTerminator(kind: ParsingContext): boolean { if (token === SyntaxKind.EndOfFileToken) { @@ -1689,10 +1706,7 @@ module ts { // In the first case though, ASI will not take effect because there is not a // line terminator after the keyword. if (scanner.hasPrecedingLineBreak() && scanner.isReservedWord()) { - var matchesPattern = lookAhead(() => { - nextToken(); - return !scanner.hasPrecedingLineBreak() && (scanner.isIdentifier() || scanner.isReservedWord()); - }); + var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); if (matchesPattern) { // Report that we need an identifier. However, report it right after the dot, @@ -1705,6 +1719,8 @@ module ts { return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); } + + function parseTokenNode(): T { var node = createNode(token); nextToken(); @@ -1972,58 +1988,62 @@ module ts { return false; } - return lookAhead(() => { - // The only allowed sequence is: - // - // [id: - // - // However, for error recovery, we also check the following cases: - // - // [... - // [id, - // [id?, - // [id?: - // [id?] - // [public id - // [private id - // [protected id - // [] - // - if (nextToken() === SyntaxKind.DotDotDotToken || token === SyntaxKind.CloseBracketToken) { - return true; - } + return lookAhead(isUnambiguouslyIndexSignature); + } - if (isModifier(token)) { - nextToken(); - if (isIdentifier()) { - return true; - } - } - else if (!isIdentifier()) { - return false; - } - else { - // Skip the identifier - nextToken(); - } + function isUnambiguouslyIndexSignature() { + // The only allowed sequence is: + // + // [id: + // + // However, for error recovery, we also check the following cases: + // + // [... + // [id, + // [id?, + // [id?: + // [id?] + // [public id + // [private id + // [protected id + // [] + // + nextToken(); + if (token === SyntaxKind.DotDotDotToken || token === SyntaxKind.CloseBracketToken) { + return true; + } - // A colon signifies a well formed indexer - // A comma should be a badly formed indexer because comma expressions are not allowed - // in computed properties. - if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken) { + if (isModifier(token)) { + nextToken(); + if (isIdentifier()) { return true; } + } + else if (!isIdentifier()) { + return false; + } + else { + // Skip the identifier + nextToken(); + } - // Question mark could be an indexer with an optional property, - // or it could be a conditional expression in a computed property. - if (token !== SyntaxKind.QuestionToken) { - return false; - } + // A colon signifies a well formed indexer + // A comma should be a badly formed indexer because comma expressions are not allowed + // in computed properties. + if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken) { + return true; + } - // If any of the following tokens are after the question mark, it cannot - // be a conditional expression, so treat it as an indexer. - return nextToken() === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBracketToken; - }); + // Question mark could be an indexer with an optional property, + // or it could be a conditional expression in a computed property. + if (token !== SyntaxKind.QuestionToken) { + return false; + } + + // If any of the following tokens are after the question mark, it cannot + // be a conditional expression, so treat it as an indexer. + nextToken(); + return token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBracketToken; } function parseIndexSignatureDeclaration(fullStart: number, modifiers: ModifiersArray): IndexSignatureDeclaration { @@ -2069,15 +2089,19 @@ module ts { case SyntaxKind.OpenBracketToken: // Both for indexers and computed properties return true; default: - return isLiteralPropertyName() && lookAhead(() => - nextToken() === SyntaxKind.OpenParenToken || - token === SyntaxKind.LessThanToken || - token === SyntaxKind.QuestionToken || - token === SyntaxKind.ColonToken || - canParseSemicolon()); + return isLiteralPropertyName() && lookAhead(isTypeMemberWithLiteralPropertyName); } } + function isTypeMemberWithLiteralPropertyName() { + nextToken(); + return token === SyntaxKind.OpenParenToken || + token === SyntaxKind.LessThanToken || + token === SyntaxKind.QuestionToken || + token === SyntaxKind.ColonToken || + canParseSemicolon(); + } + function parseTypeMember(): Declaration { switch (token) { case SyntaxKind.OpenParenToken: @@ -2087,19 +2111,25 @@ module ts { // Indexer or computed property return isIndexSignature() ? parseIndexSignatureDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined) : parsePropertyOrMethod(); case SyntaxKind.NewKeyword: - if (lookAhead(() => nextToken() === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken)) { + if (lookAhead(isStartOfConstructSignature)) { return parseSignatureMember(SyntaxKind.ConstructSignature); } + // fall through. case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: return parsePropertyOrMethod(); default: - if (token >= SyntaxKind.Identifier) { + if (isIdentifierOrKeyword()) { return parsePropertyOrMethod(); } } } + function isStartOfConstructSignature() { + nextToken(); + return token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken; + } + function parseTypeLiteral(): TypeLiteralNode { var node = createNode(SyntaxKind.TypeLiteral); node.members = parseObjectTypeMembers(); @@ -2187,15 +2217,17 @@ module ts { case SyntaxKind.OpenParenToken: // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier, // or something that starts a type. We don't want to consider things like '(1)' a type. - return lookAhead(() => { - nextToken(); - return token === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType(); - }); + return lookAhead(isStartOfParenthesizedOrFunctionType); default: return isIdentifier(); } } + function isStartOfParenthesizedOrFunctionType() { + nextToken(); + return token === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType(); + } + function parseArrayTypeOrHigher(): TypeNode { var type = parseNonArrayType(); while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { @@ -2224,35 +2256,41 @@ module ts { } function isStartOfFunctionType(): boolean { - return token === SyntaxKind.LessThanToken || token === SyntaxKind.OpenParenToken && lookAhead(() => { + if (token === SyntaxKind.LessThanToken) { + return true; + } + + return token === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType); + } + + function isUnambiguouslyStartOfFunctionType() { + nextToken(); + if (token === SyntaxKind.CloseParenToken || token === SyntaxKind.DotDotDotToken) { + // ( ) + // ( ... + return true; + } + if (isIdentifier() || isModifier(token)) { nextToken(); - if (token === SyntaxKind.CloseParenToken || token === SyntaxKind.DotDotDotToken) { - // ( ) - // ( ... + if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || + token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken || + isIdentifier() || isModifier(token)) { + // ( id : + // ( id , + // ( id ? + // ( id = + // ( modifier id return true; } - if (isIdentifier() || isModifier(token)) { + if (token === SyntaxKind.CloseParenToken) { nextToken(); - if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || - token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken || - isIdentifier() || isModifier(token)) { - // ( id : - // ( id , - // ( id ? - // ( id = - // ( modifier id + if (token === SyntaxKind.EqualsGreaterThanToken) { + // ( id ) => return true; } - if (token === SyntaxKind.CloseParenToken) { - nextToken(); - if (token === SyntaxKind.EqualsGreaterThanToken) { - // ( id ) => - return true; - } - } } - return false; - }); + } + return false; } function parseType(): TypeNode { @@ -2455,15 +2493,17 @@ module ts { // for now we just check if the next token is an identifier. More heuristics // can be added here later as necessary. We just need to make sure that we // don't accidently consume something legal. - return lookAhead(() => { - nextToken(); - return !scanner.hasPrecedingLineBreak() && isIdentifier(); - }); + return lookAhead(nextTokenIsIdentifierOnSameLine); } return false; } + function nextTokenIsIdentifierOnSameLine() { + nextToken(); + return !scanner.hasPrecedingLineBreak() && isIdentifier() + } + function parseYieldExpression(): YieldExpression { var node = createNode(SyntaxKind.YieldExpression); @@ -2546,66 +2586,9 @@ module ts { // Speculatively look ahead to be sure, and rollback if not. function isParenthesizedArrowFunctionExpression(): Tristate { if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) { - return lookAhead(() => { - var first = token; - var second = nextToken(); - - if (first === SyntaxKind.OpenParenToken) { - if (second === SyntaxKind.CloseParenToken) { - // Simple cases: "() =>", "(): ", and "() {". - // This is an arrow function with no parameters. - // The last one is not actually an arrow function, - // but this is probably what the user intended. - var third = nextToken(); - switch (third) { - case SyntaxKind.EqualsGreaterThanToken: - case SyntaxKind.ColonToken: - case SyntaxKind.OpenBraceToken: - return Tristate.True; - default: - return Tristate.False; - } - } - - // Simple case: "(..." - // This is an arrow function with a rest parameter. - if (second === SyntaxKind.DotDotDotToken) { - return Tristate.True; - } - - // If we had "(" followed by something that's not an identifier, - // then this definitely doesn't look like a lambda. - // Note: we could be a little more lenient and allow - // "(public" or "(private". These would not ever actually be allowed, - // but we could provide a good error message instead of bailing out. - if (!isIdentifier()) { - return Tristate.False; - } - - // If we have something like "(a:", then we must have a - // type-annotated parameter in an arrow function expression. - if (nextToken() === SyntaxKind.ColonToken) { - return Tristate.True; - } - - // This *could* be a parenthesized arrow function. - // Return Unknown to let the caller know. - return Tristate.Unknown; - } - else { - Debug.assert(first === SyntaxKind.LessThanToken); - - // If we have "<" not followed by an identifier, - // then this definitely is not an arrow function. - if (!isIdentifier()) { - return Tristate.False; - } - - // This *could* be a parenthesized arrow function. - return Tristate.Unknown; - } - }); + return lookAhead(isParenthesizedArrowFunctionExpressionWorker); } + if (token === SyntaxKind.EqualsGreaterThanToken) { // ERROR RECOVERY TWEAK: // If we see a standalone => try to parse it as an arrow function expression as that's @@ -2616,6 +2599,66 @@ module ts { return Tristate.False; } + function isParenthesizedArrowFunctionExpressionWorker() { + var first = token; + var second = nextToken(); + + if (first === SyntaxKind.OpenParenToken) { + if (second === SyntaxKind.CloseParenToken) { + // Simple cases: "() =>", "(): ", and "() {". + // This is an arrow function with no parameters. + // The last one is not actually an arrow function, + // but this is probably what the user intended. + var third = nextToken(); + switch (third) { + case SyntaxKind.EqualsGreaterThanToken: + case SyntaxKind.ColonToken: + case SyntaxKind.OpenBraceToken: + return Tristate.True; + default: + return Tristate.False; + } + } + + // Simple case: "(..." + // This is an arrow function with a rest parameter. + if (second === SyntaxKind.DotDotDotToken) { + return Tristate.True; + } + + // If we had "(" followed by something that's not an identifier, + // then this definitely doesn't look like a lambda. + // Note: we could be a little more lenient and allow + // "(public" or "(private". These would not ever actually be allowed, + // but we could provide a good error message instead of bailing out. + if (!isIdentifier()) { + return Tristate.False; + } + + // If we have something like "(a:", then we must have a + // type-annotated parameter in an arrow function expression. + if (nextToken() === SyntaxKind.ColonToken) { + return Tristate.True; + } + + // This *could* be a parenthesized arrow function. + // Return Unknown to let the caller know. + return Tristate.Unknown; + } + else { + Debug.assert(first === SyntaxKind.LessThanToken); + + // If we have "<" not followed by an identifier, + // then this definitely is not an arrow function. + if (!isIdentifier()) { + return Tristate.False; + } + + // This *could* be a parenthesized arrow function. + return Tristate.Unknown; + } + } + function tryParseSignatureIfArrowOrBraceFollows(): ParsedSignature { return tryParse(() => { // Arrow functions are never generators. @@ -3479,7 +3522,11 @@ module ts { } function isLabel(): boolean { - return isIdentifier() && lookAhead(() => nextToken() === SyntaxKind.ColonToken); + return isIdentifier() && lookAhead(nextTokenIsColonToken); + } + + function nextTokenIsColonToken() { + return nextToken() === SyntaxKind.ColonToken; } function parseLabeledStatement(): LabeledStatement { @@ -3532,7 +3579,7 @@ module ts { // const keyword can precede enum keyword when defining constant enums // 'const enum' do not start statement. // In ES 6 'enum' is a future reserved keyword, so it should not be used as identifier - var isConstEnum = lookAhead(() => nextToken() === SyntaxKind.EnumKeyword); + var isConstEnum = lookAhead(nextTokenIsEnumKeyword); return !isConstEnum; case SyntaxKind.InterfaceKeyword: case SyntaxKind.ClassKeyword: @@ -3551,7 +3598,7 @@ module ts { case SyntaxKind.StaticKeyword: // When followed by an identifier or keyword, these do not start a statement but // might instead be following type members - if (lookAhead(() => nextToken() >= SyntaxKind.Identifier && !scanner.hasPrecedingLineBreak())) { + if (lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine)) { return false; } default: @@ -3559,6 +3606,16 @@ module ts { } } + function nextTokenIsEnumKeyword() { + nextToken(); + return token === SyntaxKind.EnumKeyword + } + + function nextTokenIsIdentifierOrKeywordOnSameLine() { + nextToken(); + return isIdentifierOrKeyword() && !scanner.hasPrecedingLineBreak(); + } + function parseStatement(): Statement { switch (token) { case SyntaxKind.OpenBraceToken: @@ -3817,7 +3874,7 @@ module ts { } // It is very important that we check this *after* checking indexers because // the [ token can start an index signature or a computed property name - if (token >= SyntaxKind.Identifier || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || + if (isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBracketToken) { return parsePropertyMemberDeclaration(fullStart, modifiers); } @@ -3975,14 +4032,12 @@ module ts { } function isExternalModuleReference() { - if (token === SyntaxKind.RequireKeyword) { - return lookAhead(() => { - nextToken(); - return token === SyntaxKind.OpenParenToken; - }); - } + return token === SyntaxKind.RequireKeyword && + lookAhead(nextTokenIsOpenParen); + } - return false; + function nextTokenIsOpenParen() { + return nextToken() === SyntaxKind.OpenParenToken; } function parseImportDeclaration(fullStart: number, modifiers: ModifiersArray): ImportDeclaration { @@ -4039,23 +4094,47 @@ module ts { case SyntaxKind.ImportKeyword: case SyntaxKind.TypeKeyword: // Not true keywords so ensure an identifier follows - return lookAhead(() => nextToken() >= SyntaxKind.Identifier); + return lookAhead(nextTokenIsIdentifierOrKeyword); case SyntaxKind.ModuleKeyword: // Not a true keyword so ensure an identifier or string literal follows - return lookAhead(() => nextToken() >= SyntaxKind.Identifier || token === SyntaxKind.StringLiteral); + return lookAhead(nextTokenIsIdentifierOrKeywordOrStringLiteral); case SyntaxKind.ExportKeyword: // Check for export assignment or modifier on source element - return lookAhead(() => nextToken() === SyntaxKind.EqualsToken || isDeclarationStart()); + return lookAhead(nextTokenIsEqualsTokenOrDeclarationStart); case SyntaxKind.DeclareKeyword: case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.ProtectedKeyword: case SyntaxKind.StaticKeyword: // Check for modifier on source element - return lookAhead(() => { nextToken(); return isDeclarationStart(); }); + return lookAhead(nextTokenIsDeclarationStart); } } + function isIdentifierOrKeyword() { + return token >= SyntaxKind.Identifier; + } + + function nextTokenIsIdentifierOrKeyword() { + nextToken(); + return isIdentifierOrKeyword(); + } + + function nextTokenIsIdentifierOrKeywordOrStringLiteral() { + nextToken(); + return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral; + } + + function nextTokenIsEqualsTokenOrDeclarationStart() { + nextToken(); + return token === SyntaxKind.EqualsToken || isDeclarationStart(); + } + + function nextTokenIsDeclarationStart() { + nextToken(); + return isDeclarationStart(); + } + function parseDeclaration(): ModuleElement { var fullStart = getNodePos(); var modifiers = parseModifiers();