Skip to content

Commit 57adf26

Browse files
committed
Cover transform-time removal of parameter decorators
Add a dedicated transform input containing the same invalid parameter-decorator forms exercised by the compiler rejection fixture. Introduce ESM and CommonJS afterInitialize transforms that walk the AST and strip parameter decorators, including explicit-this decorators on function signatures. Extend the transform test scripts to compile that input with the stripping transforms, proving no TS1206 diagnostics are emitted once transforms remove the decorators in time.
1 parent be3857d commit 57adf26

File tree

4 files changed

+667
-2
lines changed

4 files changed

+667
-2
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@
8484
"test:browser": "node --enable-source-maps tests/browser",
8585
"test:asconfig": "cd tests/asconfig && npm run test",
8686
"test:transform": "npm run test:transform:esm && npm run test:transform:cjs",
87-
"test:transform:esm": "node bin/asc tests/compiler/empty --transform ./tests/transform/index.js --noEmit && node bin/asc tests/compiler/empty --transform ./tests/transform/simple.js --noEmit",
88-
"test:transform:cjs": "node bin/asc tests/compiler/empty --transform ./tests/transform/cjs/index.js --noEmit && node bin/asc tests/compiler/empty --transform ./tests/transform/cjs/simple.js --noEmit",
87+
"test:transform:esm": "node bin/asc tests/compiler/empty --transform ./tests/transform/index.js --noEmit && node bin/asc tests/compiler/empty --transform ./tests/transform/simple.js --noEmit && node bin/asc tests/transform/parameter-decorators.ts --transform ./tests/transform/remove-parameter-decorators.js --noEmit",
88+
"test:transform:cjs": "node bin/asc tests/compiler/empty --transform ./tests/transform/cjs/index.js --noEmit && node bin/asc tests/compiler/empty --transform ./tests/transform/cjs/simple.js --noEmit && node bin/asc tests/transform/parameter-decorators.ts --transform ./tests/transform/cjs/remove-parameter-decorators.js --noEmit",
8989
"test:cli": "node tests/cli/options.js",
9090
"asbuild": "npm run asbuild:debug && npm run asbuild:release",
9191
"asbuild:debug": "node bin/asc --config src/asconfig.json --target debug",
Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
console.log("CommonJS parameter decorator removal transform loaded");
2+
3+
const NodeKind = {
4+
NamedType: 1,
5+
FunctionType: 2,
6+
Assertion: 7,
7+
Binary: 8,
8+
Call: 9,
9+
Class: 10,
10+
Comma: 11,
11+
ElementAccess: 12,
12+
Function: 14,
13+
InstanceOf: 15,
14+
Literal: 16,
15+
New: 17,
16+
Parenthesized: 20,
17+
PropertyAccess: 21,
18+
Ternary: 22,
19+
UnaryPostfix: 27,
20+
UnaryPrefix: 28,
21+
Block: 30,
22+
Do: 33,
23+
ExportDefault: 36,
24+
Expression: 38,
25+
For: 39,
26+
ForOf: 40,
27+
If: 41,
28+
Return: 43,
29+
Switch: 44,
30+
Throw: 45,
31+
Try: 46,
32+
Variable: 47,
33+
Void: 48,
34+
While: 49,
35+
ClassDeclaration: 51,
36+
EnumDeclaration: 52,
37+
FieldDeclaration: 54,
38+
FunctionDeclaration: 55,
39+
InterfaceDeclaration: 57,
40+
MethodDeclaration: 58,
41+
NamespaceDeclaration: 59,
42+
TypeDeclaration: 60,
43+
VariableDeclaration: 61
44+
};
45+
46+
const LiteralKind = {
47+
Template: 3,
48+
Array: 5,
49+
Object: 6
50+
};
51+
52+
exports.afterInitialize = (program) => {
53+
console.log("- afterInitialize strip parameter decorators");
54+
for (const source of program.sources) {
55+
clearStatements(source.statements);
56+
}
57+
};
58+
59+
function clearStatements(statements) {
60+
if (!statements) return;
61+
for (const statement of statements) {
62+
clearStatement(statement);
63+
}
64+
}
65+
66+
function clearStatement(statement) {
67+
if (!statement) return;
68+
switch (statement.kind) {
69+
case NodeKind.Block:
70+
clearStatements(statement.statements);
71+
break;
72+
case NodeKind.ClassDeclaration:
73+
case NodeKind.InterfaceDeclaration:
74+
clearClassDeclaration(statement);
75+
break;
76+
case NodeKind.Do:
77+
clearStatement(statement.body);
78+
clearExpression(statement.condition);
79+
break;
80+
case NodeKind.EnumDeclaration:
81+
for (const value of statement.values) {
82+
clearVariableLike(value);
83+
}
84+
break;
85+
case NodeKind.ExportDefault:
86+
clearDeclaration(statement.declaration);
87+
break;
88+
case NodeKind.Expression:
89+
clearExpression(statement.expression);
90+
break;
91+
case NodeKind.For:
92+
clearStatement(statement.initializer);
93+
clearExpression(statement.condition);
94+
clearExpression(statement.incrementor);
95+
clearStatement(statement.body);
96+
break;
97+
case NodeKind.ForOf:
98+
clearStatement(statement.variable);
99+
clearExpression(statement.iterable);
100+
clearStatement(statement.body);
101+
break;
102+
case NodeKind.FunctionDeclaration:
103+
case NodeKind.MethodDeclaration:
104+
clearFunctionDeclaration(statement);
105+
break;
106+
case NodeKind.If:
107+
clearExpression(statement.condition);
108+
clearStatement(statement.ifTrue);
109+
clearStatement(statement.ifFalse);
110+
break;
111+
case NodeKind.NamespaceDeclaration:
112+
clearStatements(statement.members);
113+
break;
114+
case NodeKind.Return:
115+
clearExpression(statement.value);
116+
break;
117+
case NodeKind.Switch:
118+
clearExpression(statement.condition);
119+
for (const switchCase of statement.cases) {
120+
clearExpression(switchCase.label);
121+
clearStatements(switchCase.statements);
122+
}
123+
break;
124+
case NodeKind.Throw:
125+
clearExpression(statement.value);
126+
break;
127+
case NodeKind.Try:
128+
clearStatements(statement.bodyStatements);
129+
clearStatements(statement.catchStatements);
130+
clearStatements(statement.finallyStatements);
131+
break;
132+
case NodeKind.TypeDeclaration:
133+
clearTypeDeclaration(statement);
134+
break;
135+
case NodeKind.Variable:
136+
for (const declaration of statement.declarations) {
137+
clearVariableLike(declaration);
138+
}
139+
break;
140+
case NodeKind.Void:
141+
clearExpression(statement.expression);
142+
break;
143+
case NodeKind.While:
144+
clearExpression(statement.condition);
145+
clearStatement(statement.body);
146+
break;
147+
}
148+
}
149+
150+
function clearDeclaration(declaration) {
151+
if (!declaration) return;
152+
switch (declaration.kind) {
153+
case NodeKind.ClassDeclaration:
154+
case NodeKind.InterfaceDeclaration:
155+
clearClassDeclaration(declaration);
156+
break;
157+
case NodeKind.EnumDeclaration:
158+
for (const value of declaration.values) {
159+
clearVariableLike(value);
160+
}
161+
break;
162+
case NodeKind.FieldDeclaration:
163+
case NodeKind.VariableDeclaration:
164+
clearVariableLike(declaration);
165+
break;
166+
case NodeKind.FunctionDeclaration:
167+
case NodeKind.MethodDeclaration:
168+
clearFunctionDeclaration(declaration);
169+
break;
170+
case NodeKind.NamespaceDeclaration:
171+
clearStatements(declaration.members);
172+
break;
173+
case NodeKind.TypeDeclaration:
174+
clearTypeDeclaration(declaration);
175+
break;
176+
}
177+
}
178+
179+
function clearClassDeclaration(declaration) {
180+
clearTypeParameters(declaration.typeParameters);
181+
clearType(declaration.extendsType);
182+
clearTypes(declaration.implementsTypes);
183+
clearIndexSignature(declaration.indexSignature);
184+
for (const member of declaration.members) {
185+
clearDeclaration(member);
186+
}
187+
}
188+
189+
function clearFunctionDeclaration(declaration) {
190+
clearTypeParameters(declaration.typeParameters);
191+
clearFunctionType(declaration.signature);
192+
clearStatement(declaration.body);
193+
}
194+
195+
function clearTypeDeclaration(declaration) {
196+
clearTypeParameters(declaration.typeParameters);
197+
clearType(declaration.type);
198+
}
199+
200+
function clearVariableLike(declaration) {
201+
clearType(declaration.type);
202+
clearExpression(declaration.initializer);
203+
}
204+
205+
function clearExpression(expression) {
206+
if (!expression) return;
207+
switch (expression.kind) {
208+
case NodeKind.Assertion:
209+
clearExpression(expression.expression);
210+
clearType(expression.toType);
211+
break;
212+
case NodeKind.Binary:
213+
clearExpression(expression.left);
214+
clearExpression(expression.right);
215+
break;
216+
case NodeKind.Call:
217+
clearExpression(expression.expression);
218+
clearTypes(expression.typeArguments);
219+
clearExpressions(expression.args);
220+
break;
221+
case NodeKind.Class:
222+
clearClassDeclaration(expression.declaration);
223+
break;
224+
case NodeKind.Comma:
225+
clearExpressions(expression.expressions);
226+
break;
227+
case NodeKind.ElementAccess:
228+
clearExpression(expression.expression);
229+
clearExpression(expression.elementExpression);
230+
break;
231+
case NodeKind.Function:
232+
clearFunctionDeclaration(expression.declaration);
233+
break;
234+
case NodeKind.InstanceOf:
235+
clearExpression(expression.expression);
236+
clearType(expression.isType);
237+
break;
238+
case NodeKind.Literal:
239+
clearLiteral(expression);
240+
break;
241+
case NodeKind.New:
242+
clearTypes(expression.typeArguments);
243+
clearExpressions(expression.args);
244+
break;
245+
case NodeKind.Parenthesized:
246+
clearExpression(expression.expression);
247+
break;
248+
case NodeKind.PropertyAccess:
249+
clearExpression(expression.expression);
250+
break;
251+
case NodeKind.Ternary:
252+
clearExpression(expression.condition);
253+
clearExpression(expression.ifThen);
254+
clearExpression(expression.ifElse);
255+
break;
256+
case NodeKind.UnaryPostfix:
257+
case NodeKind.UnaryPrefix:
258+
clearExpression(expression.operand);
259+
break;
260+
}
261+
}
262+
263+
function clearExpressions(expressions) {
264+
if (!expressions) return;
265+
for (const expression of expressions) {
266+
clearExpression(expression);
267+
}
268+
}
269+
270+
function clearLiteral(literal) {
271+
switch (literal.literalKind) {
272+
case LiteralKind.Array:
273+
clearExpressions(literal.elementExpressions);
274+
break;
275+
case LiteralKind.Object:
276+
clearExpressions(literal.values);
277+
break;
278+
case LiteralKind.Template:
279+
clearExpressions(literal.expressions);
280+
break;
281+
}
282+
}
283+
284+
function clearType(type) {
285+
if (!type) return;
286+
switch (type.kind) {
287+
case NodeKind.NamedType:
288+
clearTypes(type.typeArguments);
289+
break;
290+
case NodeKind.FunctionType:
291+
clearFunctionType(type);
292+
break;
293+
}
294+
}
295+
296+
function clearTypes(types) {
297+
if (!types) return;
298+
for (const type of types) {
299+
clearType(type);
300+
}
301+
}
302+
303+
function clearTypeParameters(typeParameters) {
304+
if (!typeParameters) return;
305+
for (const typeParameter of typeParameters) {
306+
clearType(typeParameter.extendsType);
307+
clearType(typeParameter.defaultType);
308+
}
309+
}
310+
311+
function clearIndexSignature(indexSignature) {
312+
if (!indexSignature) return;
313+
clearType(indexSignature.keyType);
314+
clearType(indexSignature.valueType);
315+
}
316+
317+
function clearFunctionType(signature) {
318+
if (!signature) return;
319+
signature.explicitThisDecorators = null;
320+
clearType(signature.explicitThisType);
321+
for (const parameter of signature.parameters) {
322+
parameter.decorators = null;
323+
clearType(parameter.type);
324+
clearExpression(parameter.initializer);
325+
}
326+
clearType(signature.returnType);
327+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function regular(@first value: i32): void {}
2+
function withthis(@self this: i32, @rest ...values: i32[]): i32 { return this; }
3+
4+
class Box {
5+
constructor(@field public value: i32) {}
6+
method(@arg value: i32): void {}
7+
}
8+
9+
type Callback = (@arg value: i32) => void;
10+
const expression = function(@arg value: i32): void {};
11+
const arrow = (@arg value: i32): void => {};

0 commit comments

Comments
 (0)