as-test 0.4.4 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +196 -82
- package/as-test.config.schema.json +137 -0
- package/assembly/coverage.ts +19 -0
- package/assembly/index.ts +172 -85
- package/assembly/src/expectation.ts +263 -199
- package/assembly/src/log.ts +1 -9
- package/assembly/src/suite.ts +61 -25
- package/assembly/src/tests.ts +2 -0
- package/assembly/util/wipc.ts +286 -0
- package/bin/build.js +86 -41
- package/bin/index.js +337 -68
- package/bin/init.js +441 -183
- package/bin/reporter.js +1 -1
- package/bin/reporters/default.js +379 -0
- package/bin/reporters/types.js +1 -0
- package/bin/run.js +882 -194
- package/bin/types.js +14 -7
- package/bin/util.js +54 -3
- package/package.json +34 -16
- package/transform/lib/builder.js +169 -169
- package/transform/lib/builder.js.map +1 -1
- package/transform/lib/coverage.js +47 -1
- package/transform/lib/coverage.js.map +1 -1
- package/transform/lib/index.js +70 -0
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/location.js +20 -0
- package/transform/lib/location.js.map +1 -0
- package/transform/lib/log.js +118 -0
- package/transform/lib/log.js.map +1 -0
- package/transform/lib/mock.js +2 -2
- package/transform/lib/mock.js.map +1 -1
- package/transform/lib/util.js +3 -3
- package/transform/lib/util.js.map +1 -1
- package/.github/workflows/as-test.yml +0 -26
- package/.prettierrc +0 -3
- package/as-test.config.json +0 -19
- package/assembly/__tests__/array.spec.ts +0 -25
- package/assembly/__tests__/math.spec.ts +0 -16
- package/assembly/__tests__/mock.spec.ts +0 -22
- package/assembly/__tests__/mock.ts +0 -7
- package/assembly/__tests__/sleep.spec.ts +0 -28
- package/assembly/tsconfig.json +0 -97
- package/assets/img/screenshot.png +0 -0
- package/cli/build.ts +0 -117
- package/cli/index.ts +0 -190
- package/cli/init.ts +0 -247
- package/cli/reporter.ts +0 -1
- package/cli/run.ts +0 -286
- package/cli/tsconfig.json +0 -9
- package/cli/types.ts +0 -29
- package/cli/util.ts +0 -65
- package/run/package.json +0 -27
- package/tests/array.run.js +0 -7
- package/tests/math.run.js +0 -7
- package/tests/mock.run.js +0 -14
- package/tests/sleep.run.js +0 -7
- package/transform/src/builder.ts +0 -1474
- package/transform/src/coverage.ts +0 -580
- package/transform/src/index.ts +0 -73
- package/transform/src/linker.ts +0 -41
- package/transform/src/mock.ts +0 -163
- package/transform/src/range.ts +0 -12
- package/transform/src/types.ts +0 -35
- package/transform/src/util.ts +0 -81
- package/transform/src/visitor.ts +0 -744
- package/transform/tsconfig.json +0 -10
|
@@ -1,580 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Source,
|
|
3
|
-
Statement,
|
|
4
|
-
Token,
|
|
5
|
-
BinaryExpression,
|
|
6
|
-
CommaExpression,
|
|
7
|
-
ParenthesizedExpression,
|
|
8
|
-
ParameterNode,
|
|
9
|
-
BlockStatement,
|
|
10
|
-
ExpressionStatement,
|
|
11
|
-
FunctionDeclaration,
|
|
12
|
-
IfStatement,
|
|
13
|
-
MethodDeclaration,
|
|
14
|
-
ReturnStatement,
|
|
15
|
-
SwitchCase,
|
|
16
|
-
TernaryExpression,
|
|
17
|
-
NodeKind,
|
|
18
|
-
ArrowKind,
|
|
19
|
-
Node,
|
|
20
|
-
} from "assemblyscript/dist/assemblyscript.js";
|
|
21
|
-
import { RangeTransform } from "./range.js";
|
|
22
|
-
import { isStdlib, SimpleParser } from "./util.js";
|
|
23
|
-
import { Visitor } from "./visitor.js";
|
|
24
|
-
|
|
25
|
-
enum CoverType {
|
|
26
|
-
Function,
|
|
27
|
-
Expression,
|
|
28
|
-
Block,
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
class CoverPoint {
|
|
32
|
-
public file: string = "";
|
|
33
|
-
public hash: string = "";
|
|
34
|
-
public line: number = 0;
|
|
35
|
-
public column: number = 0;
|
|
36
|
-
public type!: CoverType;
|
|
37
|
-
public executed: boolean = false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export class CoverageTransform extends Visitor {
|
|
41
|
-
public mustImport: boolean = false;
|
|
42
|
-
public points: Map<string, CoverPoint> = new Map<string, CoverPoint>();
|
|
43
|
-
public globalStatements: Statement[] = [];
|
|
44
|
-
visitBinaryExpression(node: BinaryExpression): void {
|
|
45
|
-
super.visitBinaryExpression(node);
|
|
46
|
-
// @ts-ignore
|
|
47
|
-
if (node.visited) return;
|
|
48
|
-
// @ts-ignore
|
|
49
|
-
node.visited = true;
|
|
50
|
-
const path = node.range.source.normalizedPath;
|
|
51
|
-
|
|
52
|
-
switch (node.operator) {
|
|
53
|
-
case Token.Bar_Bar:
|
|
54
|
-
case Token.Ampersand_Ampersand: {
|
|
55
|
-
const right = node.right;
|
|
56
|
-
const rightLc = getLineCol(node);
|
|
57
|
-
|
|
58
|
-
const point = new CoverPoint();
|
|
59
|
-
point.line = rightLc?.line!;
|
|
60
|
-
point.column = rightLc?.column!;
|
|
61
|
-
point.file = path;
|
|
62
|
-
point.type = CoverType.Expression;
|
|
63
|
-
|
|
64
|
-
point.hash = hash(point);
|
|
65
|
-
|
|
66
|
-
const replacer = new RangeTransform(node);
|
|
67
|
-
const registerStmt = SimpleParser.parseTopLevelStatement(
|
|
68
|
-
`__REGISTER({
|
|
69
|
-
file: "${point.file}",
|
|
70
|
-
hash: "${point.hash}",
|
|
71
|
-
line: ${point.line},
|
|
72
|
-
column: ${point.column},
|
|
73
|
-
type: "Expression",
|
|
74
|
-
executed: false
|
|
75
|
-
});`,
|
|
76
|
-
);
|
|
77
|
-
replacer.visit(registerStmt);
|
|
78
|
-
|
|
79
|
-
let coverExpression = SimpleParser.parseExpression(
|
|
80
|
-
`(__COVER("${point.hash}"), $$REPLACE_ME)`,
|
|
81
|
-
) as ParenthesizedExpression;
|
|
82
|
-
replacer.visit(coverExpression);
|
|
83
|
-
|
|
84
|
-
(coverExpression.expression as CommaExpression).expressions[1] = right;
|
|
85
|
-
|
|
86
|
-
node.right = coverExpression;
|
|
87
|
-
|
|
88
|
-
this.globalStatements.push(registerStmt);
|
|
89
|
-
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
visitMethodDeclaration(node: MethodDeclaration): void {
|
|
95
|
-
super.visitMethodDeclaration(node);
|
|
96
|
-
// @ts-ignore
|
|
97
|
-
if (node.visited) return;
|
|
98
|
-
// @ts-ignore
|
|
99
|
-
node.visited = true;
|
|
100
|
-
if (node.body) {
|
|
101
|
-
// @ts-ignore
|
|
102
|
-
if (node.body.visited) return;
|
|
103
|
-
// @ts-ignore
|
|
104
|
-
node.body.visited = true;
|
|
105
|
-
const path = node.range.source.normalizedPath;
|
|
106
|
-
const funcLc = getLineCol(node);
|
|
107
|
-
|
|
108
|
-
const point = new CoverPoint();
|
|
109
|
-
point.line = funcLc?.line!;
|
|
110
|
-
point.column = funcLc?.column!;
|
|
111
|
-
point.file = path;
|
|
112
|
-
point.type = CoverType.Function;
|
|
113
|
-
|
|
114
|
-
point.hash = hash(point);
|
|
115
|
-
|
|
116
|
-
const replacer = new RangeTransform(node);
|
|
117
|
-
const registerStmt = SimpleParser.parseTopLevelStatement(
|
|
118
|
-
`__REGISTER({
|
|
119
|
-
file: "${point.file}",
|
|
120
|
-
hash: "${point.hash}",
|
|
121
|
-
line: ${point.line},
|
|
122
|
-
column: ${point.column},
|
|
123
|
-
type: "Function",
|
|
124
|
-
executed: false
|
|
125
|
-
})`,
|
|
126
|
-
);
|
|
127
|
-
replacer.visit(registerStmt);
|
|
128
|
-
|
|
129
|
-
const coverStmt = SimpleParser.parseStatement(
|
|
130
|
-
`__COVER("${point.hash}")`,
|
|
131
|
-
true,
|
|
132
|
-
);
|
|
133
|
-
replacer.visit(coverStmt);
|
|
134
|
-
|
|
135
|
-
const bodyBlock = node.body as BlockStatement;
|
|
136
|
-
bodyBlock.statements.unshift(coverStmt);
|
|
137
|
-
|
|
138
|
-
this.globalStatements.push(registerStmt);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
visitParameter(node: ParameterNode): void {
|
|
142
|
-
// @ts-ignore
|
|
143
|
-
if (node.visited) return;
|
|
144
|
-
// @ts-ignore
|
|
145
|
-
node.visited = true;
|
|
146
|
-
const path = node.range.source.normalizedPath;
|
|
147
|
-
if (node.initializer) {
|
|
148
|
-
// @ts-ignore
|
|
149
|
-
if (node.initializer.visited) return;
|
|
150
|
-
// @ts-ignore
|
|
151
|
-
node.initializer.visited = true;
|
|
152
|
-
super.visitParameter(node);
|
|
153
|
-
const paramLc = getLineCol(node.initializer);
|
|
154
|
-
|
|
155
|
-
const point = new CoverPoint();
|
|
156
|
-
point.line = paramLc?.line!;
|
|
157
|
-
point.column = paramLc?.column!;
|
|
158
|
-
point.file = path;
|
|
159
|
-
point.type = CoverType.Expression;
|
|
160
|
-
|
|
161
|
-
point.hash = hash(point);
|
|
162
|
-
|
|
163
|
-
const replacer = new RangeTransform(node);
|
|
164
|
-
const registerStmt = SimpleParser.parseTopLevelStatement(
|
|
165
|
-
`__REGISTER({
|
|
166
|
-
file: "${point.file}",
|
|
167
|
-
hash: "${point.hash}",
|
|
168
|
-
line: ${point.line},
|
|
169
|
-
column: ${point.column},
|
|
170
|
-
type: "Expression",
|
|
171
|
-
executed: false
|
|
172
|
-
})`,
|
|
173
|
-
);
|
|
174
|
-
replacer.visit(registerStmt);
|
|
175
|
-
|
|
176
|
-
const coverExpression = SimpleParser.parseExpression(
|
|
177
|
-
`(__COVER("${point.hash}"), $$REPLACE_ME)`,
|
|
178
|
-
) as ParenthesizedExpression;
|
|
179
|
-
replacer.visit(coverExpression);
|
|
180
|
-
|
|
181
|
-
(coverExpression.expression as CommaExpression).expressions[1] =
|
|
182
|
-
node.initializer;
|
|
183
|
-
|
|
184
|
-
node.initializer = coverExpression;
|
|
185
|
-
|
|
186
|
-
this.globalStatements.push(registerStmt);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
visitFunctionDeclaration(
|
|
190
|
-
node: FunctionDeclaration,
|
|
191
|
-
isDefault?: boolean | undefined,
|
|
192
|
-
): void {
|
|
193
|
-
super.visitFunctionDeclaration(node, isDefault);
|
|
194
|
-
// @ts-ignore
|
|
195
|
-
if (node.visited) return;
|
|
196
|
-
// @ts-ignore
|
|
197
|
-
node.visited = true;
|
|
198
|
-
if (node.body) {
|
|
199
|
-
// @ts-ignore
|
|
200
|
-
if (node.body.visited) return;
|
|
201
|
-
// @ts-ignore
|
|
202
|
-
node.body.visited = true;
|
|
203
|
-
|
|
204
|
-
const path = node.range.source.normalizedPath;
|
|
205
|
-
const funcLc = getLineCol(node);
|
|
206
|
-
const point = new CoverPoint();
|
|
207
|
-
point.line = funcLc?.line!;
|
|
208
|
-
point.column = funcLc?.column!;
|
|
209
|
-
point.file = path;
|
|
210
|
-
point.type = CoverType.Function;
|
|
211
|
-
|
|
212
|
-
point.hash = hash(point);
|
|
213
|
-
|
|
214
|
-
const replacer = new RangeTransform(node);
|
|
215
|
-
const registerStmt = SimpleParser.parseTopLevelStatement(
|
|
216
|
-
`__REGISTER({
|
|
217
|
-
file: "${point.file}",
|
|
218
|
-
hash: "${point.hash}",
|
|
219
|
-
line: ${point.line},
|
|
220
|
-
column: ${point.column},
|
|
221
|
-
type: "Function",
|
|
222
|
-
executed: false
|
|
223
|
-
})`,
|
|
224
|
-
);
|
|
225
|
-
replacer.visit(registerStmt);
|
|
226
|
-
|
|
227
|
-
this.globalStatements.push(registerStmt);
|
|
228
|
-
|
|
229
|
-
if (node.body.kind === NodeKind.Export) {
|
|
230
|
-
const coverStmt = SimpleParser.parseStatement(`{
|
|
231
|
-
__COVER("${point.hash}")
|
|
232
|
-
return $$REPLACE_ME
|
|
233
|
-
}`) as BlockStatement;
|
|
234
|
-
replacer.visit(coverStmt);
|
|
235
|
-
|
|
236
|
-
const bodyReturn = coverStmt.statements[1] as ReturnStatement;
|
|
237
|
-
const body = node.body as ExpressionStatement;
|
|
238
|
-
node.arrowKind = ArrowKind.Single;
|
|
239
|
-
bodyReturn.value = body.expression;
|
|
240
|
-
node.body = body;
|
|
241
|
-
} else {
|
|
242
|
-
const coverStmt = SimpleParser.parseStatement(
|
|
243
|
-
`__COVER("${point.hash}")`,
|
|
244
|
-
true,
|
|
245
|
-
);
|
|
246
|
-
replacer.visit(coverStmt);
|
|
247
|
-
|
|
248
|
-
if (node.body instanceof BlockStatement) {
|
|
249
|
-
node.body.statements.unshift(coverStmt);
|
|
250
|
-
} else if (node.body instanceof ExpressionStatement) {
|
|
251
|
-
const expression = (node.body as ExpressionStatement).expression;
|
|
252
|
-
node.body = Node.createBlockStatement(
|
|
253
|
-
[Node.createReturnStatement(expression, expression.range)],
|
|
254
|
-
expression.range,
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
const bodyBlock = node.body as BlockStatement;
|
|
258
|
-
bodyBlock.statements.unshift(coverStmt);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
visitIfStatement(node: IfStatement): void {
|
|
264
|
-
// @ts-ignore
|
|
265
|
-
if (node.visited) return;
|
|
266
|
-
// @ts-ignore
|
|
267
|
-
node.visited = true;
|
|
268
|
-
let visitIfTrue = false;
|
|
269
|
-
let visitIfFalse = false;
|
|
270
|
-
|
|
271
|
-
const ifTrue = node.ifTrue;
|
|
272
|
-
const ifFalse = node.ifFalse;
|
|
273
|
-
|
|
274
|
-
const path = node.range.source.normalizedPath;
|
|
275
|
-
|
|
276
|
-
if (ifTrue.kind !== NodeKind.Block) {
|
|
277
|
-
const trueLc = getLineCol(ifTrue);
|
|
278
|
-
const point = new CoverPoint();
|
|
279
|
-
|
|
280
|
-
point.line = trueLc?.line!;
|
|
281
|
-
point.column = trueLc?.column!;
|
|
282
|
-
point.file = path;
|
|
283
|
-
point.type = CoverType.Expression;
|
|
284
|
-
|
|
285
|
-
point.hash = hash(point);
|
|
286
|
-
|
|
287
|
-
const replacer = new RangeTransform(ifTrue);
|
|
288
|
-
|
|
289
|
-
const registerStmt = SimpleParser.parseTopLevelStatement(
|
|
290
|
-
`__REGISTER({
|
|
291
|
-
file: "${point.file}",
|
|
292
|
-
hash: "${point.hash}",
|
|
293
|
-
line: ${point.line},
|
|
294
|
-
column: ${point.column},
|
|
295
|
-
type: "Expression",
|
|
296
|
-
executed: false
|
|
297
|
-
})`,
|
|
298
|
-
);
|
|
299
|
-
replacer.visit(registerStmt);
|
|
300
|
-
|
|
301
|
-
const coverStmt = SimpleParser.parseStatement(
|
|
302
|
-
`{__COVER("${point.hash}")};`,
|
|
303
|
-
true,
|
|
304
|
-
) as BlockStatement;
|
|
305
|
-
replacer.visit(coverStmt);
|
|
306
|
-
|
|
307
|
-
coverStmt.statements.push(ifTrue);
|
|
308
|
-
node.ifTrue = coverStmt;
|
|
309
|
-
|
|
310
|
-
this.globalStatements.push(registerStmt);
|
|
311
|
-
|
|
312
|
-
visitIfTrue = true;
|
|
313
|
-
visitIfFalse = !!ifFalse;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (ifFalse && ifFalse.kind !== NodeKind.Block) {
|
|
317
|
-
const falseLc = getLineCol(ifFalse);
|
|
318
|
-
const point = new CoverPoint();
|
|
319
|
-
|
|
320
|
-
point.line = falseLc?.line!;
|
|
321
|
-
point.column = falseLc?.column!;
|
|
322
|
-
point.file = path;
|
|
323
|
-
point.type = CoverType.Expression;
|
|
324
|
-
|
|
325
|
-
point.hash = hash(point);
|
|
326
|
-
|
|
327
|
-
const replacer = new RangeTransform(ifTrue);
|
|
328
|
-
|
|
329
|
-
const registerStmt = SimpleParser.parseTopLevelStatement(
|
|
330
|
-
`__REGISTER({
|
|
331
|
-
file: "${point.file}",
|
|
332
|
-
hash: "${point.hash}",
|
|
333
|
-
line: ${point.line},
|
|
334
|
-
column: ${point.column},
|
|
335
|
-
type: "Expression",
|
|
336
|
-
executed: false
|
|
337
|
-
})`,
|
|
338
|
-
);
|
|
339
|
-
replacer.visit(registerStmt);
|
|
340
|
-
|
|
341
|
-
const coverStmt = SimpleParser.parseStatement(
|
|
342
|
-
`{__COVER("${point.hash}")};`,
|
|
343
|
-
true,
|
|
344
|
-
) as BlockStatement;
|
|
345
|
-
replacer.visit(coverStmt);
|
|
346
|
-
|
|
347
|
-
coverStmt.statements.push(ifFalse);
|
|
348
|
-
node.ifFalse = coverStmt;
|
|
349
|
-
|
|
350
|
-
this.globalStatements.push(registerStmt);
|
|
351
|
-
|
|
352
|
-
visitIfTrue = true;
|
|
353
|
-
visitIfFalse = true;
|
|
354
|
-
}
|
|
355
|
-
if (visitIfTrue || visitIfFalse) {
|
|
356
|
-
if (visitIfTrue) {
|
|
357
|
-
// @ts-ignore
|
|
358
|
-
if (ifTrue.visited) return;
|
|
359
|
-
// @ts-ignore
|
|
360
|
-
ifTrue.visited = true;
|
|
361
|
-
this.visit(ifTrue);
|
|
362
|
-
}
|
|
363
|
-
if (visitIfFalse) {
|
|
364
|
-
// @ts-ignore
|
|
365
|
-
if (ifFalse.visited) return;
|
|
366
|
-
// @ts-ignore
|
|
367
|
-
ifFalse.visited = true;
|
|
368
|
-
this.visit(ifFalse!);
|
|
369
|
-
}
|
|
370
|
-
} else {
|
|
371
|
-
super.visitIfStatement(node);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
visitTernaryExpression(node: TernaryExpression): void {
|
|
375
|
-
// @ts-ignore
|
|
376
|
-
if (node.visited) return;
|
|
377
|
-
// @ts-ignore
|
|
378
|
-
node.visited = true;
|
|
379
|
-
super.visitTernaryExpression(node);
|
|
380
|
-
|
|
381
|
-
const trueExpression = node.ifThen;
|
|
382
|
-
const falseExpression = node.ifElse;
|
|
383
|
-
|
|
384
|
-
const path = node.range.source.normalizedPath;
|
|
385
|
-
{
|
|
386
|
-
const trueLc = getLineCol(trueExpression);
|
|
387
|
-
const point = new CoverPoint();
|
|
388
|
-
point.line = trueLc?.line!;
|
|
389
|
-
point.column = trueLc?.column!;
|
|
390
|
-
point.file = path;
|
|
391
|
-
point.type = CoverType.Expression;
|
|
392
|
-
|
|
393
|
-
point.hash = hash(point);
|
|
394
|
-
|
|
395
|
-
const replacer = new RangeTransform(trueExpression);
|
|
396
|
-
|
|
397
|
-
const registerStmt = SimpleParser.parseTopLevelStatement(
|
|
398
|
-
`__REGISTER({
|
|
399
|
-
file: "${point.file}",
|
|
400
|
-
hash: "${point.hash}",
|
|
401
|
-
line: ${point.line},
|
|
402
|
-
column: ${point.column},
|
|
403
|
-
type: "Expression",
|
|
404
|
-
executed: false
|
|
405
|
-
})`,
|
|
406
|
-
);
|
|
407
|
-
replacer.visit(registerStmt);
|
|
408
|
-
|
|
409
|
-
const coverExpression = SimpleParser.parseExpression(
|
|
410
|
-
`(__COVER("${point.hash}"), $$REPLACE_ME)`,
|
|
411
|
-
) as ParenthesizedExpression;
|
|
412
|
-
replacer.visit(coverExpression);
|
|
413
|
-
|
|
414
|
-
(coverExpression.expression as CommaExpression).expressions[1] =
|
|
415
|
-
trueExpression;
|
|
416
|
-
node.ifThen = coverExpression;
|
|
417
|
-
|
|
418
|
-
this.globalStatements.push(registerStmt);
|
|
419
|
-
}
|
|
420
|
-
{
|
|
421
|
-
const falseLc = getLineCol(falseExpression);
|
|
422
|
-
const point = new CoverPoint();
|
|
423
|
-
point.line = falseLc?.line!;
|
|
424
|
-
point.column = falseLc?.column!;
|
|
425
|
-
point.file = path;
|
|
426
|
-
point.type = CoverType.Expression;
|
|
427
|
-
|
|
428
|
-
point.hash = hash(point);
|
|
429
|
-
|
|
430
|
-
const replacer = new RangeTransform(falseExpression);
|
|
431
|
-
|
|
432
|
-
const registerStmt = SimpleParser.parseTopLevelStatement(
|
|
433
|
-
`__REGISTER({
|
|
434
|
-
file: "${point.file}",
|
|
435
|
-
hash: "${point.hash}",
|
|
436
|
-
line: ${point.line},
|
|
437
|
-
column: ${point.column},
|
|
438
|
-
type: "Expression",
|
|
439
|
-
executed: false
|
|
440
|
-
})`,
|
|
441
|
-
);
|
|
442
|
-
replacer.visit(registerStmt);
|
|
443
|
-
|
|
444
|
-
const coverExpression = SimpleParser.parseExpression(
|
|
445
|
-
`(__COVER("${point.hash}"), $$REPLACE_ME)`,
|
|
446
|
-
) as ParenthesizedExpression;
|
|
447
|
-
replacer.visit(coverExpression);
|
|
448
|
-
|
|
449
|
-
(coverExpression.expression as CommaExpression).expressions[1] =
|
|
450
|
-
falseExpression;
|
|
451
|
-
node.ifElse = coverExpression;
|
|
452
|
-
this.globalStatements.push(registerStmt);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
visitSwitchCase(node: SwitchCase): void {
|
|
456
|
-
// @ts-ignore
|
|
457
|
-
if (node.visited) return;
|
|
458
|
-
// @ts-ignore
|
|
459
|
-
node.visited = true;
|
|
460
|
-
const path = node.range.source.normalizedPath;
|
|
461
|
-
const caseLc = getLineCol(node);
|
|
462
|
-
|
|
463
|
-
const point = new CoverPoint();
|
|
464
|
-
point.line = caseLc?.line!;
|
|
465
|
-
point.column = caseLc?.column!;
|
|
466
|
-
point.file = path;
|
|
467
|
-
point.type = CoverType.Block;
|
|
468
|
-
|
|
469
|
-
point.hash = hash(point);
|
|
470
|
-
|
|
471
|
-
const replacer = new RangeTransform(node);
|
|
472
|
-
|
|
473
|
-
const registerStmt = SimpleParser.parseTopLevelStatement(
|
|
474
|
-
`__REGISTER({
|
|
475
|
-
file: "${point.file}",
|
|
476
|
-
hash: "${point.hash}",
|
|
477
|
-
line: ${point.line},
|
|
478
|
-
column: ${point.column},
|
|
479
|
-
type: "Block",
|
|
480
|
-
executed: false
|
|
481
|
-
})`,
|
|
482
|
-
);
|
|
483
|
-
replacer.visit(registerStmt);
|
|
484
|
-
|
|
485
|
-
const coverStmt = SimpleParser.parseStatement(`__COVER("${point.hash}")`);
|
|
486
|
-
replacer.visit(coverStmt);
|
|
487
|
-
|
|
488
|
-
this.globalStatements.push(registerStmt);
|
|
489
|
-
super.visitSwitchCase(node);
|
|
490
|
-
node.statements.unshift(coverStmt);
|
|
491
|
-
}
|
|
492
|
-
visitBlockStatement(node: BlockStatement): void {
|
|
493
|
-
// @ts-ignore
|
|
494
|
-
if (node.visited) return;
|
|
495
|
-
// @ts-ignore
|
|
496
|
-
node.visited = true;
|
|
497
|
-
const path = node.range.source.normalizedPath;
|
|
498
|
-
|
|
499
|
-
const blockLc = getLineCol(node);
|
|
500
|
-
|
|
501
|
-
const point = new CoverPoint();
|
|
502
|
-
point.line = blockLc?.line!;
|
|
503
|
-
point.column = blockLc?.column!;
|
|
504
|
-
point.file = path;
|
|
505
|
-
point.type = CoverType.Block;
|
|
506
|
-
|
|
507
|
-
point.hash = hash(point);
|
|
508
|
-
|
|
509
|
-
const replacer = new RangeTransform(node);
|
|
510
|
-
|
|
511
|
-
const registerStmt = SimpleParser.parseTopLevelStatement(
|
|
512
|
-
`__REGISTER({
|
|
513
|
-
file: "${point.file}",
|
|
514
|
-
hash: "${point.hash}",
|
|
515
|
-
line: ${point.line},
|
|
516
|
-
column: ${point.column},
|
|
517
|
-
type: "Block",
|
|
518
|
-
executed: false
|
|
519
|
-
})`,
|
|
520
|
-
);
|
|
521
|
-
replacer.visit(registerStmt);
|
|
522
|
-
|
|
523
|
-
const coverStmt = SimpleParser.parseStatement(`__COVER("${point.hash}")`);
|
|
524
|
-
replacer.visit(coverStmt);
|
|
525
|
-
|
|
526
|
-
this.globalStatements.push(registerStmt);
|
|
527
|
-
super.visitBlockStatement(node);
|
|
528
|
-
node.statements.unshift(coverStmt);
|
|
529
|
-
}
|
|
530
|
-
visitSource(node: Source): void {
|
|
531
|
-
if (node.isLibrary) return;
|
|
532
|
-
if (node.simplePath === "coverage") return;
|
|
533
|
-
// Ignore all lib and std. Visit everything else.
|
|
534
|
-
if (isStdlib(node)) return;
|
|
535
|
-
super.visitSource(node);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
/**
|
|
540
|
-
* A simple djb2hash that returns a hash of a given string. See http://www.cse.yorku.ca/~oz/hash.html
|
|
541
|
-
* for implementation details.
|
|
542
|
-
*
|
|
543
|
-
* @param {string} str - The string to be hashed
|
|
544
|
-
* @returns {number} The hash of the string
|
|
545
|
-
*/
|
|
546
|
-
function djb2Hash(str: string): number {
|
|
547
|
-
const points = Array.from(str);
|
|
548
|
-
let h = 5381;
|
|
549
|
-
for (let p = 0; p < points.length; p++)
|
|
550
|
-
// h = (h * 31 + c) | 0;
|
|
551
|
-
h = ((h << 5) - h + points[p]!.codePointAt(0)!) | 0;
|
|
552
|
-
return h;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
function hash(point: CoverPoint): string {
|
|
556
|
-
const hsh = djb2Hash(
|
|
557
|
-
point.file +
|
|
558
|
-
point.line.toString() +
|
|
559
|
-
point.column.toString() +
|
|
560
|
-
point.type.toString(),
|
|
561
|
-
);
|
|
562
|
-
if (hsh < 0) {
|
|
563
|
-
const out = hsh.toString(16);
|
|
564
|
-
return "3" + out.slice(1);
|
|
565
|
-
} else {
|
|
566
|
-
return hsh.toString(16);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
class LineColumn {
|
|
571
|
-
public line!: number;
|
|
572
|
-
public column!: number;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
function getLineCol(node: Node): LineColumn {
|
|
576
|
-
return {
|
|
577
|
-
line: node.range.source.lineAt(node.range.start),
|
|
578
|
-
column: node.range.source.columnAt(),
|
|
579
|
-
};
|
|
580
|
-
}
|
package/transform/src/index.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { Transform } from "assemblyscript/dist/transform.js";
|
|
2
|
-
import {
|
|
3
|
-
CommonFlags,
|
|
4
|
-
Node,
|
|
5
|
-
Parser,
|
|
6
|
-
SourceKind,
|
|
7
|
-
Source,
|
|
8
|
-
Tokenizer,
|
|
9
|
-
} from "assemblyscript/dist/assemblyscript.js";
|
|
10
|
-
import { CoverageTransform } from "./coverage.js";
|
|
11
|
-
import { MockTransform } from "./mock.js";
|
|
12
|
-
import { isStdlib } from "./util.js";
|
|
13
|
-
|
|
14
|
-
export default class Transformer extends Transform {
|
|
15
|
-
// Trigger the transform after parse.
|
|
16
|
-
afterParse(parser: Parser): void {
|
|
17
|
-
// Create new transform
|
|
18
|
-
const mock = new MockTransform();
|
|
19
|
-
const coverage = new CoverageTransform();
|
|
20
|
-
|
|
21
|
-
// Sort the sources so that user scripts are visited last
|
|
22
|
-
const sources = parser.sources
|
|
23
|
-
.filter((source) => !isStdlib(source))
|
|
24
|
-
.sort((_a, _b) => {
|
|
25
|
-
const a = _a.internalPath;
|
|
26
|
-
const b = _b.internalPath;
|
|
27
|
-
if (a[0] === "~" && b[0] !== "~") {
|
|
28
|
-
return -1;
|
|
29
|
-
} else if (a[0] !== "~" && b[0] === "~") {
|
|
30
|
-
return 1;
|
|
31
|
-
} else {
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
const entryFile = sources.find(
|
|
36
|
-
(v) => v.sourceKind == SourceKind.UserEntry,
|
|
37
|
-
).simplePath;
|
|
38
|
-
// Loop over every source
|
|
39
|
-
for (const source of sources) {
|
|
40
|
-
const node = Node.createVariableStatement(
|
|
41
|
-
null,
|
|
42
|
-
[
|
|
43
|
-
Node.createVariableDeclaration(
|
|
44
|
-
Node.createIdentifierExpression("ENTRY_FILE", source.range),
|
|
45
|
-
null,
|
|
46
|
-
CommonFlags.Const,
|
|
47
|
-
null,
|
|
48
|
-
Node.createStringLiteralExpression(entryFile + ".ts", source.range),
|
|
49
|
-
source.range,
|
|
50
|
-
),
|
|
51
|
-
],
|
|
52
|
-
source.range,
|
|
53
|
-
);
|
|
54
|
-
source.statements.unshift(node);
|
|
55
|
-
mock.visit(source);
|
|
56
|
-
coverage.visit(source);
|
|
57
|
-
if (coverage.globalStatements.length) {
|
|
58
|
-
source.statements.unshift(...coverage.globalStatements);
|
|
59
|
-
const tokenizer = new Tokenizer(
|
|
60
|
-
new Source(
|
|
61
|
-
SourceKind.User,
|
|
62
|
-
source.normalizedPath,
|
|
63
|
-
'import { __REGISTER, __COVER } from "as-test/assembly/coverage";',
|
|
64
|
-
),
|
|
65
|
-
);
|
|
66
|
-
parser.currentSource = tokenizer.source;
|
|
67
|
-
source.statements.unshift(parser.parseTopLevelStatement(tokenizer)!);
|
|
68
|
-
parser.currentSource = source;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
coverage.globalStatements = [];
|
|
72
|
-
}
|
|
73
|
-
}
|
package/transform/src/linker.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ClassDeclaration,
|
|
3
|
-
ImportStatement,
|
|
4
|
-
NodeKind,
|
|
5
|
-
Parser,
|
|
6
|
-
Source,
|
|
7
|
-
} from "assemblyscript/dist/assemblyscript.js";
|
|
8
|
-
|
|
9
|
-
export function getImports(source: Source): ImportStatement[] {
|
|
10
|
-
return source.statements.filter(
|
|
11
|
-
(v) => v.kind === NodeKind.Import,
|
|
12
|
-
) as ImportStatement[];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function getImportedClass(
|
|
16
|
-
name: string,
|
|
17
|
-
source: Source,
|
|
18
|
-
parser: Parser,
|
|
19
|
-
): ClassDeclaration | null {
|
|
20
|
-
for (const stmt of getImports(source)) {
|
|
21
|
-
const externalSource = parser.sources.find(
|
|
22
|
-
(src) => src.internalPath === stmt.internalPath,
|
|
23
|
-
);
|
|
24
|
-
if (!externalSource) continue;
|
|
25
|
-
|
|
26
|
-
const classDeclaration = externalSource.statements.find(
|
|
27
|
-
(s) =>
|
|
28
|
-
s.kind === NodeKind.ClassDeclaration &&
|
|
29
|
-
(<ClassDeclaration>s).name.text === name,
|
|
30
|
-
) as ClassDeclaration | null;
|
|
31
|
-
|
|
32
|
-
if (classDeclaration) return classDeclaration;
|
|
33
|
-
}
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function getClasses(source: Source): ClassDeclaration[] {
|
|
38
|
-
return source.statements.filter(
|
|
39
|
-
(v) => v.kind === NodeKind.ClassDeclaration,
|
|
40
|
-
) as ClassDeclaration[];
|
|
41
|
-
}
|