@@ -120,7 +120,7 @@ export class Parser extends DiagnosticEmitter {
120120 currentModuleName : string | null = null ;
121121 /** Nesting depth of source-level statements while parsing. */
122122 currentSourceStatementDepth : i32 = 0 ;
123- /** Indicates whether the current source-level statement preserved any parameter decorators . */
123+ /** Indicates whether the current source-level statement should be revisited for post-transform parameter-decorator validation . */
124124 currentSourceStatementHasParameterDecorators : bool = false ;
125125
126126 /** Constructs a new parser. */
@@ -210,15 +210,9 @@ export class Parser extends DiagnosticEmitter {
210210
211211 // check decorators
212212 let decorators : DecoratorNode [ ] | null = null ;
213- while ( tn . skip ( Token . At ) ) {
214- if ( startPos < 0 ) startPos = tn . tokenPos ;
215- let decorator = this . parseDecorator ( tn ) ;
216- if ( ! decorator ) {
217- this . skipStatement ( tn ) ;
218- continue ;
219- }
220- if ( ! decorators ) decorators = [ decorator ] ;
221- else decorators . push ( decorator ) ;
213+ if ( tn . peek ( ) == Token . At ) {
214+ startPos = tn . nextTokenPos ;
215+ decorators = this . parseDecorators ( tn , true ) ;
222216 }
223217
224218 // check modifiers
@@ -717,7 +711,7 @@ export class Parser extends DiagnosticEmitter {
717711 // Indicates whether tryParseSignature determined that it is handling a Signature
718712 private tryParseSignatureIsSignature : bool = false ;
719713
720- /** Parses a function type, preserving parameter decorators for transforms. */
714+ /** Parses a function type, preserving leading parameter decorators for transforms while still reporting misplaced ones . */
721715 tryParseFunctionType (
722716 tn : Tokenizer
723717 ) : FunctionTypeNode | null {
@@ -744,7 +738,8 @@ export class Parser extends DiagnosticEmitter {
744738 do {
745739 let paramStart = - 1 ;
746740 let kind = ParameterKind . Default ;
747- let decorators = this . parseParameterDecorators ( tn ) ;
741+ // Preserve leading parameter decorators in the AST so transforms can inspect or remove them later.
742+ let decorators = this . parseDecorators ( tn ) ;
748743 if ( decorators ) {
749744 paramStart = decorators [ 0 ] . range . start ;
750745 isSignature = true ;
@@ -915,6 +910,27 @@ export class Parser extends DiagnosticEmitter {
915910
916911 // statements
917912
913+ /** Parses zero or more decorators starting at the current token. */
914+ private parseDecorators (
915+ tn : Tokenizer ,
916+ skipStatementOnError : bool = false
917+ ) : DecoratorNode [ ] | null {
918+ let decorators : DecoratorNode [ ] | null = null ;
919+ while ( tn . skip ( Token . At ) ) {
920+ let decorator = this . parseDecorator ( tn ) ;
921+ if ( ! decorator ) {
922+ if ( skipStatementOnError ) {
923+ this . skipStatement ( tn ) ;
924+ continue ;
925+ }
926+ break ;
927+ }
928+ if ( ! decorators ) decorators = [ decorator ] ;
929+ else decorators . push ( decorator ) ;
930+ }
931+ return decorators ;
932+ }
933+
918934 parseDecorator (
919935 tn : Tokenizer
920936 ) : DecoratorNode | null {
@@ -959,23 +975,9 @@ export class Parser extends DiagnosticEmitter {
959975 return null ;
960976 }
961977
962- private parseParameterDecorators (
963- tn : Tokenizer
964- ) : DecoratorNode [ ] | null {
965- // Preserve parameter decorators in the AST so transforms can inspect or remove them later.
966- let decorators : DecoratorNode [ ] | null = null ;
967- while ( tn . skip ( Token . At ) ) {
968- let decorator = this . parseDecorator ( tn ) ;
969- if ( ! decorator ) break ;
970- if ( ! decorators ) decorators = [ decorator ] ;
971- else decorators . push ( decorator ) ;
972- }
973- return decorators ;
974- }
975-
976- /** Tries to parse decorators that appear after a parameter has already started and reports them. */
978+ /** Consumes misplaced parameter decorators after a parameter has already started so they diagnose as TS1206 instead of cascading. */
977979 private tryParseParameterDecorators ( tn : Tokenizer ) : void {
978- let decorators = this . parseParameterDecorators ( tn ) ;
980+ let decorators = this . parseDecorators ( tn ) ;
979981 if ( decorators ) {
980982 this . error (
981983 DiagnosticCode . Decorators_are_not_valid_here ,
@@ -984,7 +986,7 @@ export class Parser extends DiagnosticEmitter {
984986 }
985987 }
986988
987- /** Remembers when a source-level statement preserved parameter decorators in one of its function signatures . */
989+ /** Records source-level statements whose function signatures preserved parameter decorators for post-transform validation . */
988990 private noteFunctionTypeParameterDecorators ( signature : FunctionTypeNode ) : void {
989991 if ( signature . explicitThisDecorators ) {
990992 this . currentSourceStatementHasParameterDecorators = true ;
@@ -1303,7 +1305,7 @@ export class Parser extends DiagnosticEmitter {
13031305
13041306 /** Explicit `this` parameter captured by the current parseParameters call, if any. */
13051307 private parseParametersThis : NamedTypeNode | null = null ;
1306- /** Decorators on the explicit `this` parameter, preserved for transforms . */
1308+ /** Decorators on the explicit `this` parameter captured by the current parseParameters call. Preserved as transform-only syntax . */
13071309 private parseParametersThisDecorators : DecoratorNode [ ] | null = null ;
13081310
13091311 parseParameters (
@@ -1327,7 +1329,8 @@ export class Parser extends DiagnosticEmitter {
13271329 while ( true ) {
13281330 if ( tn . skip ( Token . CloseParen ) ) break ;
13291331
1330- let paramDecorators = this . parseParameterDecorators ( tn ) ;
1332+ // Preserve leading parameter decorators in the AST so transforms can inspect or remove them later.
1333+ let paramDecorators = this . parseDecorators ( tn ) ;
13311334
13321335 if ( first && tn . skip ( Token . This ) ) {
13331336 if ( tn . skip ( Token . Colon ) ) {
@@ -1993,14 +1996,9 @@ export class Parser extends DiagnosticEmitter {
19931996 let isInterface = parent . kind == NodeKind . InterfaceDeclaration ;
19941997 let startPos = 0 ;
19951998 let decorators : DecoratorNode [ ] | null = null ;
1996- if ( tn . skip ( Token . At ) ) {
1997- startPos = tn . tokenPos ;
1998- do {
1999- let decorator = this . parseDecorator ( tn ) ;
2000- if ( ! decorator ) break ;
2001- if ( ! decorators ) decorators = new Array ( ) ;
2002- decorators . push ( decorator ) ;
2003- } while ( tn . skip ( Token . At ) ) ;
1999+ if ( tn . peek ( ) == Token . At ) {
2000+ startPos = tn . nextTokenPos ;
2001+ decorators = this . parseDecorators ( tn ) ;
20042002 if ( isInterface && decorators ) {
20052003 this . error (
20062004 DiagnosticCode . Decorators_are_not_valid_here ,
0 commit comments