Skip to content

Commit 932cb9e

Browse files
committed
Clarify transform-only parameter decorator contract
1 parent 57adf26 commit 932cb9e

File tree

4 files changed

+15
-9
lines changed

4 files changed

+15
-9
lines changed

src/ast.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@ export class FunctionTypeNode extends TypeNode {
930930
super(NodeKind.FunctionType, isNullable, range);
931931
}
932932

933-
/** Decorators on an explicit `this` parameter, if any. */
933+
/** Decorators on an explicit `this` parameter, if any, preserved for transforms. */
934934
explicitThisDecorators: DecoratorNode[] | null = null;
935935
}
936936

@@ -977,7 +977,7 @@ export class ParameterNode extends Node {
977977
super(NodeKind.Parameter, range);
978978
}
979979

980-
/** Decorators, if any. */
980+
/** Decorators, if any, preserved so transforms can rewrite them before validation. */
981981
decorators: DecoratorNode[] | null = null;
982982
/** Implicit field declaration, if applicable. */
983983
implicitFieldDeclaration: FieldDeclaration | null = null;

src/compiler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@ export class Compiler extends DiagnosticEmitter {
536536

537537
// initialize lookup maps, built-ins, imports, exports, etc.
538538
this.program.initialize();
539+
// Reject any parameter decorators that transforms left on the AST.
539540
this.program.validateParameterDecorators();
540541

541542

src/parser.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -698,12 +698,13 @@ export class Parser extends DiagnosticEmitter {
698698
// Indicates whether tryParseSignature determined that it is handling a Signature
699699
private tryParseSignatureIsSignature: bool = false;
700700

701-
/** Parses a function type, as used in type declarations. */
701+
/** Parses a function type, preserving parameter decorators for transforms. */
702702
tryParseFunctionType(
703703
tn: Tokenizer
704704
): FunctionTypeNode | null {
705705

706-
// at '(': ('...'? Identifier '?'? ':' Type (',' '...'? Identifier '?'? ':' Type)* )? ')' '=>' Type
706+
// at '(': (Decorator* ('...'? Identifier '?'? ':' Type | this ':' Type)
707+
// (',' Decorator* ('...'? Identifier '?'? ':' Type | this ':' Type))* )? ')' '=>' Type
707708

708709
let state = tn.mark();
709710
let startPos = tn.tokenPos;
@@ -937,6 +938,7 @@ export class Parser extends DiagnosticEmitter {
937938
private parseParameterDecorators(
938939
tn: Tokenizer
939940
): DecoratorNode[] | null {
941+
// Preserve parameter decorators in the AST so transforms can inspect or remove them later.
940942
let decorators: DecoratorNode[] | null = null;
941943
while (tn.skip(Token.At)) {
942944
let decorator = this.parseDecorator(tn);
@@ -1249,23 +1251,25 @@ export class Parser extends DiagnosticEmitter {
12491251
return null;
12501252
}
12511253

1254+
/** Explicit `this` parameter captured by the current parseParameters call, if any. */
12521255
private parseParametersThis: NamedTypeNode | null = null;
1256+
/** Decorators on the explicit `this` parameter, preserved for transforms. */
12531257
private parseParametersThisDecorators: DecoratorNode[] | null = null;
12541258

12551259
parseParameters(
12561260
tn: Tokenizer,
12571261
isConstructor: bool = false
12581262
): ParameterNode[] | null {
12591263

1260-
// at '(': (Parameter (',' Parameter)*)? ')'
1264+
// at '(': (Decorator* Parameter (',' Decorator* Parameter)*)? ')'
12611265

12621266
let parameters = new Array<ParameterNode>();
12631267
let seenRest: ParameterNode | null = null;
12641268
let seenOptional = false;
12651269
let reportedRest = false;
12661270
let thisType: TypeNode | null = null;
12671271

1268-
// check if there is a leading `this` parameter
1272+
// check if there is a leading `this` parameter, preserving any decorators on it
12691273
this.parseParametersThis = null;
12701274
this.parseParametersThisDecorators = null;
12711275

@@ -1361,7 +1365,8 @@ export class Parser extends DiagnosticEmitter {
13611365
decorators: DecoratorNode[] | null = null
13621366
): ParameterNode | null {
13631367

1364-
// before: ('public' | 'private' | 'protected' | '...')? Identifier '?'? (':' Type)? ('=' Expression)?
1368+
// before: Decorator* ('public' | 'private' | 'protected' | 'readonly')? '...'? Identifier
1369+
// '?'? (':' Type)? ('=' Expression)?
13651370

13661371
let isRest = false;
13671372
let isOptional = false;

src/program.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ export class Program extends DiagnosticEmitter {
495495
nextSignatureId: i32 = 0;
496496
/** An indicator if the program has been initialized. */
497497
initialized: bool = false;
498-
/** An indicator if parameter decorators have been validated. */
498+
/** Indicates whether the one-shot post-transform parameter decorator validation has run. */
499499
parameterDecoratorsValidated: bool = false;
500500

501501
// Lookup maps
@@ -1532,7 +1532,7 @@ export class Program extends DiagnosticEmitter {
15321532
}
15331533
}
15341534

1535-
/** Validates that no parameter decorators survive past transform time. */
1535+
/** Rejects parameter decorators that survive transform time. These remain transform-only syntax. */
15361536
validateParameterDecorators(): void {
15371537
if (this.parameterDecoratorsValidated) return;
15381538
this.parameterDecoratorsValidated = true;

0 commit comments

Comments
 (0)