@@ -138,25 +138,27 @@ module ts {
138138 return ( < Identifier > ( < ExpressionStatement > node ) . expression ) . text === "use strict" ;
139139 }
140140
141- export function getLeadingCommentsOfNode ( node : Node , sourceFileOfNode : SourceFile ) {
141+ export function getLeadingCommentRangesOfNode ( node : Node , sourceFileOfNode ?: SourceFile ) {
142+ sourceFileOfNode = sourceFileOfNode || getSourceFileOfNode ( node ) ;
143+
142144 // If parameter/type parameter, the prev token trailing comments are part of this node too
143145 if ( node . kind === SyntaxKind . Parameter || node . kind === SyntaxKind . TypeParameter ) {
144146 // e.g. (/** blah */ a, /** blah */ b);
145- return concatenate ( getTrailingComments ( sourceFileOfNode . text , node . pos ) ,
147+ return concatenate ( getTrailingCommentRanges ( sourceFileOfNode . text , node . pos ) ,
146148 // e.g.: (
147149 // /** blah */ a,
148150 // /** blah */ b);
149- getLeadingComments ( sourceFileOfNode . text , node . pos ) ) ;
151+ getLeadingCommentRanges ( sourceFileOfNode . text , node . pos ) ) ;
150152 }
151153 else {
152- return getLeadingComments ( sourceFileOfNode . text , node . pos ) ;
154+ return getLeadingCommentRanges ( sourceFileOfNode . text , node . pos ) ;
153155 }
154156 }
155157
156158 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 ) ) ;
158160
159- function isJsDocComment ( comment : Comment ) {
161+ function isJsDocComment ( comment : CommentRange ) {
160162 // True if the comment starts with '/**' but not if it is '/**/'
161163 return sourceFileOfNode . text . charCodeAt ( comment . pos + 1 ) === CharacterCodes . asterisk &&
162164 sourceFileOfNode . text . charCodeAt ( comment . pos + 2 ) === CharacterCodes . asterisk &&
@@ -626,12 +628,6 @@ module ts {
626628 Parameters , // Parameters in parameter list
627629 }
628630
629- enum TrailingCommaBehavior {
630- Disallow ,
631- Allow ,
632- Preserve
633- }
634-
635631 // Tracks whether we nested (directly or indirectly) in a certain control block.
636632 // Used for validating break and continue statements.
637633 enum ControlBlockContext {
@@ -1203,7 +1199,7 @@ module ts {
12031199 }
12041200
12051201 // 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 > {
12071203 var saveParsingContext = parsingContext ;
12081204 parsingContext |= 1 << kind ;
12091205 var result = < NodeArray < T > > [ ] ;
@@ -1228,15 +1224,14 @@ module ts {
12281224 else if ( isListTerminator ( kind ) ) {
12291225 // Check if the last token was a comma.
12301226 if ( commaStart >= 0 ) {
1231- if ( trailingCommaBehavior === TrailingCommaBehavior . Disallow ) {
1227+ if ( ! allowTrailingComma ) {
12321228 if ( file . syntacticErrors . length === errorCountBeforeParsingList ) {
12331229 // Report a grammar error so we don't affect lookahead
12341230 grammarErrorAtPos ( commaStart , scanner . getStartPos ( ) - commaStart , Diagnostics . Trailing_comma_not_allowed ) ;
12351231 }
12361232 }
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 ;
12401235 }
12411236
12421237 break ;
@@ -1271,7 +1266,7 @@ module ts {
12711266
12721267 function parseBracketedList < T extends Node > ( kind : ParsingContext , parseElement : ( ) => T , startToken : SyntaxKind , endToken : SyntaxKind ) : NodeArray < T > {
12731268 if ( parseExpected ( startToken ) ) {
1274- var result = parseDelimitedList ( kind , parseElement , TrailingCommaBehavior . Disallow ) ;
1269+ var result = parseDelimitedList ( kind , parseElement , /*allowTrailingComma*/ false ) ;
12751270 parseExpected ( endToken ) ;
12761271 return result ;
12771272 }
@@ -2172,10 +2167,10 @@ module ts {
21722167 // The identifier eval or arguments may not appear as the LeftHandSideExpression of an
21732168 // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
21742169 // 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 ) ) {
21762171 reportInvalidUseInStrictMode ( < Identifier > operand ) ;
21772172 }
2178- else if ( token === SyntaxKind . DeleteKeyword && operand . kind === SyntaxKind . Identifier ) {
2173+ else if ( operator === SyntaxKind . DeleteKeyword && operand . kind === SyntaxKind . Identifier ) {
21792174 // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its
21802175 // UnaryExpression is a direct reference to a variable, function argument, or function name
21812176 grammarErrorOnNode ( operand , Diagnostics . delete_cannot_be_called_on_an_identifier_in_strict_mode ) ;
@@ -2307,7 +2302,11 @@ module ts {
23072302 else {
23082303 parseExpected ( SyntaxKind . OpenParenToken ) ;
23092304 }
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 ) ;
23112310 parseExpected ( SyntaxKind . CloseParenToken ) ;
23122311 expr = finishNode ( callExpr ) ;
23132312 continue ;
@@ -2376,15 +2375,33 @@ module ts {
23762375 return finishNode ( node ) ;
23772376 }
23782377
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+
23792391 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 ) ;
23812397 }
23822398
23832399 function parseArrayLiteral ( ) : ArrayLiteral {
23842400 var node = < ArrayLiteral > createNode ( SyntaxKind . ArrayLiteral ) ;
23852401 parseExpected ( SyntaxKind . OpenBracketToken ) ;
23862402 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 ) ;
23882405 parseExpected ( SyntaxKind . CloseBracketToken ) ;
23892406 return finishNode ( node ) ;
23902407 }
@@ -2426,10 +2443,7 @@ module ts {
24262443 node . flags |= NodeFlags . MultiLine ;
24272444 }
24282445
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 ) ;
24332447 parseExpected ( SyntaxKind . CloseBraceToken ) ;
24342448
24352449 var seen : Map < SymbolFlags > = { } ;
@@ -2518,7 +2532,11 @@ module ts {
25182532 parseExpected ( SyntaxKind . NewKeyword ) ;
25192533 node . func = parseCallAndAccess ( parsePrimaryExpression ( ) , /* inNewExpression */ true ) ;
25202534 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 ) ;
25222540 parseExpected ( SyntaxKind . CloseParenToken ) ;
25232541 }
25242542 return finishNode ( node ) ;
@@ -3087,7 +3105,8 @@ module ts {
30873105 }
30883106
30893107 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 ) ;
30913110 }
30923111
30933112 function parseVariableStatement ( pos ?: number , flags ?: NodeFlags ) : VariableStatement {
@@ -3486,7 +3505,8 @@ module ts {
34863505 var implementsKeywordLength : number ;
34873506 if ( parseOptional ( SyntaxKind . ImplementsKeyword ) ) {
34883507 implementsKeywordLength = scanner . getStartPos ( ) - implementsKeywordStart ;
3489- node . implementedTypes = parseDelimitedList ( ParsingContext . BaseTypeReferences , parseTypeReference , TrailingCommaBehavior . Disallow ) ;
3508+ node . implementedTypes = parseDelimitedList ( ParsingContext . BaseTypeReferences ,
3509+ parseTypeReference , /*allowTrailingComma*/ false ) ;
34903510 }
34913511 var errorCountBeforeClassBody = file . syntacticErrors . length ;
34923512 if ( parseExpected ( SyntaxKind . OpenBraceToken ) ) {
@@ -3514,7 +3534,8 @@ module ts {
35143534 var extendsKeywordLength : number ;
35153535 if ( parseOptional ( SyntaxKind . ExtendsKeyword ) ) {
35163536 extendsKeywordLength = scanner . getStartPos ( ) - extendsKeywordStart ;
3517- node . baseTypes = parseDelimitedList ( ParsingContext . BaseTypeReferences , parseTypeReference , TrailingCommaBehavior . Disallow ) ;
3537+ node . baseTypes = parseDelimitedList ( ParsingContext . BaseTypeReferences ,
3538+ parseTypeReference , /*allowTrailingComma*/ false ) ;
35183539 }
35193540 var errorCountBeforeInterfaceBody = file . syntacticErrors . length ;
35203541 node . members = parseTypeLiteral ( ) . members ;
@@ -3578,7 +3599,8 @@ module ts {
35783599 parseExpected ( SyntaxKind . EnumKeyword ) ;
35793600 node . name = parseIdentifier ( ) ;
35803601 if ( parseExpected ( SyntaxKind . OpenBraceToken ) ) {
3581- node . members = parseDelimitedList ( ParsingContext . EnumMembers , parseAndCheckEnumMember , TrailingCommaBehavior . Allow ) ;
3602+ node . members = parseDelimitedList ( ParsingContext . EnumMembers ,
3603+ parseAndCheckEnumMember , /*allowTrailingComma*/ true ) ;
35823604 parseExpected ( SyntaxKind . CloseBraceToken ) ;
35833605 }
35843606 else {
0 commit comments