apex-mutation-testing 1.3.0 → 1.4.0-dev-92.22252711786-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/README.md +1 -1
- package/lib/adapter/sObjectDescribeRepository.d.ts +1 -1
- package/lib/adapter/sObjectDescribeRepository.js +19 -19
- package/lib/adapter/sObjectDescribeRepository.js.map +1 -1
- package/lib/mutator/arithmeticOperatorMutator.d.ts +4 -11
- package/lib/mutator/arithmeticOperatorMutator.js +25 -89
- package/lib/mutator/arithmeticOperatorMutator.js.map +1 -1
- package/lib/mutator/baseListener.d.ts +4 -3
- package/lib/mutator/baseListener.js +14 -3
- package/lib/mutator/baseListener.js.map +1 -1
- package/lib/mutator/emptyReturnMutator.d.ts +5 -3
- package/lib/mutator/emptyReturnMutator.js +32 -41
- package/lib/mutator/emptyReturnMutator.js.map +1 -1
- package/lib/mutator/falseReturnMutator.d.ts +5 -2
- package/lib/mutator/falseReturnMutator.js +18 -11
- package/lib/mutator/falseReturnMutator.js.map +1 -1
- package/lib/mutator/mutationListener.d.ts +1 -5
- package/lib/mutator/mutationListener.js +2 -29
- package/lib/mutator/mutationListener.js.map +1 -1
- package/lib/mutator/negationMutator.d.ts +5 -2
- package/lib/mutator/negationMutator.js +22 -12
- package/lib/mutator/negationMutator.js.map +1 -1
- package/lib/mutator/nonVoidMethodCallMutator.d.ts +12 -0
- package/lib/mutator/nonVoidMethodCallMutator.js +142 -0
- package/lib/mutator/nonVoidMethodCallMutator.js.map +1 -0
- package/lib/mutator/nullReturnMutator.d.ts +5 -2
- package/lib/mutator/nullReturnMutator.js +18 -8
- package/lib/mutator/nullReturnMutator.js.map +1 -1
- package/lib/mutator/trueReturnMutator.d.ts +5 -2
- package/lib/mutator/trueReturnMutator.js +18 -11
- package/lib/mutator/trueReturnMutator.js.map +1 -1
- package/lib/mutator/voidMethodCallMutator.d.ts +0 -1
- package/lib/mutator/voidMethodCallMutator.js +3 -10
- package/lib/mutator/voidMethodCallMutator.js.map +1 -1
- package/lib/service/mutantGenerator.d.ts +2 -3
- package/lib/service/mutantGenerator.js +11 -8
- package/lib/service/mutantGenerator.js.map +1 -1
- package/lib/service/mutationTestingService.js +8 -9
- package/lib/service/mutationTestingService.js.map +1 -1
- package/lib/service/typeDiscoverer.d.ts +7 -0
- package/lib/service/typeDiscoverer.js +134 -0
- package/lib/service/typeDiscoverer.js.map +1 -0
- package/lib/service/typeMatcher.d.ts +16 -1
- package/lib/service/typeMatcher.js +27 -1
- package/lib/service/typeMatcher.js.map +1 -1
- package/lib/type/ApexMethod.d.ts +22 -20
- package/lib/type/ApexMethod.js +45 -21
- package/lib/type/ApexMethod.js.map +1 -1
- package/lib/type/TypeRegistry.d.ts +22 -0
- package/lib/type/TypeRegistry.js +144 -0
- package/lib/type/TypeRegistry.js.map +1 -0
- package/npm-shrinkwrap.json +2 -2
- package/oclif.manifest.json +1 -1
- package/package.json +2 -2
- package/lib/mutator/returnTypeAwareBaseListener.d.ts +0 -12
- package/lib/mutator/returnTypeAwareBaseListener.js +0 -24
- package/lib/mutator/returnTypeAwareBaseListener.js.map +0 -1
- package/lib/service/typeGatherer.d.ts +0 -12
- package/lib/service/typeGatherer.js +0 -142
- package/lib/service/typeGatherer.js.map +0 -1
package/README.md
CHANGED
|
@@ -174,7 +174,7 @@ EXAMPLES
|
|
|
174
174
|
$ sf apex mutation test run --apex-class MyClass --test-class MyClassTest
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
-
_See code: [src/commands/apex/mutation/test/run.ts](https://github.com/scolladon/apex-mutation-testing/blob/v1.
|
|
177
|
+
_See code: [src/commands/apex/mutation/test/run.ts](https://github.com/scolladon/apex-mutation-testing/blob/v1.4.0-dev-92.22252711786-1/src/commands/apex/mutation/test/run.ts)_
|
|
178
178
|
<!-- commandsstop -->
|
|
179
179
|
|
|
180
180
|
## Backlog
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { mapLimit } from 'async';
|
|
2
|
-
import {
|
|
2
|
+
import { APEX_TYPE } from '../type/ApexMethod.js';
|
|
3
3
|
const DESCRIBE_FIELD_TYPE_MAP = {
|
|
4
|
-
int:
|
|
5
|
-
double:
|
|
6
|
-
currency:
|
|
7
|
-
percent:
|
|
8
|
-
date:
|
|
9
|
-
datetime:
|
|
10
|
-
boolean:
|
|
11
|
-
id:
|
|
12
|
-
reference:
|
|
13
|
-
string:
|
|
14
|
-
textarea:
|
|
15
|
-
email:
|
|
16
|
-
phone:
|
|
17
|
-
url:
|
|
18
|
-
picklist:
|
|
19
|
-
multipicklist:
|
|
20
|
-
encryptedstring:
|
|
4
|
+
int: APEX_TYPE.INTEGER,
|
|
5
|
+
double: APEX_TYPE.DOUBLE,
|
|
6
|
+
currency: APEX_TYPE.DECIMAL,
|
|
7
|
+
percent: APEX_TYPE.DOUBLE,
|
|
8
|
+
date: APEX_TYPE.DATE,
|
|
9
|
+
datetime: APEX_TYPE.DATETIME,
|
|
10
|
+
boolean: APEX_TYPE.BOOLEAN,
|
|
11
|
+
id: APEX_TYPE.ID,
|
|
12
|
+
reference: APEX_TYPE.ID,
|
|
13
|
+
string: APEX_TYPE.STRING,
|
|
14
|
+
textarea: APEX_TYPE.STRING,
|
|
15
|
+
email: APEX_TYPE.STRING,
|
|
16
|
+
phone: APEX_TYPE.STRING,
|
|
17
|
+
url: APEX_TYPE.STRING,
|
|
18
|
+
picklist: APEX_TYPE.STRING,
|
|
19
|
+
multipicklist: APEX_TYPE.STRING,
|
|
20
|
+
encryptedstring: APEX_TYPE.STRING,
|
|
21
21
|
};
|
|
22
22
|
const MAX_CONCURRENT_DESCRIBE_CALLS = 25;
|
|
23
23
|
export class SObjectDescribeRepository {
|
|
@@ -32,7 +32,7 @@ export class SObjectDescribeRepository {
|
|
|
32
32
|
const describeResult = await this.connection.describe(name);
|
|
33
33
|
const fieldMap = new Map();
|
|
34
34
|
for (const field of describeResult.fields) {
|
|
35
|
-
fieldMap.set(field.name.toLowerCase(), DESCRIBE_FIELD_TYPE_MAP[field.type] ??
|
|
35
|
+
fieldMap.set(field.name.toLowerCase(), DESCRIBE_FIELD_TYPE_MAP[field.type] ?? APEX_TYPE.OBJECT);
|
|
36
36
|
}
|
|
37
37
|
this.fieldTypes.set(name.toLowerCase(), fieldMap);
|
|
38
38
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sObjectDescribeRepository.js","sourceRoot":"","sources":["../../src/adapter/sObjectDescribeRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"sObjectDescribeRepository.js","sourceRoot":"","sources":["../../src/adapter/sObjectDescribeRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,OAAO,EAAE,SAAS,EAAqB,MAAM,uBAAuB,CAAA;AAEpE,MAAM,uBAAuB,GAA6B;IACxD,GAAG,EAAE,SAAS,CAAC,OAAO;IACtB,MAAM,EAAE,SAAS,CAAC,MAAM;IACxB,QAAQ,EAAE,SAAS,CAAC,OAAO;IAC3B,OAAO,EAAE,SAAS,CAAC,MAAM;IACzB,IAAI,EAAE,SAAS,CAAC,IAAI;IACpB,QAAQ,EAAE,SAAS,CAAC,QAAQ;IAC5B,OAAO,EAAE,SAAS,CAAC,OAAO;IAC1B,EAAE,EAAE,SAAS,CAAC,EAAE;IAChB,SAAS,EAAE,SAAS,CAAC,EAAE;IACvB,MAAM,EAAE,SAAS,CAAC,MAAM;IACxB,QAAQ,EAAE,SAAS,CAAC,MAAM;IAC1B,KAAK,EAAE,SAAS,CAAC,MAAM;IACvB,KAAK,EAAE,SAAS,CAAC,MAAM;IACvB,GAAG,EAAE,SAAS,CAAC,MAAM;IACrB,QAAQ,EAAE,SAAS,CAAC,MAAM;IAC1B,aAAa,EAAE,SAAS,CAAC,MAAM;IAC/B,eAAe,EAAE,SAAS,CAAC,MAAM;CAClC,CAAA;AAED,MAAM,6BAA6B,GAAG,EAAE,CAAA;AAExC,MAAM,OAAO,yBAAyB;IAGP;IAFZ,UAAU,GAAsB,IAAI,GAAG,EAAE,CAAA;IAE1D,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAEhD,KAAK,CAAC,QAAQ,CAAC,YAAsB;QAC1C,MAAM,QAAQ,CACZ,YAAY,EACZ,6BAA6B,EAC7B,KAAK,EAAE,IAAY,EAAE,EAAE;YACrB,IAAI,CAAC;gBACH,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;gBAC3D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAA;gBAC5C,KAAK,MAAM,KAAK,IAAI,cAAc,CAAC,MAAM,EAAE,CAAC;oBAC1C,QAAQ,CAAC,GAAG,CACV,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,EACxB,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,MAAM,CACxD,CAAA;gBACH,CAAC;gBACD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAA;YACnD,CAAC;YAAC,MAAM,CAAC;gBACP,6DAA6D;YAC/D,CAAC;QACH,CAAC,CACF,CAAA;IACH,CAAC;IAEM,SAAS,CAAC,QAAgB;QAC/B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;IACpD,CAAC;IAEM,gBAAgB,CACrB,eAAuB,EACvB,SAAiB;QAEjB,OAAO,IAAI,CAAC,UAAU;aACnB,GAAG,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC;YACnC,EAAE,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAA;IAClC,CAAC;CACF"}
|
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
import { ParserRuleContext } from 'antlr4ts';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { TypeRegistry } from '../type/TypeRegistry.js';
|
|
3
|
+
import { BaseListener } from './baseListener.js';
|
|
4
|
+
export declare class ArithmeticOperatorMutator extends BaseListener {
|
|
4
5
|
private readonly REPLACEMENT_MAP;
|
|
5
6
|
private static readonly NUMERIC_TYPES;
|
|
6
|
-
|
|
7
|
-
private classFields;
|
|
8
|
-
enterMethodDeclaration(ctx: ParserRuleContext): void;
|
|
9
|
-
enterLocalVariableDeclaration(ctx: ParserRuleContext): void;
|
|
10
|
-
enterFormalParameter(ctx: ParserRuleContext): void;
|
|
11
|
-
enterFieldDeclaration(ctx: ParserRuleContext): void;
|
|
12
|
-
enterEnhancedForControl(ctx: ParserRuleContext): void;
|
|
7
|
+
constructor(typeRegistry?: TypeRegistry);
|
|
13
8
|
enterArth1Expression(ctx: ParserRuleContext): void;
|
|
14
9
|
enterArth2Expression(ctx: ParserRuleContext): void;
|
|
15
10
|
enterAssignExpression(_ctx: ParserRuleContext): void;
|
|
16
11
|
private processArithmeticOperation;
|
|
17
12
|
private isNonNumericContext;
|
|
18
13
|
private isNonNumericOperand;
|
|
19
|
-
private resolveApexType;
|
|
20
|
-
private trackVariableDeclaration;
|
|
21
14
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TerminalNode } from 'antlr4ts/tree/index.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
export class ArithmeticOperatorMutator extends
|
|
2
|
+
import { APEX_TYPE } from '../type/ApexMethod.js';
|
|
3
|
+
import { BaseListener } from './baseListener.js';
|
|
4
|
+
export class ArithmeticOperatorMutator extends BaseListener {
|
|
5
5
|
REPLACEMENT_MAP = {
|
|
6
6
|
'+': ['-', '*', '/'],
|
|
7
7
|
'-': ['+', '*', '/'],
|
|
@@ -9,36 +9,13 @@ export class ArithmeticOperatorMutator extends ReturnTypeAwareBaseListener {
|
|
|
9
9
|
'/': ['+', '-', '*'],
|
|
10
10
|
};
|
|
11
11
|
static NUMERIC_TYPES = new Set([
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
APEX_TYPE.INTEGER,
|
|
13
|
+
APEX_TYPE.LONG,
|
|
14
|
+
APEX_TYPE.DOUBLE,
|
|
15
|
+
APEX_TYPE.DECIMAL,
|
|
16
16
|
]);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
enterMethodDeclaration(ctx) {
|
|
20
|
-
super.enterMethodDeclaration(ctx);
|
|
21
|
-
this.methodScopeVariables = new Map();
|
|
22
|
-
}
|
|
23
|
-
enterLocalVariableDeclaration(ctx) {
|
|
24
|
-
this.trackVariableDeclaration(ctx, this.methodScopeVariables);
|
|
25
|
-
}
|
|
26
|
-
enterFormalParameter(ctx) {
|
|
27
|
-
if (ctx.children && ctx.children.length >= 2) {
|
|
28
|
-
const typeName = ctx.children[ctx.children.length - 2].text;
|
|
29
|
-
const paramName = ctx.children[ctx.children.length - 1].text;
|
|
30
|
-
this.methodScopeVariables.set(paramName, typeName.toLowerCase());
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
enterFieldDeclaration(ctx) {
|
|
34
|
-
this.trackVariableDeclaration(ctx, this.classFields);
|
|
35
|
-
}
|
|
36
|
-
enterEnhancedForControl(ctx) {
|
|
37
|
-
if (ctx.children && ctx.children.length >= 2) {
|
|
38
|
-
const typeName = ctx.children[0].text;
|
|
39
|
-
const varName = ctx.children[1].text;
|
|
40
|
-
this.methodScopeVariables.set(varName, typeName.toLowerCase());
|
|
41
|
-
}
|
|
17
|
+
constructor(typeRegistry) {
|
|
18
|
+
super(typeRegistry);
|
|
42
19
|
}
|
|
43
20
|
// Handle MUL, DIV, and MOD operations (*, /, %)
|
|
44
21
|
enterArth1Expression(ctx) {
|
|
@@ -58,8 +35,13 @@ export class ArithmeticOperatorMutator extends ReturnTypeAwareBaseListener {
|
|
|
58
35
|
const operatorText = operatorNode.text;
|
|
59
36
|
const replacements = this.REPLACEMENT_MAP[operatorText];
|
|
60
37
|
if (replacements) {
|
|
61
|
-
if (operatorText === '+'
|
|
62
|
-
|
|
38
|
+
if (operatorText === '+') {
|
|
39
|
+
const methodName = this.typeRegistry
|
|
40
|
+
? this.getEnclosingMethodName(ctx)
|
|
41
|
+
: null;
|
|
42
|
+
if (this.isNonNumericContext(ctx, methodName)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
63
45
|
}
|
|
64
46
|
for (const replacement of replacements) {
|
|
65
47
|
this.createMutationFromTerminalNode(operatorNode, replacement);
|
|
@@ -68,70 +50,24 @@ export class ArithmeticOperatorMutator extends ReturnTypeAwareBaseListener {
|
|
|
68
50
|
}
|
|
69
51
|
}
|
|
70
52
|
}
|
|
71
|
-
isNonNumericContext(ctx) {
|
|
53
|
+
isNonNumericContext(ctx, methodName) {
|
|
72
54
|
const leftText = ctx.getChild(0).text;
|
|
73
55
|
const rightText = ctx.getChild(2).text;
|
|
74
|
-
return (this.isNonNumericOperand(leftText) ||
|
|
56
|
+
return (this.isNonNumericOperand(leftText, methodName) ||
|
|
57
|
+
this.isNonNumericOperand(rightText, methodName));
|
|
75
58
|
}
|
|
76
|
-
isNonNumericOperand(text) {
|
|
59
|
+
isNonNumericOperand(text, methodName) {
|
|
77
60
|
if (text.includes("'")) {
|
|
78
61
|
return true;
|
|
79
62
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (text.includes('.')) {
|
|
85
|
-
const rootVar = text.split('.')[0];
|
|
86
|
-
const rootType = this.methodScopeVariables.get(rootVar) ?? this.classFields.get(rootVar);
|
|
87
|
-
if (rootType !== undefined) {
|
|
88
|
-
if (this._sObjectDescribeRepository?.isSObject(rootType)) {
|
|
89
|
-
const fieldName = text.split('.').slice(1).join('.');
|
|
90
|
-
const fieldType = this._sObjectDescribeRepository.resolveFieldType(rootType, fieldName);
|
|
91
|
-
if (fieldType !== undefined) {
|
|
92
|
-
return !ArithmeticOperatorMutator.NUMERIC_TYPES.has(fieldType);
|
|
93
|
-
}
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
return !ArithmeticOperatorMutator.NUMERIC_TYPES.has(this.resolveApexType(rootType));
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
const methodCallMatch = text.match(/^(\w+)\(/);
|
|
100
|
-
if (methodCallMatch) {
|
|
101
|
-
const methodName = methodCallMatch[1];
|
|
102
|
-
const methodInfo = this.typeTable.get(methodName);
|
|
103
|
-
if (methodInfo) {
|
|
104
|
-
return !ArithmeticOperatorMutator.NUMERIC_TYPES.has(methodInfo.type);
|
|
63
|
+
if (this.typeRegistry && methodName) {
|
|
64
|
+
const resolved = this.typeRegistry.resolveType(methodName, text);
|
|
65
|
+
if (resolved) {
|
|
66
|
+
return !ArithmeticOperatorMutator.NUMERIC_TYPES.has(resolved.apexType);
|
|
105
67
|
}
|
|
68
|
+
return false;
|
|
106
69
|
}
|
|
107
70
|
return false;
|
|
108
71
|
}
|
|
109
|
-
resolveApexType(typeName) {
|
|
110
|
-
const typeMap = {
|
|
111
|
-
integer: ApexType.INTEGER,
|
|
112
|
-
long: ApexType.LONG,
|
|
113
|
-
double: ApexType.DOUBLE,
|
|
114
|
-
decimal: ApexType.DECIMAL,
|
|
115
|
-
string: ApexType.STRING,
|
|
116
|
-
boolean: ApexType.BOOLEAN,
|
|
117
|
-
date: ApexType.DATE,
|
|
118
|
-
datetime: ApexType.DATETIME,
|
|
119
|
-
id: ApexType.ID,
|
|
120
|
-
};
|
|
121
|
-
return typeMap[typeName] ?? ApexType.OBJECT;
|
|
122
|
-
}
|
|
123
|
-
trackVariableDeclaration(ctx, target) {
|
|
124
|
-
if (ctx.children && ctx.children.length >= 2) {
|
|
125
|
-
const typeName = ctx.children[0].text;
|
|
126
|
-
for (let i = 1; i < ctx.children.length; i++) {
|
|
127
|
-
const child = ctx.children[i];
|
|
128
|
-
const childText = child.text;
|
|
129
|
-
if (childText !== ',' && childText !== '=') {
|
|
130
|
-
const varName = childText.split('=')[0];
|
|
131
|
-
target.set(varName, typeName.toLowerCase());
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
72
|
}
|
|
137
73
|
//# sourceMappingURL=arithmeticOperatorMutator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arithmeticOperatorMutator.js","sourceRoot":"","sources":["../../src/mutator/arithmeticOperatorMutator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"arithmeticOperatorMutator.js","sourceRoot":"","sources":["../../src/mutator/arithmeticOperatorMutator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ParserRuleContext, Token } from 'antlr4ts';
|
|
2
2
|
import { TerminalNode } from 'antlr4ts/tree/index.js';
|
|
3
3
|
import { ApexParserListener } from 'apex-parser';
|
|
4
|
-
import { SObjectDescribeRepository } from '../adapter/sObjectDescribeRepository.js';
|
|
5
4
|
import { ApexMutation } from '../type/ApexMutation.js';
|
|
5
|
+
import { TypeRegistry } from '../type/TypeRegistry.js';
|
|
6
6
|
export declare class BaseListener implements ApexParserListener {
|
|
7
|
+
protected typeRegistry?: TypeRegistry | undefined;
|
|
7
8
|
_mutations: ApexMutation[];
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
constructor(typeRegistry?: TypeRegistry | undefined);
|
|
10
|
+
protected getEnclosingMethodName(ctx: ParserRuleContext): string | null;
|
|
10
11
|
protected createMutation(startToken: Token, endToken: Token, originalText: string, replacement: string): void;
|
|
11
12
|
protected createMutationFromParserRuleContext(ctx: ParserRuleContext, replacement: string): void;
|
|
12
13
|
protected createMutationFromTerminalNode(node: TerminalNode, replacement: string): void;
|
|
@@ -1,9 +1,20 @@
|
|
|
1
|
+
import { MethodDeclarationContext } from 'apex-parser';
|
|
1
2
|
// @ts-ignore: Base type with just a common _mutations property
|
|
2
3
|
export class BaseListener {
|
|
4
|
+
typeRegistry;
|
|
3
5
|
_mutations = [];
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
constructor(typeRegistry) {
|
|
7
|
+
this.typeRegistry = typeRegistry;
|
|
8
|
+
}
|
|
9
|
+
getEnclosingMethodName(ctx) {
|
|
10
|
+
let current = ctx.parent;
|
|
11
|
+
while (current) {
|
|
12
|
+
if (current instanceof MethodDeclarationContext) {
|
|
13
|
+
return current.children?.[1]?.text ?? null;
|
|
14
|
+
}
|
|
15
|
+
current = current.parent;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
7
18
|
}
|
|
8
19
|
createMutation(startToken, endToken, originalText, replacement) {
|
|
9
20
|
this._mutations.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseListener.js","sourceRoot":"","sources":["../../src/mutator/baseListener.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"baseListener.js","sourceRoot":"","sources":["../../src/mutator/baseListener.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsB,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAI1E,+DAA+D;AAC/D,MAAM,OAAO,YAAY;IAGD;IAFtB,UAAU,GAAmB,EAAE,CAAA;IAE/B,YAAsB,YAA2B;QAA3B,iBAAY,GAAZ,YAAY,CAAe;IAAG,CAAC;IAE3C,sBAAsB,CAAC,GAAsB;QACrD,IAAI,OAAO,GAAkC,GAAG,CAAC,MAEpC,CAAA;QACb,OAAO,OAAO,EAAE,CAAC;YACf,IAAI,OAAO,YAAY,wBAAwB,EAAE,CAAC;gBAChD,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,IAAI,CAAA;YAC5C,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,MAAuC,CAAA;QAC3D,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAES,cAAc,CACtB,UAAiB,EACjB,QAAe,EACf,YAAoB,EACpB,WAAmB;QAEnB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YACnB,YAAY,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI;YACnC,MAAM,EAAE;gBACN,UAAU;gBACV,QAAQ;gBACR,IAAI,EAAE,YAAY;aACnB;YACD,WAAW;SACZ,CAAC,CAAA;IACJ,CAAC;IAES,mCAAmC,CAC3C,GAAsB,EACtB,WAAmB;QAEnB,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QACjE,CAAC;IACH,CAAC;IAES,8BAA8B,CACtC,IAAkB,EAClB,WAAmB;QAEnB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QACvE,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { ParserRuleContext } from 'antlr4ts';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { TypeRegistry } from '../type/TypeRegistry.js';
|
|
3
|
+
import { BaseListener } from './baseListener.js';
|
|
4
|
+
export declare class EmptyReturnMutator extends BaseListener {
|
|
5
|
+
constructor(typeRegistry?: TypeRegistry);
|
|
4
6
|
enterReturnStatement(ctx: ParserRuleContext): void;
|
|
5
|
-
private
|
|
7
|
+
private getTypeInfoForMutation;
|
|
6
8
|
isEmptyValue(type: string, expressionText: string): boolean;
|
|
7
9
|
}
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import { ParserRuleContext } from 'antlr4ts';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { APEX_TYPE, getDefaultValueForApexType } from '../type/ApexMethod.js';
|
|
3
|
+
import { BaseListener } from './baseListener.js';
|
|
4
|
+
const SKIP_TYPES = new Set([
|
|
5
|
+
APEX_TYPE.VOID,
|
|
6
|
+
APEX_TYPE.BOOLEAN,
|
|
7
|
+
APEX_TYPE.SOBJECT,
|
|
8
|
+
APEX_TYPE.OBJECT,
|
|
9
|
+
APEX_TYPE.APEX_CLASS,
|
|
10
|
+
APEX_TYPE.DATE,
|
|
11
|
+
APEX_TYPE.DATETIME,
|
|
12
|
+
APEX_TYPE.TIME,
|
|
13
|
+
]);
|
|
14
|
+
export class EmptyReturnMutator extends BaseListener {
|
|
15
|
+
constructor(typeRegistry) {
|
|
16
|
+
super(typeRegistry);
|
|
17
|
+
}
|
|
5
18
|
enterReturnStatement(ctx) {
|
|
6
|
-
|
|
7
|
-
return;
|
|
8
|
-
}
|
|
9
|
-
const typeInfo = this.getCurrentMethodReturnTypeInfo();
|
|
19
|
+
const typeInfo = this.getTypeInfoForMutation(ctx);
|
|
10
20
|
if (!typeInfo) {
|
|
11
21
|
return;
|
|
12
22
|
}
|
|
13
|
-
|
|
14
|
-
if ([
|
|
15
|
-
ApexType.VOID,
|
|
16
|
-
ApexType.BOOLEAN,
|
|
17
|
-
ApexType.SOBJECT,
|
|
18
|
-
ApexType.OBJECT,
|
|
19
|
-
ApexType.APEX_CLASS,
|
|
20
|
-
ApexType.DATE,
|
|
21
|
-
ApexType.DATETIME,
|
|
22
|
-
ApexType.TIME,
|
|
23
|
-
].includes(typeInfo.type)) {
|
|
23
|
+
if (SKIP_TYPES.has(typeInfo.apexType)) {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
26
|
if (!ctx.children || ctx.children.length < 2) {
|
|
@@ -30,36 +30,27 @@ export class EmptyReturnMutator extends ReturnTypeAwareBaseListener {
|
|
|
30
30
|
if (!(expressionNode instanceof ParserRuleContext)) {
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
-
if (this.isEmptyValue(typeInfo.
|
|
33
|
+
if (this.isEmptyValue(typeInfo.typeName, expressionNode.text)) {
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
|
-
const emptyValue =
|
|
36
|
+
const emptyValue = getDefaultValueForApexType(typeInfo.apexType, typeInfo.typeName);
|
|
37
37
|
if (emptyValue) {
|
|
38
38
|
this.createMutationFromParserRuleContext(expressionNode, emptyValue);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return '0.0';
|
|
53
|
-
case ApexType.BLOB:
|
|
54
|
-
return "Blob.valueOf('')";
|
|
55
|
-
case ApexType.LIST:
|
|
56
|
-
case ApexType.SET:
|
|
57
|
-
case ApexType.MAP:
|
|
58
|
-
case ApexType.SOBJECT:
|
|
59
|
-
return `new ${typeInfo.returnType}()`;
|
|
60
|
-
default:
|
|
61
|
-
return null;
|
|
41
|
+
getTypeInfoForMutation(ctx) {
|
|
42
|
+
if (!this.typeRegistry) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const methodName = this.getEnclosingMethodName(ctx);
|
|
46
|
+
if (!methodName) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const resolved = this.typeRegistry.resolveType(methodName);
|
|
50
|
+
if (!resolved) {
|
|
51
|
+
return null;
|
|
62
52
|
}
|
|
53
|
+
return { apexType: resolved.apexType, typeName: resolved.typeName };
|
|
63
54
|
}
|
|
64
55
|
isEmptyValue(type, expressionText) {
|
|
65
56
|
const lowerType = type.toLowerCase();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emptyReturnMutator.js","sourceRoot":"","sources":["../../src/mutator/emptyReturnMutator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"emptyReturnMutator.js","sourceRoot":"","sources":["../../src/mutator/emptyReturnMutator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { ParserRuleContext } from 'antlr4ts';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { TypeRegistry } from '../type/TypeRegistry.js';
|
|
3
|
+
import { BaseListener } from './baseListener.js';
|
|
4
|
+
export declare class FalseReturnMutator extends BaseListener {
|
|
5
|
+
constructor(typeRegistry?: TypeRegistry);
|
|
4
6
|
enterReturnStatement(ctx: ParserRuleContext): void;
|
|
7
|
+
private shouldMutate;
|
|
5
8
|
}
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import { ParserRuleContext } from 'antlr4ts';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
export class FalseReturnMutator extends
|
|
2
|
+
import { APEX_TYPE } from '../type/ApexMethod.js';
|
|
3
|
+
import { BaseListener } from './baseListener.js';
|
|
4
|
+
export class FalseReturnMutator extends BaseListener {
|
|
5
|
+
constructor(typeRegistry) {
|
|
6
|
+
super(typeRegistry);
|
|
7
|
+
}
|
|
5
8
|
enterReturnStatement(ctx) {
|
|
6
|
-
if (!this.
|
|
7
|
-
return;
|
|
8
|
-
}
|
|
9
|
-
const typeInfo = this.getCurrentMethodReturnTypeInfo();
|
|
10
|
-
if (!typeInfo) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
if (typeInfo.type !== ApexType.BOOLEAN) {
|
|
9
|
+
if (!this.shouldMutate(ctx)) {
|
|
14
10
|
return;
|
|
15
11
|
}
|
|
16
12
|
if (!ctx.children || ctx.children.length < 2) {
|
|
@@ -25,5 +21,16 @@ export class FalseReturnMutator extends ReturnTypeAwareBaseListener {
|
|
|
25
21
|
}
|
|
26
22
|
this.createMutationFromParserRuleContext(expressionNode, 'false');
|
|
27
23
|
}
|
|
24
|
+
shouldMutate(ctx) {
|
|
25
|
+
if (!this.typeRegistry) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
const methodName = this.getEnclosingMethodName(ctx);
|
|
29
|
+
if (!methodName) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
const typeInfo = this.typeRegistry.resolveType(methodName);
|
|
33
|
+
return !!typeInfo && typeInfo.apexType === APEX_TYPE.BOOLEAN;
|
|
34
|
+
}
|
|
28
35
|
}
|
|
29
36
|
//# sourceMappingURL=falseReturnMutator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"falseReturnMutator.js","sourceRoot":"","sources":["../../src/mutator/falseReturnMutator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"falseReturnMutator.js","sourceRoot":"","sources":["../../src/mutator/falseReturnMutator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,MAAM,OAAO,kBAAmB,SAAQ,YAAY;IAClD,YAAY,YAA2B;QACrC,KAAK,CAAC,YAAY,CAAC,CAAA;IACrB,CAAC;IAED,oBAAoB,CAAC,GAAsB;QACzC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAM;QACR,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,OAAM;QACR,CAAC;QAED,MAAM,cAAc,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QACtC,IAAI,CAAC,CAAC,cAAc,YAAY,iBAAiB,CAAC,EAAE,CAAC;YACnD,OAAM;QACR,CAAC;QAED,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,CAAC;YACzD,OAAM;QACR,CAAC;QAED,IAAI,CAAC,mCAAmC,CAAC,cAAc,EAAE,OAAO,CAAC,CAAA;IACnE,CAAC;IAEO,YAAY,CAAC,GAAsB;QACzC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,OAAO,KAAK,CAAA;QACd,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAA;QACnD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,KAAK,CAAA;QACd,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,UAAU,CAAC,CAAA;QAC1D,OAAO,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,CAAC,OAAO,CAAA;IAC9D,CAAC;CACF"}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { ApexParserListener } from 'apex-parser';
|
|
2
|
-
import { SObjectDescribeRepository } from '../adapter/sObjectDescribeRepository.js';
|
|
3
|
-
import { ApexMethod } from '../type/ApexMethod.js';
|
|
4
2
|
import { ApexMutation } from '../type/ApexMutation.js';
|
|
5
3
|
import { BaseListener } from './baseListener.js';
|
|
6
4
|
export declare class MutationListener implements ApexParserListener {
|
|
7
5
|
protected readonly coveredLines: Set<number>;
|
|
8
|
-
protected readonly typeTable?: Map<string, ApexMethod> | undefined;
|
|
9
6
|
private listeners;
|
|
10
7
|
_mutations: ApexMutation[];
|
|
11
|
-
private static readonly ALWAYS_FORWARD_METHODS;
|
|
12
8
|
getMutations(): ApexMutation[];
|
|
13
|
-
constructor(listeners: BaseListener[], coveredLines: Set<number
|
|
9
|
+
constructor(listeners: BaseListener[], coveredLines: Set<number>);
|
|
14
10
|
}
|
|
@@ -1,39 +1,14 @@
|
|
|
1
|
-
import { ReturnTypeAwareBaseListener } from './returnTypeAwareBaseListener.js';
|
|
2
1
|
// @ts-ignore: Just a proxy doing accumulation of mutations
|
|
3
2
|
export class MutationListener {
|
|
4
3
|
coveredLines;
|
|
5
|
-
typeTable;
|
|
6
4
|
listeners;
|
|
7
5
|
_mutations = [];
|
|
8
|
-
// Methods that should always be called regardless of covered lines
|
|
9
|
-
// These are needed for tracking method context in type-aware mutators
|
|
10
|
-
static ALWAYS_FORWARD_METHODS = new Set([
|
|
11
|
-
'enterMethodDeclaration',
|
|
12
|
-
'exitMethodDeclaration',
|
|
13
|
-
'enterLocalVariableDeclaration',
|
|
14
|
-
'enterFormalParameter',
|
|
15
|
-
'enterFieldDeclaration',
|
|
16
|
-
'enterEnhancedForControl',
|
|
17
|
-
]);
|
|
18
6
|
getMutations() {
|
|
19
7
|
return this._mutations;
|
|
20
8
|
}
|
|
21
|
-
constructor(listeners, coveredLines
|
|
9
|
+
constructor(listeners, coveredLines) {
|
|
22
10
|
this.coveredLines = coveredLines;
|
|
23
|
-
this.typeTable = typeTable;
|
|
24
11
|
this.listeners = listeners;
|
|
25
|
-
if (typeTable) {
|
|
26
|
-
this.listeners.forEach(listener => {
|
|
27
|
-
if (listener instanceof ReturnTypeAwareBaseListener) {
|
|
28
|
-
listener.setTypeTable(typeTable);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
if (sObjectDescribeRepository) {
|
|
33
|
-
this.listeners.forEach(listener => {
|
|
34
|
-
listener.setSObjectDescribeRepository(sObjectDescribeRepository);
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
12
|
// Share mutations array across all listeners
|
|
38
13
|
this.listeners
|
|
39
14
|
.filter(listener => '_mutations' in listener)
|
|
@@ -51,9 +26,7 @@ export class MutationListener {
|
|
|
51
26
|
return (...args) => {
|
|
52
27
|
if (Array.isArray(args) && args.length > 0) {
|
|
53
28
|
const ctx = args[0];
|
|
54
|
-
|
|
55
|
-
this.coveredLines.has(ctx?.start?.line);
|
|
56
|
-
if (shouldForward) {
|
|
29
|
+
if (this.coveredLines.has(ctx?.start?.line)) {
|
|
57
30
|
this.listeners.forEach(listener => {
|
|
58
31
|
if (prop in listener && typeof listener[prop] === 'function') {
|
|
59
32
|
;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutationListener.js","sourceRoot":"","sources":["../../src/mutator/mutationListener.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mutationListener.js","sourceRoot":"","sources":["../../src/mutator/mutationListener.ts"],"names":[],"mappings":"AAKA,2DAA2D;AAC3D,MAAM,OAAO,gBAAgB;IAUN;IATb,SAAS,CAAgB;IACjC,UAAU,GAAmB,EAAE,CAAA;IAExB,YAAY;QACjB,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;IAED,YACE,SAAyB,EACN,YAAyB;QAAzB,iBAAY,GAAZ,YAAY,CAAa;QAE5C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAE1B,6CAA6C;QAC7C,IAAI,CAAC,SAAS;aACX,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,YAAY,IAAI,QAAQ,CAAC;aAC5C,OAAO,CAAC,QAAQ,CAAC,EAAE;YAClB,CAAC;YAAC,QAAyB,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAA;QAC1D,CAAC,CAAC,CAAA;QAEJ,2EAA2E;QAC3E,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE;YACrB,GAAG,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;gBACpB,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;oBACnB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAA;gBACrB,CAAC;gBAED,wEAAwE;gBACxE,OAAO,CAAC,GAAG,IAAe,EAAE,EAAE;oBAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAsB,CAAA;wBACxC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;4BAC5C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;gCAChC,IAAI,IAAI,IAAI,QAAQ,IAAI,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC;oCAC7D,CAAC;oCAAC,QAAQ,CAAC,IAAI,CAAc,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;gCACrD,CAAC;4BACH,CAAC,CAAC,CAAA;wBACJ,CAAC;oBACH,CAAC;gBACH,CAAC,CAAA;YACH,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;CACF"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { ParserRuleContext } from 'antlr4ts';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { TypeRegistry } from '../type/TypeRegistry.js';
|
|
3
|
+
import { BaseListener } from './baseListener.js';
|
|
4
|
+
export declare class NegationMutator extends BaseListener {
|
|
4
5
|
private static readonly NUMERIC_TYPES;
|
|
5
6
|
private static readonly ZERO_LITERAL;
|
|
7
|
+
constructor(typeRegistry?: TypeRegistry);
|
|
6
8
|
enterReturnStatement(ctx: ParserRuleContext): void;
|
|
9
|
+
private isNumericReturn;
|
|
7
10
|
private isNegatedExpression;
|
|
8
11
|
private formatNegation;
|
|
9
12
|
}
|