@d-es-ign/stryker-js-instrumenter 9.6.0
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/LICENSE +201 -0
- package/dist/src/create-instrumenter.d.ts +16 -0
- package/dist/src/create-instrumenter.d.ts.map +1 -0
- package/dist/src/create-instrumenter.js +15 -0
- package/dist/src/create-instrumenter.js.map +1 -0
- package/dist/src/disable-type-checks.d.ts +11 -0
- package/dist/src/disable-type-checks.d.ts.map +1 -0
- package/dist/src/disable-type-checks.js +125 -0
- package/dist/src/disable-type-checks.js.map +1 -0
- package/dist/src/file.d.ts +6 -0
- package/dist/src/file.d.ts.map +1 -0
- package/dist/src/file.js +2 -0
- package/dist/src/file.js.map +1 -0
- package/dist/src/frameworks/angular-ignorer.d.ts +16 -0
- package/dist/src/frameworks/angular-ignorer.d.ts.map +1 -0
- package/dist/src/frameworks/angular-ignorer.js +85 -0
- package/dist/src/frameworks/angular-ignorer.js.map +1 -0
- package/dist/src/frameworks/index.d.ts +4 -0
- package/dist/src/frameworks/index.d.ts.map +1 -0
- package/dist/src/frameworks/index.js +7 -0
- package/dist/src/frameworks/index.js.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +8 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/instrument-result.d.ts +7 -0
- package/dist/src/instrument-result.d.ts.map +1 -0
- package/dist/src/instrument-result.js +2 -0
- package/dist/src/instrument-result.js.map +1 -0
- package/dist/src/instrumenter-options.d.ts +5 -0
- package/dist/src/instrumenter-options.d.ts.map +1 -0
- package/dist/src/instrumenter-options.js +2 -0
- package/dist/src/instrumenter-options.js.map +1 -0
- package/dist/src/instrumenter-tokens.d.ts +6 -0
- package/dist/src/instrumenter-tokens.d.ts.map +1 -0
- package/dist/src/instrumenter-tokens.js +6 -0
- package/dist/src/instrumenter-tokens.js.map +1 -0
- package/dist/src/instrumenter.d.ts +24 -0
- package/dist/src/instrumenter.d.ts.map +1 -0
- package/dist/src/instrumenter.js +76 -0
- package/dist/src/instrumenter.js.map +1 -0
- package/dist/src/mutant-placers/expression-mutant-placer.d.ts +10 -0
- package/dist/src/mutant-placers/expression-mutant-placer.d.ts.map +1 -0
- package/dist/src/mutant-placers/expression-mutant-placer.js +144 -0
- package/dist/src/mutant-placers/expression-mutant-placer.js.map +1 -0
- package/dist/src/mutant-placers/index.d.ts +5 -0
- package/dist/src/mutant-placers/index.d.ts.map +1 -0
- package/dist/src/mutant-placers/index.js +11 -0
- package/dist/src/mutant-placers/index.js.map +1 -0
- package/dist/src/mutant-placers/mutant-placer.d.ts +8 -0
- package/dist/src/mutant-placers/mutant-placer.d.ts.map +1 -0
- package/dist/src/mutant-placers/mutant-placer.js +2 -0
- package/dist/src/mutant-placers/mutant-placer.js.map +1 -0
- package/dist/src/mutant-placers/statement-mutant-placer.d.ts +8 -0
- package/dist/src/mutant-placers/statement-mutant-placer.d.ts.map +1 -0
- package/dist/src/mutant-placers/statement-mutant-placer.js +24 -0
- package/dist/src/mutant-placers/statement-mutant-placer.js.map +1 -0
- package/dist/src/mutant-placers/switch-case-mutant-placer.d.ts +14 -0
- package/dist/src/mutant-placers/switch-case-mutant-placer.d.ts.map +1 -0
- package/dist/src/mutant-placers/switch-case-mutant-placer.js +29 -0
- package/dist/src/mutant-placers/switch-case-mutant-placer.js.map +1 -0
- package/dist/src/mutant-placers/throw-placement-error.d.ts +5 -0
- package/dist/src/mutant-placers/throw-placement-error.d.ts.map +1 -0
- package/dist/src/mutant-placers/throw-placement-error.js +17 -0
- package/dist/src/mutant-placers/throw-placement-error.js.map +1 -0
- package/dist/src/mutant.d.ts +27 -0
- package/dist/src/mutant.d.ts.map +1 -0
- package/dist/src/mutant.js +80 -0
- package/dist/src/mutant.js.map +1 -0
- package/dist/src/mutators/arithmetic-operator-mutator.d.ts +3 -0
- package/dist/src/mutators/arithmetic-operator-mutator.d.ts.map +1 -0
- package/dist/src/mutators/arithmetic-operator-mutator.js +34 -0
- package/dist/src/mutators/arithmetic-operator-mutator.js.map +1 -0
- package/dist/src/mutators/array-declaration-mutator.d.ts +3 -0
- package/dist/src/mutators/array-declaration-mutator.d.ts.map +1 -0
- package/dist/src/mutators/array-declaration-mutator.js +26 -0
- package/dist/src/mutators/array-declaration-mutator.js.map +1 -0
- package/dist/src/mutators/arrow-function-mutator.d.ts +3 -0
- package/dist/src/mutators/arrow-function-mutator.d.ts.map +1 -0
- package/dist/src/mutators/arrow-function-mutator.js +14 -0
- package/dist/src/mutators/arrow-function-mutator.js.map +1 -0
- package/dist/src/mutators/assignment-operator-mutator.d.ts +3 -0
- package/dist/src/mutators/assignment-operator-mutator.d.ts.map +1 -0
- package/dist/src/mutators/assignment-operator-mutator.js +42 -0
- package/dist/src/mutators/assignment-operator-mutator.js.map +1 -0
- package/dist/src/mutators/block-statement-mutator.d.ts +3 -0
- package/dist/src/mutators/block-statement-mutator.d.ts.map +1 -0
- package/dist/src/mutators/block-statement-mutator.js +63 -0
- package/dist/src/mutators/block-statement-mutator.js.map +1 -0
- package/dist/src/mutators/boolean-literal-mutator.d.ts +3 -0
- package/dist/src/mutators/boolean-literal-mutator.d.ts.map +1 -0
- package/dist/src/mutators/boolean-literal-mutator.js +17 -0
- package/dist/src/mutators/boolean-literal-mutator.js.map +1 -0
- package/dist/src/mutators/conditional-expression-mutator.d.ts +3 -0
- package/dist/src/mutators/conditional-expression-mutator.d.ts.map +1 -0
- package/dist/src/mutators/conditional-expression-mutator.js +81 -0
- package/dist/src/mutators/conditional-expression-mutator.js.map +1 -0
- package/dist/src/mutators/equality-operator-mutator.d.ts +3 -0
- package/dist/src/mutators/equality-operator-mutator.d.ts.map +1 -0
- package/dist/src/mutators/equality-operator-mutator.js +28 -0
- package/dist/src/mutators/equality-operator-mutator.js.map +1 -0
- package/dist/src/mutators/index.d.ts +4 -0
- package/dist/src/mutators/index.d.ts.map +1 -0
- package/dist/src/mutators/index.js +4 -0
- package/dist/src/mutators/index.js.map +1 -0
- package/dist/src/mutators/logical-operator-mutator.d.ts +3 -0
- package/dist/src/mutators/logical-operator-mutator.d.ts.map +1 -0
- package/dist/src/mutators/logical-operator-mutator.js +21 -0
- package/dist/src/mutators/logical-operator-mutator.js.map +1 -0
- package/dist/src/mutators/method-expression-mutator.d.ts +3 -0
- package/dist/src/mutators/method-expression-mutator.d.ts.map +1 -0
- package/dist/src/mutators/method-expression-mutator.js +65 -0
- package/dist/src/mutators/method-expression-mutator.js.map +1 -0
- package/dist/src/mutators/mutate.d.ts +3 -0
- package/dist/src/mutators/mutate.d.ts.map +1 -0
- package/dist/src/mutators/mutate.js +35 -0
- package/dist/src/mutators/mutate.js.map +1 -0
- package/dist/src/mutators/mutator-options.d.ts +5 -0
- package/dist/src/mutators/mutator-options.d.ts.map +1 -0
- package/dist/src/mutators/mutator-options.js +2 -0
- package/dist/src/mutators/mutator-options.js.map +1 -0
- package/dist/src/mutators/node-mutator.d.ts +6 -0
- package/dist/src/mutators/node-mutator.d.ts.map +1 -0
- package/dist/src/mutators/node-mutator.js +2 -0
- package/dist/src/mutators/node-mutator.js.map +1 -0
- package/dist/src/mutators/object-literal-mutator.d.ts +3 -0
- package/dist/src/mutators/object-literal-mutator.d.ts.map +1 -0
- package/dist/src/mutators/object-literal-mutator.js +11 -0
- package/dist/src/mutators/object-literal-mutator.js.map +1 -0
- package/dist/src/mutators/optional-chaining-mutator.d.ts +15 -0
- package/dist/src/mutators/optional-chaining-mutator.d.ts.map +1 -0
- package/dist/src/mutators/optional-chaining-mutator.js +28 -0
- package/dist/src/mutators/optional-chaining-mutator.js.map +1 -0
- package/dist/src/mutators/regex-mutator.d.ts +3 -0
- package/dist/src/mutators/regex-mutator.d.ts.map +1 -0
- package/dist/src/mutators/regex-mutator.js +53 -0
- package/dist/src/mutators/regex-mutator.js.map +1 -0
- package/dist/src/mutators/string-literal-mutator.d.ts +3 -0
- package/dist/src/mutators/string-literal-mutator.d.ts.map +1 -0
- package/dist/src/mutators/string-literal-mutator.js +36 -0
- package/dist/src/mutators/string-literal-mutator.js.map +1 -0
- package/dist/src/mutators/unary-operator-mutator.d.ts +3 -0
- package/dist/src/mutators/unary-operator-mutator.d.ts.map +1 -0
- package/dist/src/mutators/unary-operator-mutator.js +27 -0
- package/dist/src/mutators/unary-operator-mutator.js.map +1 -0
- package/dist/src/mutators/update-operator-mutator.d.ts +3 -0
- package/dist/src/mutators/update-operator-mutator.d.ts.map +1 -0
- package/dist/src/mutators/update-operator-mutator.js +17 -0
- package/dist/src/mutators/update-operator-mutator.js.map +1 -0
- package/dist/src/parsers/create-parser.d.ts +5 -0
- package/dist/src/parsers/create-parser.d.ts.map +1 -0
- package/dist/src/parsers/create-parser.js +58 -0
- package/dist/src/parsers/create-parser.js.map +1 -0
- package/dist/src/parsers/html-parser.d.ts +4 -0
- package/dist/src/parsers/html-parser.d.ts.map +1 -0
- package/dist/src/parsers/html-parser.js +96 -0
- package/dist/src/parsers/html-parser.js.map +1 -0
- package/dist/src/parsers/index.d.ts +5 -0
- package/dist/src/parsers/index.d.ts.map +1 -0
- package/dist/src/parsers/index.js +3 -0
- package/dist/src/parsers/index.js.map +1 -0
- package/dist/src/parsers/js-parser.d.ts +4 -0
- package/dist/src/parsers/js-parser.d.ts.map +1 -0
- package/dist/src/parsers/js-parser.js +50 -0
- package/dist/src/parsers/js-parser.js.map +1 -0
- package/dist/src/parsers/parse-error.d.ts +5 -0
- package/dist/src/parsers/parse-error.d.ts.map +1 -0
- package/dist/src/parsers/parse-error.js +6 -0
- package/dist/src/parsers/parse-error.js.map +1 -0
- package/dist/src/parsers/parser-context.d.ts +6 -0
- package/dist/src/parsers/parser-context.d.ts.map +1 -0
- package/dist/src/parsers/parser-context.js +2 -0
- package/dist/src/parsers/parser-context.js.map +1 -0
- package/dist/src/parsers/parser-options.d.ts +4 -0
- package/dist/src/parsers/parser-options.d.ts.map +1 -0
- package/dist/src/parsers/parser-options.js +2 -0
- package/dist/src/parsers/parser-options.js.map +1 -0
- package/dist/src/parsers/svelte-parser.d.ts +4 -0
- package/dist/src/parsers/svelte-parser.d.ts.map +1 -0
- package/dist/src/parsers/svelte-parser.js +169 -0
- package/dist/src/parsers/svelte-parser.js.map +1 -0
- package/dist/src/parsers/ts-parser.d.ts +9 -0
- package/dist/src/parsers/ts-parser.d.ts.map +1 -0
- package/dist/src/parsers/ts-parser.js +54 -0
- package/dist/src/parsers/ts-parser.js.map +1 -0
- package/dist/src/printers/html-printer.d.ts +4 -0
- package/dist/src/printers/html-printer.d.ts.map +1 -0
- package/dist/src/printers/html-printer.js +15 -0
- package/dist/src/printers/html-printer.js.map +1 -0
- package/dist/src/printers/index.d.ts +7 -0
- package/dist/src/printers/index.d.ts.map +1 -0
- package/dist/src/printers/index.js +23 -0
- package/dist/src/printers/index.js.map +1 -0
- package/dist/src/printers/js-printer.d.ts +4 -0
- package/dist/src/printers/js-printer.d.ts.map +1 -0
- package/dist/src/printers/js-printer.js +6 -0
- package/dist/src/printers/js-printer.js.map +1 -0
- package/dist/src/printers/svelte-printer.d.ts +4 -0
- package/dist/src/printers/svelte-printer.d.ts.map +1 -0
- package/dist/src/printers/svelte-printer.js +28 -0
- package/dist/src/printers/svelte-printer.js.map +1 -0
- package/dist/src/printers/ts-printer.d.ts +4 -0
- package/dist/src/printers/ts-printer.d.ts.map +1 -0
- package/dist/src/printers/ts-printer.js +9 -0
- package/dist/src/printers/ts-printer.js.map +1 -0
- package/dist/src/syntax/index.d.ts +86 -0
- package/dist/src/syntax/index.d.ts.map +1 -0
- package/dist/src/syntax/index.js +9 -0
- package/dist/src/syntax/index.js.map +1 -0
- package/dist/src/transformers/babel-transformer.d.ts +4 -0
- package/dist/src/transformers/babel-transformer.d.ts.map +1 -0
- package/dist/src/transformers/babel-transformer.js +142 -0
- package/dist/src/transformers/babel-transformer.js.map +1 -0
- package/dist/src/transformers/directive-bookkeeper.d.ts +19 -0
- package/dist/src/transformers/directive-bookkeeper.d.ts.map +1 -0
- package/dist/src/transformers/directive-bookkeeper.js +108 -0
- package/dist/src/transformers/directive-bookkeeper.js.map +1 -0
- package/dist/src/transformers/html-transformer.d.ts +4 -0
- package/dist/src/transformers/html-transformer.d.ts.map +1 -0
- package/dist/src/transformers/html-transformer.js +6 -0
- package/dist/src/transformers/html-transformer.js.map +1 -0
- package/dist/src/transformers/ignorer-bookkeeper.d.ts +18 -0
- package/dist/src/transformers/ignorer-bookkeeper.d.ts.map +1 -0
- package/dist/src/transformers/ignorer-bookkeeper.js +29 -0
- package/dist/src/transformers/ignorer-bookkeeper.js.map +1 -0
- package/dist/src/transformers/index.d.ts +6 -0
- package/dist/src/transformers/index.d.ts.map +1 -0
- package/dist/src/transformers/index.js +4 -0
- package/dist/src/transformers/index.js.map +1 -0
- package/dist/src/transformers/mutant-collector.d.ts +19 -0
- package/dist/src/transformers/mutant-collector.d.ts.map +1 -0
- package/dist/src/transformers/mutant-collector.js +25 -0
- package/dist/src/transformers/mutant-collector.js.map +1 -0
- package/dist/src/transformers/svelte-transformer.d.ts +4 -0
- package/dist/src/transformers/svelte-transformer.d.ts.map +1 -0
- package/dist/src/transformers/svelte-transformer.js +46 -0
- package/dist/src/transformers/svelte-transformer.js.map +1 -0
- package/dist/src/transformers/transformer-options.d.ts +6 -0
- package/dist/src/transformers/transformer-options.d.ts.map +1 -0
- package/dist/src/transformers/transformer-options.js +2 -0
- package/dist/src/transformers/transformer-options.js.map +1 -0
- package/dist/src/transformers/transformer.d.ts +22 -0
- package/dist/src/transformers/transformer.d.ts.map +1 -0
- package/dist/src/transformers/transformer.js +30 -0
- package/dist/src/transformers/transformer.js.map +1 -0
- package/dist/src/util/binary-operator.d.ts +2 -0
- package/dist/src/util/binary-operator.d.ts.map +1 -0
- package/dist/src/util/binary-operator.js +2 -0
- package/dist/src/util/binary-operator.js.map +1 -0
- package/dist/src/util/index.d.ts +4 -0
- package/dist/src/util/index.d.ts.map +1 -0
- package/dist/src/util/index.js +4 -0
- package/dist/src/util/index.js.map +1 -0
- package/dist/src/util/position-converter.d.ts +16 -0
- package/dist/src/util/position-converter.d.ts.map +1 -0
- package/dist/src/util/position-converter.js +126 -0
- package/dist/src/util/position-converter.js.map +1 -0
- package/dist/src/util/syntax-helpers.d.ts +60 -0
- package/dist/src/util/syntax-helpers.d.ts.map +1 -0
- package/dist/src/util/syntax-helpers.js +217 -0
- package/dist/src/util/syntax-helpers.js.map +1 -0
- package/package.json +64 -0
- package/src/create-instrumenter.ts +30 -0
- package/src/disable-type-checks.ts +153 -0
- package/src/file.ts +6 -0
- package/src/frameworks/angular-ignorer.ts +129 -0
- package/src/frameworks/index.ts +9 -0
- package/src/index.ts +8 -0
- package/src/instrument-result.ts +8 -0
- package/src/instrumenter-options.ts +5 -0
- package/src/instrumenter-tokens.ts +5 -0
- package/src/instrumenter.ts +100 -0
- package/src/mutant-placers/expression-mutant-placer.ts +210 -0
- package/src/mutant-placers/index.ts +12 -0
- package/src/mutant-placers/mutant-placer.ts +9 -0
- package/src/mutant-placers/statement-mutant-placer.ts +39 -0
- package/src/mutant-placers/switch-case-mutant-placer.ts +41 -0
- package/src/mutant-placers/throw-placement-error.ts +34 -0
- package/src/mutant.ts +101 -0
- package/src/mutators/arithmetic-operator-mutator.ts +51 -0
- package/src/mutators/array-declaration-mutator.ts +36 -0
- package/src/mutators/arrow-function-mutator.ts +22 -0
- package/src/mutators/assignment-operator-mutator.ts +59 -0
- package/src/mutators/block-statement-mutator.ts +89 -0
- package/src/mutators/boolean-literal-mutator.ts +24 -0
- package/src/mutators/conditional-expression-mutator.ts +92 -0
- package/src/mutators/equality-operator-mutator.ts +35 -0
- package/src/mutators/index.ts +3 -0
- package/src/mutators/logical-operator-mutator.ts +29 -0
- package/src/mutators/method-expression-mutator.ts +99 -0
- package/src/mutators/mutate.ts +36 -0
- package/src/mutators/mutator-options.ts +4 -0
- package/src/mutators/node-mutator.ts +6 -0
- package/src/mutators/object-literal-mutator.ts +15 -0
- package/src/mutators/optional-chaining-mutator.ts +39 -0
- package/src/mutators/regex-mutator.ts +69 -0
- package/src/mutators/string-literal-mutator.ts +49 -0
- package/src/mutators/unary-operator-mutator.ts +39 -0
- package/src/mutators/update-operator-mutator.ts +26 -0
- package/src/parsers/create-parser.ts +78 -0
- package/src/parsers/html-parser.ts +138 -0
- package/src/parsers/index.ts +5 -0
- package/src/parsers/js-parser.ts +58 -0
- package/src/parsers/parse-error.ts +9 -0
- package/src/parsers/parser-context.ts +15 -0
- package/src/parsers/parser-options.ts +3 -0
- package/src/parsers/svelte-parser.ts +255 -0
- package/src/parsers/ts-parser.ts +69 -0
- package/src/printers/html-printer.ts +20 -0
- package/src/printers/index.ts +33 -0
- package/src/printers/js-printer.ts +11 -0
- package/src/printers/svelte-printer.ts +34 -0
- package/src/printers/ts-printer.ts +14 -0
- package/src/syntax/index.ts +97 -0
- package/src/transformers/babel-transformer.ts +217 -0
- package/src/transformers/directive-bookkeeper.ts +173 -0
- package/src/transformers/html-transformer.ts +13 -0
- package/src/transformers/ignorer-bookkeeper.ts +41 -0
- package/src/transformers/index.ts +6 -0
- package/src/transformers/mutant-collector.ts +44 -0
- package/src/transformers/svelte-transformer.ts +57 -0
- package/src/transformers/transformer-options.ts +7 -0
- package/src/transformers/transformer.ts +54 -0
- package/src/util/binary-operator.ts +23 -0
- package/src/util/index.ts +3 -0
- package/src/util/position-converter.ts +145 -0
- package/src/util/syntax-helpers.ts +301 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Position } from '@stryker-mutator/api/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A class that can convert a string offset back to line / column.
|
|
5
|
+
* Grabbed from TypeScript code base
|
|
6
|
+
* @see https://github.com/microsoft/TypeScript/blob/aa9b6953441b53f8b14072c047f0519b611150c4/src/compiler/scanner.ts#L503
|
|
7
|
+
*/
|
|
8
|
+
export class PositionConverter {
|
|
9
|
+
private _lineStarts?: readonly number[];
|
|
10
|
+
private get lineStarts() {
|
|
11
|
+
if (!this._lineStarts) {
|
|
12
|
+
this._lineStarts = this.computeLineStarts(this.text);
|
|
13
|
+
}
|
|
14
|
+
return this._lineStarts;
|
|
15
|
+
}
|
|
16
|
+
constructor(private readonly text: string) {}
|
|
17
|
+
|
|
18
|
+
public positionFromOffset(offset: number): Position {
|
|
19
|
+
const lineNumber = this.computeLineOfPosition(offset);
|
|
20
|
+
return {
|
|
21
|
+
line: lineNumber,
|
|
22
|
+
column: offset - this.lineStarts[lineNumber],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private computeLineOfPosition(offset: number) {
|
|
27
|
+
let lineNumber = binarySearch(this.lineStarts, offset);
|
|
28
|
+
if (lineNumber < 0) {
|
|
29
|
+
// If the actual position was not found,
|
|
30
|
+
// the binary search returns the 2's-complement of the next line start
|
|
31
|
+
// e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20
|
|
32
|
+
// then the search will return -2.
|
|
33
|
+
//
|
|
34
|
+
// We want the index of the previous line start, so we subtract 1.
|
|
35
|
+
// Review 2's-complement if this is confusing.
|
|
36
|
+
lineNumber = ~lineNumber - 1;
|
|
37
|
+
if (lineNumber === -1) {
|
|
38
|
+
throw new Error('position cannot precede the beginning of the file');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return lineNumber;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private computeLineStarts(text: string): number[] {
|
|
45
|
+
const result: number[] = [];
|
|
46
|
+
let pos = 0;
|
|
47
|
+
let lineStart = 0;
|
|
48
|
+
while (pos < text.length) {
|
|
49
|
+
const ch = text.charCodeAt(pos);
|
|
50
|
+
pos++;
|
|
51
|
+
switch (ch) {
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
53
|
+
case CharacterCodes.carriageReturn: {
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
55
|
+
if (text.charCodeAt(pos) === CharacterCodes.lineFeed) {
|
|
56
|
+
pos++;
|
|
57
|
+
}
|
|
58
|
+
// falls through
|
|
59
|
+
}
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
61
|
+
case CharacterCodes.lineFeed:
|
|
62
|
+
result.push(lineStart);
|
|
63
|
+
lineStart = pos;
|
|
64
|
+
break;
|
|
65
|
+
default:
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
67
|
+
if (ch > CharacterCodes.maxAsciiCharacter && isLineBreak(ch)) {
|
|
68
|
+
result.push(lineStart);
|
|
69
|
+
lineStart = pos;
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
result.push(lineStart);
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function binarySearch(array: readonly number[], value: number): number {
|
|
80
|
+
if (!array.length) {
|
|
81
|
+
return -1;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let low = 0;
|
|
85
|
+
let high = array.length - 1;
|
|
86
|
+
while (low <= high) {
|
|
87
|
+
const middle = low + ((high - low) >> 1);
|
|
88
|
+
const midKey = compare(array[middle], value);
|
|
89
|
+
switch (midKey) {
|
|
90
|
+
case Comparison.LessThan:
|
|
91
|
+
low = middle + 1;
|
|
92
|
+
break;
|
|
93
|
+
case Comparison.EqualTo:
|
|
94
|
+
return middle;
|
|
95
|
+
case Comparison.GreaterThan:
|
|
96
|
+
high = middle - 1;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return ~low;
|
|
102
|
+
}
|
|
103
|
+
const enum Comparison {
|
|
104
|
+
LessThan = -1,
|
|
105
|
+
EqualTo = 0,
|
|
106
|
+
GreaterThan = 1,
|
|
107
|
+
}
|
|
108
|
+
function compare(a: number, b: number) {
|
|
109
|
+
return a < b
|
|
110
|
+
? Comparison.LessThan
|
|
111
|
+
: a > b
|
|
112
|
+
? Comparison.GreaterThan
|
|
113
|
+
: Comparison.EqualTo;
|
|
114
|
+
}
|
|
115
|
+
const enum CharacterCodes {
|
|
116
|
+
lineFeed = 0x0a, // \n
|
|
117
|
+
carriageReturn = 0x0d, // \r
|
|
118
|
+
maxAsciiCharacter = 0x7f,
|
|
119
|
+
lineSeparator = 0x2028,
|
|
120
|
+
paragraphSeparator = 0x2029,
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function isLineBreak(ch: number): boolean {
|
|
124
|
+
// ES5 7.3:
|
|
125
|
+
// The ECMAScript line terminator characters are listed in Table 3.
|
|
126
|
+
// Table 3: Line Terminator Characters
|
|
127
|
+
// Code Unit Value Name Formal Name
|
|
128
|
+
// \u000A Line Feed <LF>
|
|
129
|
+
// \u000D Carriage Return <CR>
|
|
130
|
+
// \u2028 Line separator <LS>
|
|
131
|
+
// \u2029 Paragraph separator <PS>
|
|
132
|
+
// Only the characters in Table 3 are treated as line terminators. Other new line or line
|
|
133
|
+
// breaking characters are treated as white space but not as line terminators.
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
137
|
+
ch === CharacterCodes.lineFeed ||
|
|
138
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
139
|
+
ch === CharacterCodes.carriageReturn ||
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
141
|
+
ch === CharacterCodes.lineSeparator ||
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
|
|
143
|
+
ch === CharacterCodes.paragraphSeparator
|
|
144
|
+
);
|
|
145
|
+
}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { INSTRUMENTER_CONSTANTS as ID } from '@stryker-mutator/api/core';
|
|
2
|
+
import babel from '@babel/core';
|
|
3
|
+
import { deepFreeze, I } from '@stryker-mutator/util';
|
|
4
|
+
|
|
5
|
+
import { Mutant } from '../mutant.js';
|
|
6
|
+
|
|
7
|
+
import { MutantCollector } from '../transformers/index.js';
|
|
8
|
+
import { MutatorOptions } from '../mutators/index.js';
|
|
9
|
+
|
|
10
|
+
export { ID };
|
|
11
|
+
|
|
12
|
+
const STRYKER_NAMESPACE_HELPER = 'stryNS_9fa48';
|
|
13
|
+
const COVER_MUTANT_HELPER = 'stryCov_9fa48';
|
|
14
|
+
const IS_MUTANT_ACTIVE_HELPER = 'stryMutAct_9fa48';
|
|
15
|
+
|
|
16
|
+
const { types, traverse } = babel;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Returns syntax for the header if JS/TS files
|
|
20
|
+
*/
|
|
21
|
+
export const instrumentationBabelHeader = deepFreeze(
|
|
22
|
+
// `globalThis` implementation is based on core-js's implementation. See https://github.com/stryker-mutator/stryker-js/issues/4035
|
|
23
|
+
babel.parse(
|
|
24
|
+
`function ${STRYKER_NAMESPACE_HELPER}(){
|
|
25
|
+
var g = typeof globalThis === 'object' && globalThis && globalThis.Math === Math && globalThis || new Function("return this")();
|
|
26
|
+
var ns = g.${ID.NAMESPACE} || (g.${ID.NAMESPACE} = {});
|
|
27
|
+
if (ns.${ID.ACTIVE_MUTANT} === undefined && g.process && g.process.env && g.process.env.${ID.ACTIVE_MUTANT_ENV_VARIABLE}) {
|
|
28
|
+
ns.${ID.ACTIVE_MUTANT} = g.process.env.${ID.ACTIVE_MUTANT_ENV_VARIABLE};
|
|
29
|
+
}
|
|
30
|
+
function retrieveNS(){
|
|
31
|
+
return ns;
|
|
32
|
+
}
|
|
33
|
+
${STRYKER_NAMESPACE_HELPER} = retrieveNS;
|
|
34
|
+
return retrieveNS();
|
|
35
|
+
}
|
|
36
|
+
${STRYKER_NAMESPACE_HELPER}();
|
|
37
|
+
|
|
38
|
+
function ${COVER_MUTANT_HELPER}() {
|
|
39
|
+
var ns = ${STRYKER_NAMESPACE_HELPER}();
|
|
40
|
+
var cov = ns.${ID.MUTATION_COVERAGE_OBJECT} || (ns.${ID.MUTATION_COVERAGE_OBJECT} = { static: {}, perTest: {} });
|
|
41
|
+
function cover() {
|
|
42
|
+
var c = cov.static;
|
|
43
|
+
if (ns.${ID.CURRENT_TEST_ID}) {
|
|
44
|
+
c = cov.perTest[ns.${ID.CURRENT_TEST_ID}] = cov.perTest[ns.${ID.CURRENT_TEST_ID}] || {};
|
|
45
|
+
}
|
|
46
|
+
var a = arguments;
|
|
47
|
+
for(var i=0; i < a.length; i++){
|
|
48
|
+
c[a[i]] = (c[a[i]] || 0) + 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
${COVER_MUTANT_HELPER} = cover;
|
|
52
|
+
cover.apply(null, arguments);
|
|
53
|
+
}
|
|
54
|
+
function ${IS_MUTANT_ACTIVE_HELPER}(id) {
|
|
55
|
+
var ns = ${STRYKER_NAMESPACE_HELPER}();
|
|
56
|
+
function isActive(id) {
|
|
57
|
+
if (ns.${ID.ACTIVE_MUTANT} === id) {
|
|
58
|
+
if (ns.${ID.HIT_COUNT} !== void 0 && ++ns.${ID.HIT_COUNT} > ns.${ID.HIT_LIMIT}) {
|
|
59
|
+
throw new Error('Stryker: Hit count limit reached (' + ns.${ID.HIT_COUNT} + ')');
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
${IS_MUTANT_ACTIVE_HELPER} = isActive;
|
|
66
|
+
return isActive(id);
|
|
67
|
+
}`,
|
|
68
|
+
{ configFile: false, browserslistConfigFile: false, env: { targets: {} } },
|
|
69
|
+
) as babel.types.File,
|
|
70
|
+
).program.body as readonly babel.types.Statement[]; // cast here, otherwise the thing gets unwieldy to handle
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* returns syntax for `global.activeMutant === $mutantId`
|
|
74
|
+
* @param mutantId The id of the mutant to switch
|
|
75
|
+
*/
|
|
76
|
+
export function mutantTestExpression(
|
|
77
|
+
mutantId: string,
|
|
78
|
+
): babel.types.CallExpression {
|
|
79
|
+
return types.callExpression(types.identifier(IS_MUTANT_ACTIVE_HELPER), [
|
|
80
|
+
types.stringLiteral(mutantId),
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
interface Position {
|
|
85
|
+
line: number;
|
|
86
|
+
column: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function eqLocation(
|
|
90
|
+
a: babel.types.SourceLocation,
|
|
91
|
+
b: babel.types.SourceLocation,
|
|
92
|
+
): boolean {
|
|
93
|
+
function eqPosition(start: Position, end: Position): boolean {
|
|
94
|
+
return start.column === end.column && start.line === end.line;
|
|
95
|
+
}
|
|
96
|
+
return eqPosition(a.start, b.start) && eqPosition(a.end, b.end);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function eqNode<T extends babel.types.Node>(
|
|
100
|
+
a: T,
|
|
101
|
+
b: babel.types.Node,
|
|
102
|
+
): b is T {
|
|
103
|
+
return a.type === b.type && !!a.loc && !!b.loc && eqLocation(a.loc, b.loc);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function offsetLocations(
|
|
107
|
+
file: babel.types.File,
|
|
108
|
+
{
|
|
109
|
+
position,
|
|
110
|
+
line,
|
|
111
|
+
column,
|
|
112
|
+
}: { position: number; line: number; column: number },
|
|
113
|
+
): void {
|
|
114
|
+
const offsetNode = (node: babel.types.Node): void => {
|
|
115
|
+
node.start! += position;
|
|
116
|
+
node.end! += position;
|
|
117
|
+
// we need to subtract 1, as lines always start at 1
|
|
118
|
+
node.loc!.start.line += line - 1;
|
|
119
|
+
node.loc!.end.line += line - 1;
|
|
120
|
+
if (node.loc!.start.line === line) {
|
|
121
|
+
node.loc!.start.column += column;
|
|
122
|
+
}
|
|
123
|
+
if (node.loc!.end.line === line) {
|
|
124
|
+
node.loc!.end.column += column;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
traverse(file, {
|
|
128
|
+
enter(path) {
|
|
129
|
+
offsetNode(path.node);
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
// Don't forget the file itself!
|
|
133
|
+
file.start! += position;
|
|
134
|
+
file.end! += position;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Returns a sequence of mutation coverage counters with an optional last expression.
|
|
139
|
+
*
|
|
140
|
+
* @example (global.__coverMutant__(0, 1), 40 + 2)
|
|
141
|
+
* @param mutants The mutants for which covering syntax needs to be generated
|
|
142
|
+
* @param targetExpression The original expression
|
|
143
|
+
*/
|
|
144
|
+
export function mutationCoverageSequenceExpression(
|
|
145
|
+
mutants: Iterable<Mutant>,
|
|
146
|
+
targetExpression?: babel.types.Expression,
|
|
147
|
+
): babel.types.Expression {
|
|
148
|
+
const mutantIds = [...mutants].map((mutant) =>
|
|
149
|
+
types.stringLiteral(mutant.id),
|
|
150
|
+
);
|
|
151
|
+
const sequence: babel.types.Expression[] = [
|
|
152
|
+
types.callExpression(types.identifier(COVER_MUTANT_HELPER), mutantIds),
|
|
153
|
+
];
|
|
154
|
+
if (targetExpression) {
|
|
155
|
+
sequence.push(targetExpression);
|
|
156
|
+
}
|
|
157
|
+
return types.sequenceExpression(sequence);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function isTypeNode(path: babel.NodePath): boolean {
|
|
161
|
+
return (
|
|
162
|
+
path.isTypeAnnotation() ||
|
|
163
|
+
flowTypeAnnotationNodeTypes.includes(path.node.type) ||
|
|
164
|
+
tsTypeAnnotationNodeTypes.includes(path.node.type) ||
|
|
165
|
+
isDeclareVariableStatement(path) ||
|
|
166
|
+
isDeclareModule(path)
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Determines whether or not it is a declare variable statement node.
|
|
172
|
+
* @example
|
|
173
|
+
* declare const foo: 'foo';
|
|
174
|
+
*/
|
|
175
|
+
function isDeclareVariableStatement(path: babel.NodePath): boolean {
|
|
176
|
+
return path.isVariableDeclaration() && path.node.declare === true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Determines whether or not a node is a string literal that is the name of a module.
|
|
181
|
+
* @example
|
|
182
|
+
* declare module "express" {};
|
|
183
|
+
*/
|
|
184
|
+
function isDeclareModule(path: babel.NodePath): boolean {
|
|
185
|
+
return path.isTSModuleDeclaration() && (path.node.declare ?? false);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const tsTypeAnnotationNodeTypes: ReadonlyArray<babel.types.Node['type']> =
|
|
189
|
+
Object.freeze([
|
|
190
|
+
'TSAsExpression',
|
|
191
|
+
'TSInterfaceDeclaration',
|
|
192
|
+
'TSTypeAnnotation',
|
|
193
|
+
'TSTypeAliasDeclaration',
|
|
194
|
+
'TSEnumDeclaration',
|
|
195
|
+
'TSDeclareFunction',
|
|
196
|
+
'TSTypeParameterInstantiation',
|
|
197
|
+
'TSTypeParameterDeclaration',
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
const flowTypeAnnotationNodeTypes: ReadonlyArray<babel.types.Node['type']> =
|
|
201
|
+
Object.freeze([
|
|
202
|
+
'DeclareClass',
|
|
203
|
+
'DeclareFunction',
|
|
204
|
+
'DeclareInterface',
|
|
205
|
+
'DeclareModule',
|
|
206
|
+
'DeclareModuleExports',
|
|
207
|
+
'DeclareTypeAlias',
|
|
208
|
+
'DeclareOpaqueType',
|
|
209
|
+
'DeclareVariable',
|
|
210
|
+
'DeclareExportDeclaration',
|
|
211
|
+
'DeclareExportAllDeclaration',
|
|
212
|
+
'InterfaceDeclaration',
|
|
213
|
+
'OpaqueType',
|
|
214
|
+
'TypeAlias',
|
|
215
|
+
'InterfaceDeclaration',
|
|
216
|
+
]);
|
|
217
|
+
|
|
218
|
+
export function isImportDeclaration(path: babel.NodePath): boolean {
|
|
219
|
+
return (
|
|
220
|
+
types.isTSImportEqualsDeclaration(path.node) || path.isImportDeclaration()
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* A location of an ast node in a file
|
|
226
|
+
*/
|
|
227
|
+
export interface SourceLocationInFile {
|
|
228
|
+
end: Position;
|
|
229
|
+
start: Position;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Determines if a location (needle) is included in an other location (haystack)
|
|
234
|
+
* @param haystack The range to look in
|
|
235
|
+
* @param needle the range to search for
|
|
236
|
+
*/
|
|
237
|
+
export function locationIncluded(
|
|
238
|
+
haystack: SourceLocationInFile,
|
|
239
|
+
needle: SourceLocationInFile,
|
|
240
|
+
): boolean {
|
|
241
|
+
const startIncluded =
|
|
242
|
+
haystack.start.line < needle.start.line ||
|
|
243
|
+
(haystack.start.line === needle.start.line &&
|
|
244
|
+
haystack.start.column <= needle.start.column);
|
|
245
|
+
const endIncluded =
|
|
246
|
+
haystack.end.line > needle.end.line ||
|
|
247
|
+
(haystack.end.line === needle.end.line &&
|
|
248
|
+
haystack.end.column >= needle.end.column);
|
|
249
|
+
return startIncluded && endIncluded;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Determines if two locations overlap with each other
|
|
254
|
+
*/
|
|
255
|
+
export function locationOverlaps(
|
|
256
|
+
a: SourceLocationInFile,
|
|
257
|
+
b: SourceLocationInFile,
|
|
258
|
+
): boolean {
|
|
259
|
+
const startIncluded =
|
|
260
|
+
a.start.line < b.end.line ||
|
|
261
|
+
(a.start.line === b.end.line && a.start.column <= b.end.column);
|
|
262
|
+
const endIncluded =
|
|
263
|
+
a.end.line > b.start.line ||
|
|
264
|
+
(a.end.line === b.start.line && a.end.column >= b.start.column);
|
|
265
|
+
return startIncluded && endIncluded;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Helper for `types.cloneNode(node, deep: true, withoutLocations: false);`
|
|
270
|
+
*/
|
|
271
|
+
export function deepCloneNode<TNode extends babel.types.Node>(
|
|
272
|
+
node: TNode,
|
|
273
|
+
): TNode {
|
|
274
|
+
return types.cloneNode(node, /* deep */ true, /* withoutLocations */ false);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export function placeHeaderIfNeeded(
|
|
278
|
+
mutantCollector: I<MutantCollector>,
|
|
279
|
+
originFileName: string,
|
|
280
|
+
options: MutatorOptions,
|
|
281
|
+
root: babel.types.File,
|
|
282
|
+
): void {
|
|
283
|
+
if (mutantCollector.hasPlacedMutants(originFileName) && !options.noHeader) {
|
|
284
|
+
// Be sure to leave comments like `// @flow` in.
|
|
285
|
+
placeHeader(root);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function placeHeader(root: babel.types.File): void {
|
|
290
|
+
let header = instrumentationBabelHeader;
|
|
291
|
+
if (Array.isArray(root.program.body[0]?.leadingComments)) {
|
|
292
|
+
header = [
|
|
293
|
+
{
|
|
294
|
+
...instrumentationBabelHeader[0],
|
|
295
|
+
leadingComments: root.program.body[0]?.leadingComments,
|
|
296
|
+
},
|
|
297
|
+
...instrumentationBabelHeader.slice(1),
|
|
298
|
+
];
|
|
299
|
+
}
|
|
300
|
+
root.program.body.unshift(...header);
|
|
301
|
+
}
|