/
string-literal-mutator.ts
37 lines (32 loc) · 1.4 KB
/
string-literal-mutator.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import babel, { type NodePath } from '@babel/core';
import { NodeMutator } from './node-mutator.js';
const { types } = babel;
export const stringLiteralMutator: NodeMutator = {
name: 'StringLiteral',
*mutate(path) {
if (path.isTemplateLiteral()) {
const replacement = path.node.quasis.length === 1 && path.node.quasis[0].value.raw.length === 0 ? 'Stryker was here!' : '';
yield types.templateLiteral([types.templateElement({ raw: replacement })], []);
}
if (path.isStringLiteral() && isValidParent(path)) {
yield types.stringLiteral(path.node.value.length === 0 ? 'Stryker was here!' : '');
}
},
};
function isValidParent(child: NodePath<babel.types.StringLiteral>): boolean {
const parent = child.parent;
return !(
types.isImportDeclaration(parent) ||
types.isExportDeclaration(parent) ||
types.isImportOrExportDeclaration(parent) ||
types.isTSExternalModuleReference(parent) ||
types.isJSXAttribute(parent) ||
types.isExpressionStatement(parent) ||
types.isTSLiteralType(parent) ||
types.isObjectMethod(parent) ||
(types.isObjectProperty(parent) && parent.key === child.node) ||
(types.isClassProperty(parent) && parent.key === child.node) ||
(types.isCallExpression(parent) && types.isIdentifier(parent.callee, { name: 'require' })) ||
(types.isCallExpression(parent) && types.isIdentifier(parent.callee, { name: 'Symbol' }))
);
}