From 6bd2fbbf0aaa5154930ce36f4d153ee91a3c5f1f Mon Sep 17 00:00:00 2001 From: Nico Jansen Date: Wed, 4 Nov 2020 11:47:56 +0100 Subject: [PATCH] fix(ts): support es private fields (#2605) Support [es private fields](https://www.typescriptlang.org/docs/handbook/classes.html#ecmascript-private-fields) in typescript code. --- e2e/package-lock.json | 14 +- e2e/package.json | 2 +- .../karma-webpack-with-ts/package-lock.json | 14 +- e2e/test/karma-webpack-with-ts/package.json | 4 +- packages/api/package.json | 2 +- packages/core/package.json | 4 +- packages/instrumenter/package.json | 2 + .../instrumenter/src/parsers/ts-parser.ts | 6 +- .../test/integration/parsers.it.spec.js.snap | 1162 +++++++++++++++++ .../test/integration/parsers.it.spec.ts | 5 + .../test/unit/parsers/ts-parser.spec.ts | 4 + .../testResources/instrumenter/ts-sample.ts | 14 + .../instrumenter/ts-sample.ts.out.snap | 35 +- .../testResources/parser/new-ts-features.ts | 13 + packages/test-helpers/package.json | 2 +- 15 files changed, 1260 insertions(+), 23 deletions(-) create mode 100644 packages/instrumenter/testResources/parser/new-ts-features.ts diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 45bc9ade10..1a7f8bd721 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -8666,18 +8666,18 @@ } }, "mutation-testing-metrics": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/mutation-testing-metrics/-/mutation-testing-metrics-1.4.0.tgz", - "integrity": "sha512-+S1c/6T6CcTlT0hjc7Vo/uvdksglsZk9Ug0wLNYB3DF7tmn1DBUjw+52QwiY3vfGZ1jqsyPcJstgZyoYlWnvrA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/mutation-testing-metrics/-/mutation-testing-metrics-1.4.3.tgz", + "integrity": "sha512-b+5upZuuEDyY5oWb/3Jvo8kMxo9VHVP8t7ryZproBbp9bclDbS3c6kFScR6qJPFQ90NK2S7ab/cGxRHMXnNbJQ==", "dev": true, "requires": { - "mutation-testing-report-schema": "^1.4.0" + "mutation-testing-report-schema": "^1.4.3" } }, "mutation-testing-report-schema": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/mutation-testing-report-schema/-/mutation-testing-report-schema-1.4.0.tgz", - "integrity": "sha512-0jEZCv3aIckkKTn8IZ1fRdrmgYHkOc5ieA61qnsuxMezXUNfZmZA2etL4vwku8K3H8v5IgT7+yYoCQSysSvBfw==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/mutation-testing-report-schema/-/mutation-testing-report-schema-1.4.3.tgz", + "integrity": "sha512-+TLMYFGFL8MtcbIF0g9VG+OS5qkPPaZtvyT0v/XWrKgrbAhpnJYNsZV9/xMWuO/V8WC02mLksn/HrDnKnIVqXw==", "dev": true }, "mz": { diff --git a/e2e/package.json b/e2e/package.json index c95df63409..719e301610 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -29,7 +29,7 @@ "link-parent-bin": "^2.0.0", "load-grunt-tasks": "~5.1.0", "mocha": "~8.2.0", - "mutation-testing-metrics": "~1.4.0", + "mutation-testing-metrics": "~1.4.3", "rxjs": "~6.5.3", "semver": "~6.3.0", "ts-jest": "~26.3.0", diff --git a/e2e/test/karma-webpack-with-ts/package-lock.json b/e2e/test/karma-webpack-with-ts/package-lock.json index 73b24455b3..2f26aee5ad 100644 --- a/e2e/test/karma-webpack-with-ts/package-lock.json +++ b/e2e/test/karma-webpack-with-ts/package-lock.json @@ -23,17 +23,17 @@ "integrity": "sha512-GSJHHXMGLZDzTRq59IUfL9FCdAlGfqNp/dEa7k7aBaaWD+JKaCjsAk9KYm2V12ItonVaYx2dprN66Zdm1AuBTQ==" }, "mutation-testing-metrics": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/mutation-testing-metrics/-/mutation-testing-metrics-1.4.0.tgz", - "integrity": "sha512-+S1c/6T6CcTlT0hjc7Vo/uvdksglsZk9Ug0wLNYB3DF7tmn1DBUjw+52QwiY3vfGZ1jqsyPcJstgZyoYlWnvrA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/mutation-testing-metrics/-/mutation-testing-metrics-1.4.3.tgz", + "integrity": "sha512-b+5upZuuEDyY5oWb/3Jvo8kMxo9VHVP8t7ryZproBbp9bclDbS3c6kFScR6qJPFQ90NK2S7ab/cGxRHMXnNbJQ==", "requires": { - "mutation-testing-report-schema": "^1.4.0" + "mutation-testing-report-schema": "^1.4.3" } }, "mutation-testing-report-schema": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/mutation-testing-report-schema/-/mutation-testing-report-schema-1.4.0.tgz", - "integrity": "sha512-0jEZCv3aIckkKTn8IZ1fRdrmgYHkOc5ieA61qnsuxMezXUNfZmZA2etL4vwku8K3H8v5IgT7+yYoCQSysSvBfw==" + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/mutation-testing-report-schema/-/mutation-testing-report-schema-1.4.3.tgz", + "integrity": "sha512-+TLMYFGFL8MtcbIF0g9VG+OS5qkPPaZtvyT0v/XWrKgrbAhpnJYNsZV9/xMWuO/V8WC02mLksn/HrDnKnIVqXw==" } } } diff --git a/e2e/test/karma-webpack-with-ts/package.json b/e2e/test/karma-webpack-with-ts/package.json index 38ea1382aa..e0d3d93f60 100644 --- a/e2e/test/karma-webpack-with-ts/package.json +++ b/e2e/test/karma-webpack-with-ts/package.json @@ -8,8 +8,8 @@ }, "dependencies": { "lit-element": "~2.3.1", - "mutation-testing-metrics": "~1.4.0", - "mutation-testing-report-schema": "~1.4.0" + "mutation-testing-metrics": "~1.4.3", + "mutation-testing-report-schema": "~1.4.3" }, "devDependencies": { "@types/webpack-env": "~1.15.2" diff --git a/packages/api/package.json b/packages/api/package.json index 8019f75bbb..fd9e8e30e8 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -38,7 +38,7 @@ "node": ">=10" }, "dependencies": { - "mutation-testing-report-schema": "~1.4.0", + "mutation-testing-report-schema": "~1.4.3", "surrial": "~2.0.2", "tslib": "~2.0.0" }, diff --git a/packages/core/package.json b/packages/core/package.json index 3069a5dc11..839a9437f5 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -71,8 +71,8 @@ "log4js": "~6.2.1", "minimatch": "~3.0.4", "mkdirp": "~1.0.3", - "mutation-testing-elements": "~1.4.1", - "mutation-testing-metrics": "~1.4.0", + "mutation-testing-elements": "~1.4.3", + "mutation-testing-metrics": "~1.4.3", "npm-run-path": "~4.0.1", "progress": "~2.0.0", "rimraf": "~3.0.0", diff --git a/packages/instrumenter/package.json b/packages/instrumenter/package.json index db8ef708a6..c51edd0f58 100644 --- a/packages/instrumenter/package.json +++ b/packages/instrumenter/package.json @@ -33,7 +33,9 @@ "@babel/core": "~7.12.3", "@babel/generator": "~7.12.1", "@babel/parser": "~7.12.3", + "@babel/plugin-proposal-class-properties": "^7.12.1", "@babel/plugin-proposal-decorators": "~7.12.1 ", + "@babel/plugin-proposal-private-methods": "^7.12.1", "@babel/preset-typescript": "~7.12.1 ", "@stryker-mutator/api": "4.1.0", "@stryker-mutator/util": "4.1.0", diff --git a/packages/instrumenter/src/parsers/ts-parser.ts b/packages/instrumenter/src/parsers/ts-parser.ts index e8ef350bc8..d32de96a4a 100644 --- a/packages/instrumenter/src/parsers/ts-parser.ts +++ b/packages/instrumenter/src/parsers/ts-parser.ts @@ -18,7 +18,11 @@ export async function parse(text: string, fileName: string): Promise { configFile: false, babelrc: false, presets: [[require.resolve('@babel/preset-typescript'), { isTSX, allExtensions: true }]], - plugins: [[require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }]], + plugins: [ + require.resolve('@babel/plugin-proposal-class-properties'), + require.resolve('@babel/plugin-proposal-private-methods'), + [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }], + ], }); if (types.isProgram(ast)) { throw new Error(`Expected ${fileName} to contain a babel.types.file, but was a program`); diff --git a/packages/instrumenter/test/integration/parsers.it.spec.js.snap b/packages/instrumenter/test/integration/parsers.it.spec.js.snap index 4867b16a9a..1998b9daba 100644 --- a/packages/instrumenter/test/integration/parsers.it.spec.js.snap +++ b/packages/instrumenter/test/integration/parsers.it.spec.js.snap @@ -14960,6 +14960,1168 @@ Object { } `; +exports[`parsers integration should be able to parse a ts file with more recent TS features 1`] = ` +Object { + "format": "ts", + "originFileName": "new-ts-features.ts", + "rawContent": "class Person { + #name = 'unknown'; + + get name(): string { + return this.#name; + } + set name(value: string) { + if(value.length < 2){ + throw new Error('Name should be at least 2 characters long'); + } + this.#name = value; + } +} +", + "root": Node { + "comments": Array [], + "end": 245, + "errors": Array [], + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 14, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "body": Node { + "body": Array [ + Node { + "end": 35, + "extra": undefined, + "innerComments": undefined, + "key": Node { + "end": 22, + "extra": undefined, + "id": Node { + "end": 22, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 2, + }, + "filename": undefined, + "identifierName": "name", + "start": Position { + "column": 3, + "line": 2, + }, + }, + "name": "name", + "range": Array [ + 18, + 22, + ], + "start": 18, + "trailingComments": undefined, + "type": "Identifier", + }, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 2, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 2, + "line": 2, + }, + }, + "range": Array [ + 17, + 22, + ], + "start": 17, + "trailingComments": undefined, + "type": "PrivateName", + }, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 2, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 2, + "line": 2, + }, + }, + "range": Array [ + 17, + 35, + ], + "start": 17, + "static": false, + "trailingComments": undefined, + "type": "ClassPrivateProperty", + "value": Node { + "end": 34, + "extra": Object { + "raw": "'unknown'", + "rawValue": "unknown", + }, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 2, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 10, + "line": 2, + }, + }, + "range": Array [ + 25, + 34, + ], + "start": 25, + "trailingComments": undefined, + "type": "StringLiteral", + "value": "unknown", + }, + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "argument": Node { + "computed": false, + "end": 81, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 5, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 11, + "line": 5, + }, + }, + "object": Node { + "end": 75, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 5, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 11, + "line": 5, + }, + }, + "range": Array [ + 71, + 75, + ], + "start": 71, + "trailingComments": undefined, + "type": "ThisExpression", + }, + "property": Node { + "end": 81, + "extra": undefined, + "id": Node { + "end": 81, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 5, + }, + "filename": undefined, + "identifierName": "name", + "start": Position { + "column": 17, + "line": 5, + }, + }, + "name": "name", + "range": Array [ + 77, + 81, + ], + "start": 77, + "trailingComments": undefined, + "type": "Identifier", + }, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 5, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 16, + "line": 5, + }, + }, + "range": Array [ + 76, + 81, + ], + "start": 76, + "trailingComments": undefined, + "type": "PrivateName", + }, + "range": Array [ + 71, + 81, + ], + "start": 71, + "trailingComments": undefined, + "type": "MemberExpression", + }, + "end": 82, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 5, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "range": Array [ + 64, + 82, + ], + "start": 64, + "trailingComments": undefined, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 86, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 6, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 21, + "line": 4, + }, + }, + "range": Array [ + 58, + 86, + ], + "start": 58, + "trailingComments": undefined, + "type": "BlockStatement", + }, + "computed": false, + "end": 86, + "extra": undefined, + "generator": false, + "id": null, + "innerComments": undefined, + "key": Node { + "end": 47, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 10, + "line": 4, + }, + "filename": undefined, + "identifierName": "name", + "start": Position { + "column": 6, + "line": 4, + }, + }, + "name": "name", + "range": Array [ + 43, + 47, + ], + "start": 43, + "trailingComments": undefined, + "type": "Identifier", + }, + "kind": "get", + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 6, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 2, + "line": 4, + }, + }, + "params": Array [], + "range": Array [ + 39, + 86, + ], + "returnType": Node { + "end": 57, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 4, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 12, + "line": 4, + }, + }, + "range": Array [ + 49, + 57, + ], + "start": 49, + "trailingComments": undefined, + "type": "TSTypeAnnotation", + "typeAnnotation": Node { + "end": 57, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 4, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 14, + "line": 4, + }, + }, + "range": Array [ + 51, + 57, + ], + "start": 51, + "trailingComments": undefined, + "type": "TSStringKeyword", + }, + }, + "start": 39, + "static": false, + "trailingComments": undefined, + "type": "ClassMethod", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "argument": Node { + "arguments": Array [ + Node { + "end": 206, + "extra": Object { + "raw": "'Name should be at least 2 characters long'", + "rawValue": "Name should be at least 2 characters long", + }, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 9, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 22, + "line": 9, + }, + }, + "range": Array [ + 163, + 206, + ], + "start": 163, + "trailingComments": undefined, + "type": "StringLiteral", + "value": "Name should be at least 2 characters long", + }, + ], + "callee": Node { + "end": 162, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 9, + }, + "filename": undefined, + "identifierName": "Error", + "start": Position { + "column": 16, + "line": 9, + }, + }, + "name": "Error", + "range": Array [ + 157, + 162, + ], + "start": 157, + "trailingComments": undefined, + "type": "Identifier", + }, + "end": 207, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 66, + "line": 9, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 12, + "line": 9, + }, + }, + "range": Array [ + 153, + 207, + ], + "start": 153, + "trailingComments": undefined, + "type": "NewExpression", + }, + "end": 208, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 67, + "line": 9, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 6, + "line": 9, + }, + }, + "range": Array [ + 147, + 208, + ], + "start": 147, + "trailingComments": undefined, + "type": "ThrowStatement", + }, + ], + "directives": Array [], + "end": 214, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 10, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 24, + "line": 8, + }, + }, + "range": Array [ + 139, + 214, + ], + "start": 139, + "trailingComments": undefined, + "type": "BlockStatement", + }, + "end": 214, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 10, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 4, + "line": 8, + }, + }, + "range": Array [ + 119, + 214, + ], + "start": 119, + "test": Node { + "end": 138, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "left": Node { + "computed": false, + "end": 134, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 8, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 7, + "line": 8, + }, + }, + "object": Node { + "end": 127, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 8, + }, + "filename": undefined, + "identifierName": "value", + "start": Position { + "column": 7, + "line": 8, + }, + }, + "name": "value", + "range": Array [ + 122, + 127, + ], + "start": 122, + "trailingComments": undefined, + "type": "Identifier", + }, + "property": Node { + "end": 134, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 8, + }, + "filename": undefined, + "identifierName": "length", + "start": Position { + "column": 13, + "line": 8, + }, + }, + "name": "length", + "range": Array [ + 128, + 134, + ], + "start": 128, + "trailingComments": undefined, + "type": "Identifier", + }, + "range": Array [ + 122, + 134, + ], + "start": 122, + "trailingComments": undefined, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 8, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 7, + "line": 8, + }, + }, + "operator": "<", + "range": Array [ + 122, + 138, + ], + "right": Node { + "end": 138, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 8, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 22, + "line": 8, + }, + }, + "range": Array [ + 137, + 138, + ], + "start": 137, + "trailingComments": undefined, + "type": "NumericLiteral", + "value": 2, + }, + "start": 122, + "trailingComments": undefined, + "type": "BinaryExpression", + }, + "trailingComments": undefined, + "type": "IfStatement", + }, + Node { + "end": 238, + "expression": Node { + "end": 237, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "left": Node { + "computed": false, + "end": 229, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 11, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 4, + "line": 11, + }, + }, + "object": Node { + "end": 223, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 11, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 4, + "line": 11, + }, + }, + "range": Array [ + 219, + 223, + ], + "start": 219, + "trailingComments": undefined, + "type": "ThisExpression", + }, + "property": Node { + "end": 229, + "extra": undefined, + "id": Node { + "end": 229, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 11, + }, + "filename": undefined, + "identifierName": "name", + "start": Position { + "column": 10, + "line": 11, + }, + }, + "name": "name", + "range": Array [ + 225, + 229, + ], + "start": 225, + "trailingComments": undefined, + "type": "Identifier", + }, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 11, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 9, + "line": 11, + }, + }, + "range": Array [ + 224, + 229, + ], + "start": 224, + "trailingComments": undefined, + "type": "PrivateName", + }, + "range": Array [ + 219, + 229, + ], + "start": 219, + "trailingComments": undefined, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 11, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 4, + "line": 11, + }, + }, + "operator": "=", + "range": Array [ + 219, + 237, + ], + "right": Node { + "end": 237, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 11, + }, + "filename": undefined, + "identifierName": "value", + "start": Position { + "column": 17, + "line": 11, + }, + }, + "name": "value", + "range": Array [ + 232, + 237, + ], + "start": 232, + "trailingComments": undefined, + "type": "Identifier", + }, + "start": 219, + "trailingComments": undefined, + "type": "AssignmentExpression", + }, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 11, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 4, + "line": 11, + }, + }, + "range": Array [ + 219, + 238, + ], + "start": 219, + "trailingComments": undefined, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 242, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 12, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 26, + "line": 7, + }, + }, + "range": Array [ + 113, + 242, + ], + "start": 113, + "trailingComments": undefined, + "type": "BlockStatement", + }, + "computed": false, + "end": 242, + "extra": undefined, + "generator": false, + "id": null, + "innerComments": undefined, + "key": Node { + "end": 97, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 10, + "line": 7, + }, + "filename": undefined, + "identifierName": "name", + "start": Position { + "column": 6, + "line": 7, + }, + }, + "name": "name", + "range": Array [ + 93, + 97, + ], + "start": 93, + "trailingComments": undefined, + "type": "Identifier", + }, + "kind": "set", + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 12, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 2, + "line": 7, + }, + }, + "params": Array [ + Node { + "end": 111, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 7, + }, + "filename": undefined, + "identifierName": "value", + "start": Position { + "column": 11, + "line": 7, + }, + }, + "name": "value", + "range": Array [ + 98, + 111, + ], + "start": 98, + "trailingComments": undefined, + "type": "Identifier", + "typeAnnotation": Node { + "end": 111, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 7, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 16, + "line": 7, + }, + }, + "range": Array [ + 103, + 111, + ], + "start": 103, + "trailingComments": undefined, + "type": "TSTypeAnnotation", + "typeAnnotation": Node { + "end": 111, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 7, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 18, + "line": 7, + }, + }, + "range": Array [ + 105, + 111, + ], + "start": 105, + "trailingComments": undefined, + "type": "TSStringKeyword", + }, + }, + }, + ], + "range": Array [ + 89, + 242, + ], + "start": 89, + "static": false, + "trailingComments": undefined, + "type": "ClassMethod", + }, + ], + "end": 244, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 13, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 13, + "line": 1, + }, + }, + "range": Array [ + 13, + 244, + ], + "start": 13, + "trailingComments": undefined, + "type": "ClassBody", + }, + "end": 244, + "extra": undefined, + "id": Node { + "end": 12, + "extra": undefined, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "filename": undefined, + "identifierName": "Person", + "start": Position { + "column": 6, + "line": 1, + }, + }, + "name": "Person", + "range": Array [ + 6, + 12, + ], + "start": 6, + "trailingComments": undefined, + "type": "Identifier", + }, + "innerComments": undefined, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 13, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 244, + ], + "start": 0, + "superClass": null, + "trailingComments": undefined, + "type": "ClassDeclaration", + }, + ], + "directives": Array [], + "end": 245, + "extra": undefined, + "innerComments": undefined, + "interpreter": null, + "leadingComments": undefined, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 14, + }, + "filename": undefined, + "identifierName": undefined, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 245, + ], + "sourceType": "module", + "start": 0, + "trailingComments": undefined, + "type": "Program", + }, + "range": Array [ + 0, + 245, + ], + "start": 0, + "trailingComments": undefined, + "type": "File", + }, +} +`; + exports[`parsers integration should ignore configuration when parsing ts files 1`] = ` Object { "format": "ts", diff --git a/packages/instrumenter/test/integration/parsers.it.spec.ts b/packages/instrumenter/test/integration/parsers.it.spec.ts index 84c2833aa1..f294fe54a0 100644 --- a/packages/instrumenter/test/integration/parsers.it.spec.ts +++ b/packages/instrumenter/test/integration/parsers.it.spec.ts @@ -50,6 +50,11 @@ describe('parsers integration', () => { expect(actual).to.matchSnapshot(); }); + it('should be able to parse a ts file with more recent TS features', async () => { + const actual = await actAssertTS('new-ts-features.ts'); + expect(actual).to.matchSnapshot(); + }); + it('should allow a plugin that conflicts with the default plugins as long as plugins are emptied out', async () => { process.chdir(resolveTestResource('js-in-babel-project')); const actual = await actAssertJS('js-in-babel-project/src/app.js', createParserOptions({ plugins: [] })); diff --git a/packages/instrumenter/test/unit/parsers/ts-parser.spec.ts b/packages/instrumenter/test/unit/parsers/ts-parser.spec.ts index 35b4406c5f..aaf54d847d 100644 --- a/packages/instrumenter/test/unit/parsers/ts-parser.spec.ts +++ b/packages/instrumenter/test/unit/parsers/ts-parser.spec.ts @@ -22,6 +22,10 @@ describe('ts-parser', () => { await arrangeAndAssert("@Component({ selector: 'auto-complete'}) class A {}", (t) => t.isDecorator()); }); + it('should allow for private fields', async () => { + await arrangeAndAssert('class A { #foo; get foo() { return this.#foo; }}', (t) => t.isPrivateName() && t.node.id.name === 'foo'); + }); + it('should allow jsx if extension is tsx', async () => { await arrangeAndAssert( `class MyComponent extends React.Component { diff --git a/packages/instrumenter/testResources/instrumenter/ts-sample.ts b/packages/instrumenter/testResources/instrumenter/ts-sample.ts index 1bcb72b3ec..08ffca40a1 100644 --- a/packages/instrumenter/testResources/instrumenter/ts-sample.ts +++ b/packages/instrumenter/testResources/instrumenter/ts-sample.ts @@ -1 +1,15 @@ const bar: number = 40 + 2; + +class Person { + #name = 'unknown'; + + get name(): string { + return this.#name; + } + set name(value: string) { + if(value.length < 2){ + throw new Error('Name should be at least 2 characters long'); + } + this.#name = value; + } +} diff --git a/packages/instrumenter/testResources/instrumenter/ts-sample.ts.out.snap b/packages/instrumenter/testResources/instrumenter/ts-sample.ts.out.snap index fb96df20f1..5319f0f1d3 100644 --- a/packages/instrumenter/testResources/instrumenter/ts-sample.ts.out.snap +++ b/packages/instrumenter/testResources/instrumenter/ts-sample.ts.out.snap @@ -55,5 +55,38 @@ function stryMutAct_9fa48(id) { return isActive(id); } -const bar: number = stryMutAct_9fa48(0) ? 40 - 2 : (stryCov_9fa48(0), 40 + 2);" +const bar: number = stryMutAct_9fa48(0) ? 40 - 2 : (stryCov_9fa48(0), 40 + 2); + +class Person { + #name = stryMutAct_9fa48(1) ? \\"\\" : (stryCov_9fa48(1), 'unknown'); + + get name(): string { + if (stryMutAct_9fa48(2)) { + {} + } else { + stryCov_9fa48(2); + return this.#name; + } + } + + set name(value: string) { + if (stryMutAct_9fa48(3)) { + {} + } else { + stryCov_9fa48(3); + + if (stryMutAct_9fa48(7) ? value.length >= 2 : stryMutAct_9fa48(6) ? value.length <= 2 : stryMutAct_9fa48(5) ? false : stryMutAct_9fa48(4) ? true : (stryCov_9fa48(4, 5, 6, 7), value.length < 2)) { + if (stryMutAct_9fa48(8)) { + {} + } else { + stryCov_9fa48(8); + throw new Error(stryMutAct_9fa48(9) ? \\"\\" : (stryCov_9fa48(9), 'Name should be at least 2 characters long')); + } + } + + this.#name = value; + } + } + +}" `; diff --git a/packages/instrumenter/testResources/parser/new-ts-features.ts b/packages/instrumenter/testResources/parser/new-ts-features.ts new file mode 100644 index 0000000000..9e45f7087d --- /dev/null +++ b/packages/instrumenter/testResources/parser/new-ts-features.ts @@ -0,0 +1,13 @@ +class Person { + #name = 'unknown'; + + get name(): string { + return this.#name; + } + set name(value: string) { + if(value.length < 2){ + throw new Error('Name should be at least 2 characters long'); + } + this.#name = value; + } +} diff --git a/packages/test-helpers/package.json b/packages/test-helpers/package.json index bb699c0d4f..3b74f3ccba 100644 --- a/packages/test-helpers/package.json +++ b/packages/test-helpers/package.json @@ -18,7 +18,7 @@ "license": "ISC", "dependencies": { "ajv": "~6.12.0", - "mutation-testing-metrics": "~1.4.0" + "mutation-testing-metrics": "~1.4.3" }, "devDependencies": { "@stryker-mutator/api": "4.1.0",