@@ -138,25 +138,27 @@ module ts {
138
138
return ( < Identifier > ( < ExpressionStatement > node ) . expression ) . text === "use strict" ;
139
139
}
140
140
141
- export function getLeadingCommentsOfNode ( node : Node , sourceFileOfNode : SourceFile ) {
141
+ export function getLeadingCommentRangesOfNode ( node : Node , sourceFileOfNode ?: SourceFile ) {
142
+ sourceFileOfNode = sourceFileOfNode || getSourceFileOfNode ( node ) ;
143
+
142
144
// If parameter/type parameter, the prev token trailing comments are part of this node too
143
145
if ( node . kind === SyntaxKind . Parameter || node . kind === SyntaxKind . TypeParameter ) {
144
146
// e.g. (/** blah */ a, /** blah */ b);
145
- return concatenate ( getTrailingComments ( sourceFileOfNode . text , node . pos ) ,
147
+ return concatenate ( getTrailingCommentRanges ( sourceFileOfNode . text , node . pos ) ,
146
148
// e.g.: (
147
149
// /** blah */ a,
148
150
// /** blah */ b);
149
- getLeadingComments ( sourceFileOfNode . text , node . pos ) ) ;
151
+ getLeadingCommentRanges ( sourceFileOfNode . text , node . pos ) ) ;
150
152
}
151
153
else {
152
- return getLeadingComments ( sourceFileOfNode . text , node . pos ) ;
154
+ return getLeadingCommentRanges ( sourceFileOfNode . text , node . pos ) ;
153
155
}
154
156
}
155
157
156
158
export function getJsDocComments ( node : Declaration , sourceFileOfNode : SourceFile ) {
157
- return filter ( getLeadingCommentsOfNode ( node , sourceFileOfNode ) , comment => isJsDocComment ( comment ) ) ;
159
+ return filter ( getLeadingCommentRangesOfNode ( node , sourceFileOfNode ) , comment => isJsDocComment ( comment ) ) ;
158
160
159
- function isJsDocComment ( comment : Comment ) {
161
+ function isJsDocComment ( comment : CommentRange ) {
160
162
// True if the comment starts with '/**' but not if it is '/**/'
161
163
return sourceFileOfNode . text . charCodeAt ( comment . pos + 1 ) === CharacterCodes . asterisk &&
162
164
sourceFileOfNode . text . charCodeAt ( comment . pos + 2 ) === CharacterCodes . asterisk &&
@@ -626,12 +628,6 @@ module ts {
626
628
Parameters , // Parameters in parameter list
627
629
}
628
630
629
- enum TrailingCommaBehavior {
630
- Disallow ,
631
- Allow ,
632
- Preserve
633
- }
634
-
635
631
// Tracks whether we nested (directly or indirectly) in a certain control block.
636
632
// Used for validating break and continue statements.
637
633
enum ControlBlockContext {
@@ -1203,7 +1199,7 @@ module ts {
1203
1199
}
1204
1200
1205
1201
// Parses a comma-delimited list of elements
1206
- function parseDelimitedList < T extends Node > ( kind : ParsingContext , parseElement : ( ) => T , trailingCommaBehavior : TrailingCommaBehavior ) : NodeArray < T > {
1202
+ function parseDelimitedList < T extends Node > ( kind : ParsingContext , parseElement : ( ) => T , allowTrailingComma : boolean ) : NodeArray < T > {
1207
1203
var saveParsingContext = parsingContext ;
1208
1204
parsingContext |= 1 << kind ;
1209
1205
var result = < NodeArray < T > > [ ] ;
@@ -1228,15 +1224,14 @@ module ts {
1228
1224
else if ( isListTerminator ( kind ) ) {
1229
1225
// Check if the last token was a comma.
1230
1226
if ( commaStart >= 0 ) {
1231
- if ( trailingCommaBehavior === TrailingCommaBehavior . Disallow ) {
1227
+ if ( ! allowTrailingComma ) {
1232
1228
if ( file . syntacticErrors . length === errorCountBeforeParsingList ) {
1233
1229
// Report a grammar error so we don't affect lookahead
1234
1230
grammarErrorAtPos ( commaStart , scanner . getStartPos ( ) - commaStart , Diagnostics . Trailing_comma_not_allowed ) ;
1235
1231
}
1236
1232
}
1237
- else if ( trailingCommaBehavior === TrailingCommaBehavior . Preserve ) {
1238
- result . push ( < T > createNode ( SyntaxKind . OmittedExpression ) ) ;
1239
- }
1233
+ // Always preserve a trailing comma by marking it on the NodeArray
1234
+ result . hasTrailingComma = true ;
1240
1235
}
1241
1236
1242
1237
break ;
@@ -1271,7 +1266,7 @@ module ts {
1271
1266
1272
1267
function parseBracketedList < T extends Node > ( kind : ParsingContext , parseElement : ( ) => T , startToken : SyntaxKind , endToken : SyntaxKind ) : NodeArray < T > {
1273
1268
if ( parseExpected ( startToken ) ) {
1274
- var result = parseDelimitedList ( kind , parseElement , TrailingCommaBehavior . Disallow ) ;
1269
+ var result = parseDelimitedList ( kind , parseElement , /*allowTrailingComma*/ false ) ;
1275
1270
parseExpected ( endToken ) ;
1276
1271
return result ;
1277
1272
}
@@ -2172,10 +2167,10 @@ module ts {
2172
2167
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
2173
2168
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
2174
2169
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator
2175
- if ( ( token === SyntaxKind . PlusPlusToken || token === SyntaxKind . MinusMinusToken ) && isEvalOrArgumentsIdentifier ( operand ) ) {
2170
+ if ( ( operator === SyntaxKind . PlusPlusToken || operator === SyntaxKind . MinusMinusToken ) && isEvalOrArgumentsIdentifier ( operand ) ) {
2176
2171
reportInvalidUseInStrictMode ( < Identifier > operand ) ;
2177
2172
}
2178
- else if ( token === SyntaxKind . DeleteKeyword && operand . kind === SyntaxKind . Identifier ) {
2173
+ else if ( operator === SyntaxKind . DeleteKeyword && operand . kind === SyntaxKind . Identifier ) {
2179
2174
// When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
2180
2175
// UnaryExpression is a direct reference to a variable, function argument, or function name
2181
2176
grammarErrorOnNode ( operand , Diagnostics . delete_cannot_be_called_on_an_identifier_in_strict_mode ) ;
@@ -2307,7 +2302,11 @@ module ts {
2307
2302
else {
2308
2303
parseExpected ( SyntaxKind . OpenParenToken ) ;
2309
2304
}
2310
- callExpr . arguments = parseDelimitedList ( ParsingContext . ArgumentExpressions , parseAssignmentExpression , TrailingCommaBehavior . Disallow ) ;
2305
+ // It is an error to have a trailing comma in an argument list. However, the checker
2306
+ // needs evidence of a trailing comma in order to give good results for signature help.
2307
+ // That is why we do not allow a trailing comma, but we "preserve" a trailing comma.
2308
+ callExpr . arguments = parseDelimitedList ( ParsingContext . ArgumentExpressions ,
2309
+ parseArgumentExpression , /*allowTrailingComma*/ false ) ;
2311
2310
parseExpected ( SyntaxKind . CloseParenToken ) ;
2312
2311
expr = finishNode ( callExpr ) ;
2313
2312
continue ;
@@ -2376,15 +2375,33 @@ module ts {
2376
2375
return finishNode ( node ) ;
2377
2376
}
2378
2377
2378
+ function parseAssignmentExpressionOrOmittedExpression ( omittedExpressionDiagnostic : DiagnosticMessage ) : Expression {
2379
+ if ( token === SyntaxKind . CommaToken ) {
2380
+ if ( omittedExpressionDiagnostic ) {
2381
+ var errorStart = scanner . getTokenPos ( ) ;
2382
+ var errorLength = scanner . getTextPos ( ) - errorStart ;
2383
+ grammarErrorAtPos ( errorStart , errorLength , omittedExpressionDiagnostic ) ;
2384
+ }
2385
+ return createNode ( SyntaxKind . OmittedExpression ) ;
2386
+ }
2387
+
2388
+ return parseAssignmentExpression ( ) ;
2389
+ }
2390
+
2379
2391
function parseArrayLiteralElement ( ) : Expression {
2380
- return token === SyntaxKind . CommaToken ? createNode ( SyntaxKind . OmittedExpression ) : parseAssignmentExpression ( ) ;
2392
+ return parseAssignmentExpressionOrOmittedExpression ( /*omittedExpressionDiagnostic*/ undefined ) ;
2393
+ }
2394
+
2395
+ function parseArgumentExpression ( ) : Expression {
2396
+ return parseAssignmentExpressionOrOmittedExpression ( Diagnostics . Argument_expression_expected ) ;
2381
2397
}
2382
2398
2383
2399
function parseArrayLiteral ( ) : ArrayLiteral {
2384
2400
var node = < ArrayLiteral > createNode ( SyntaxKind . ArrayLiteral ) ;
2385
2401
parseExpected ( SyntaxKind . OpenBracketToken ) ;
2386
2402
if ( scanner . hasPrecedingLineBreak ( ) ) node . flags |= NodeFlags . MultiLine ;
2387
- node . elements = parseDelimitedList ( ParsingContext . ArrayLiteralMembers , parseArrayLiteralElement , TrailingCommaBehavior . Preserve ) ;
2403
+ node . elements = parseDelimitedList ( ParsingContext . ArrayLiteralMembers ,
2404
+ parseArrayLiteralElement , /*allowTrailingComma*/ true ) ;
2388
2405
parseExpected ( SyntaxKind . CloseBracketToken ) ;
2389
2406
return finishNode ( node ) ;
2390
2407
}
@@ -2426,10 +2443,7 @@ module ts {
2426
2443
node . flags |= NodeFlags . MultiLine ;
2427
2444
}
2428
2445
2429
- // ES3 itself does not accept a trailing comma in an object literal, however, we'd like to preserve it in ES5.
2430
- var trailingCommaBehavior = languageVersion === ScriptTarget . ES3 ? TrailingCommaBehavior . Allow : TrailingCommaBehavior . Preserve ;
2431
-
2432
- node . properties = parseDelimitedList ( ParsingContext . ObjectLiteralMembers , parseObjectLiteralMember , trailingCommaBehavior ) ;
2446
+ node . properties = parseDelimitedList ( ParsingContext . ObjectLiteralMembers , parseObjectLiteralMember , /*allowTrailingComma*/ true ) ;
2433
2447
parseExpected ( SyntaxKind . CloseBraceToken ) ;
2434
2448
2435
2449
var seen : Map < SymbolFlags > = { } ;
@@ -2518,7 +2532,11 @@ module ts {
2518
2532
parseExpected ( SyntaxKind . NewKeyword ) ;
2519
2533
node . func = parseCallAndAccess ( parsePrimaryExpression ( ) , /* inNewExpression */ true ) ;
2520
2534
if ( parseOptional ( SyntaxKind . OpenParenToken ) || token === SyntaxKind . LessThanToken && ( node . typeArguments = tryParse ( parseTypeArgumentsAndOpenParen ) ) ) {
2521
- node . arguments = parseDelimitedList ( ParsingContext . ArgumentExpressions , parseAssignmentExpression , TrailingCommaBehavior . Disallow ) ;
2535
+ // It is an error to have a trailing comma in an argument list. However, the checker
2536
+ // needs evidence of a trailing comma in order to give good results for signature help.
2537
+ // That is why we do not allow a trailing comma, but we "preserve" a trailing comma.
2538
+ node . arguments = parseDelimitedList ( ParsingContext . ArgumentExpressions ,
2539
+ parseArgumentExpression , /*allowTrailingComma*/ false ) ;
2522
2540
parseExpected ( SyntaxKind . CloseParenToken ) ;
2523
2541
}
2524
2542
return finishNode ( node ) ;
@@ -3087,7 +3105,8 @@ module ts {
3087
3105
}
3088
3106
3089
3107
function parseVariableDeclarationList ( flags : NodeFlags , noIn ?: boolean ) : NodeArray < VariableDeclaration > {
3090
- return parseDelimitedList ( ParsingContext . VariableDeclarations , ( ) => parseVariableDeclaration ( flags , noIn ) , TrailingCommaBehavior . Disallow ) ;
3108
+ return parseDelimitedList ( ParsingContext . VariableDeclarations ,
3109
+ ( ) => parseVariableDeclaration ( flags , noIn ) , /*allowTrailingComma*/ false ) ;
3091
3110
}
3092
3111
3093
3112
function parseVariableStatement ( pos ?: number , flags ?: NodeFlags ) : VariableStatement {
@@ -3486,7 +3505,8 @@ module ts {
3486
3505
var implementsKeywordLength : number ;
3487
3506
if ( parseOptional ( SyntaxKind . ImplementsKeyword ) ) {
3488
3507
implementsKeywordLength = scanner . getStartPos ( ) - implementsKeywordStart ;
3489
- node . implementedTypes = parseDelimitedList ( ParsingContext . BaseTypeReferences , parseTypeReference , TrailingCommaBehavior . Disallow ) ;
3508
+ node . implementedTypes = parseDelimitedList ( ParsingContext . BaseTypeReferences ,
3509
+ parseTypeReference , /*allowTrailingComma*/ false ) ;
3490
3510
}
3491
3511
var errorCountBeforeClassBody = file . syntacticErrors . length ;
3492
3512
if ( parseExpected ( SyntaxKind . OpenBraceToken ) ) {
@@ -3514,7 +3534,8 @@ module ts {
3514
3534
var extendsKeywordLength : number ;
3515
3535
if ( parseOptional ( SyntaxKind . ExtendsKeyword ) ) {
3516
3536
extendsKeywordLength = scanner . getStartPos ( ) - extendsKeywordStart ;
3517
- node . baseTypes = parseDelimitedList ( ParsingContext . BaseTypeReferences , parseTypeReference , TrailingCommaBehavior . Disallow ) ;
3537
+ node . baseTypes = parseDelimitedList ( ParsingContext . BaseTypeReferences ,
3538
+ parseTypeReference , /*allowTrailingComma*/ false ) ;
3518
3539
}
3519
3540
var errorCountBeforeInterfaceBody = file . syntacticErrors . length ;
3520
3541
node . members = parseTypeLiteral ( ) . members ;
@@ -3578,7 +3599,8 @@ module ts {
3578
3599
parseExpected ( SyntaxKind . EnumKeyword ) ;
3579
3600
node . name = parseIdentifier ( ) ;
3580
3601
if ( parseExpected ( SyntaxKind . OpenBraceToken ) ) {
3581
- node . members = parseDelimitedList ( ParsingContext . EnumMembers , parseAndCheckEnumMember , TrailingCommaBehavior . Allow ) ;
3602
+ node . members = parseDelimitedList ( ParsingContext . EnumMembers ,
3603
+ parseAndCheckEnumMember , /*allowTrailingComma*/ true ) ;
3582
3604
parseExpected ( SyntaxKind . CloseBraceToken ) ;
3583
3605
}
3584
3606
else {
0 commit comments