From 4850dfbb8e7dcf97fc5ac0dd6b2bebd81c759b8f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 10 Dec 2014 20:55:46 -0800 Subject: [PATCH] Support modifiers on index signatures in an object type. This makes index signature parsing non-contextual. This is necessary so that incremental parsing can reuse index signatures acros classes and object types. --- src/compiler/parser.ts | 58 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 9552e0f9cc9..bd408ad24ef 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2226,7 +2226,8 @@ module ts { return token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBracketToken; } - function parseIndexSignatureDeclaration(fullStart: number, modifiers: ModifiersArray): IndexSignatureDeclaration { + function parseIndexSignatureDeclaration(modifiers: ModifiersArray): IndexSignatureDeclaration { + var fullStart = modifiers ? modifiers.pos : scanner.getStartPos(); var node = createNode(SyntaxKind.IndexSignature, fullStart); setModifiers(node, modifiers); node.parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); @@ -2268,10 +2269,25 @@ module ts { case SyntaxKind.OpenBracketToken: // Both for indexers and computed properties return true; default: + if (isModifier(token)) { + var result = lookAhead(isStartOfIndexSignatureDeclaration); + if (result) { + return result; + } + } + return isLiteralPropertyName() && lookAhead(isTypeMemberWithLiteralPropertyName); } } + function isStartOfIndexSignatureDeclaration() { + while (isModifier(token)) { + nextToken(); + } + + return isIndexSignature(); + } + function isTypeMemberWithLiteralPropertyName() { nextToken(); return token === SyntaxKind.OpenParenToken || @@ -2288,7 +2304,9 @@ module ts { return parseSignatureMember(SyntaxKind.CallSignature); case SyntaxKind.OpenBracketToken: // Indexer or computed property - return isIndexSignature() ? parseIndexSignatureDeclaration(scanner.getStartPos(), /*modifiers:*/ undefined) : parsePropertyOrMethodSignature(); + return isIndexSignature() + ? parseIndexSignatureDeclaration(/*modifiers:*/ undefined) + : parsePropertyOrMethodSignature(); case SyntaxKind.NewKeyword: if (lookAhead(isStartOfConstructSignature)) { return parseSignatureMember(SyntaxKind.ConstructSignature); @@ -2298,12 +2316,32 @@ module ts { case SyntaxKind.NumericLiteral: return parsePropertyOrMethodSignature(); default: + // Index declaration as allowed as a type member. But as per the grammar, + // they also allow modifiers. So we have to check for an index declaration + // that might be following modifiers. This ensures that things work properly + // when incrementally parsing as the parser will produce the Index declaration + // if it has the same text regardless of whether it is inside a class or an + // object type. + if (isModifier(token)) { + var result = tryParse(parseIndexSignatureWithModifiers); + if (result) { + return result; + } + } + if (isIdentifierOrKeyword()) { return parsePropertyOrMethodSignature(); } } } + function parseIndexSignatureWithModifiers() { + var modifiers = parseModifiers(); + return isIndexSignature() + ? parseIndexSignatureDeclaration(modifiers) + : undefined; + } + function isStartOfConstructSignature() { nextToken(); return token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken; @@ -3866,6 +3904,12 @@ module ts { } // Else parse it like identifier - fall through default: + // Functions and variable statements are allowed as a statement. But as per + // the grammar, they also allow modifiers. So we have to check for those + // statements that might be following modifiers. This ensures that things + // work properly when incrementally parsing as the parser will produce the + // same FunctionDeclaraiton or VariableStatement if it has the same text + // regardless of whether it is inside a block or not. if (isModifier(token)) { var result = tryParse(parseVariableStatementOrFunctionDeclarationWithModifiers); if (result) { @@ -4177,12 +4221,16 @@ module ts { return parseConstructorDeclaration(fullStart, modifiers); } if (isIndexSignature()) { - return parseIndexSignatureDeclaration(fullStart, modifiers); + return parseIndexSignatureDeclaration(modifiers); } // 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 (isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || - token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBracketToken) { + if (isIdentifierOrKeyword() || + token === SyntaxKind.StringLiteral || + token === SyntaxKind.NumericLiteral || + token === SyntaxKind.AsteriskToken || + token === SyntaxKind.OpenBracketToken) { + return parsePropertyOrMethodDeclaration(fullStart, modifiers); }