apex-mutation-testing 1.3.0-dev-83.21870988968-1 → 1.3.0-dev-83.22024108564-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 +10 -0
- package/lib/adapter/sObjectDescribeRepository.js +53 -0
- package/lib/adapter/sObjectDescribeRepository.js.map +1 -0
- package/lib/mutator/arithmeticOperatorMutator.d.ts +14 -2
- package/lib/mutator/arithmeticOperatorMutator.js +103 -2
- package/lib/mutator/arithmeticOperatorMutator.js.map +1 -1
- package/lib/mutator/baseListener.d.ts +3 -0
- package/lib/mutator/baseListener.js +4 -0
- package/lib/mutator/baseListener.js.map +1 -1
- package/lib/mutator/emptyReturnMutator.js +1 -2
- package/lib/mutator/emptyReturnMutator.js.map +1 -1
- package/lib/mutator/mutationListener.d.ts +3 -1
- package/lib/mutator/mutationListener.js +19 -2
- package/lib/mutator/mutationListener.js.map +1 -1
- package/lib/mutator/negationMutator.d.ts +6 -4
- package/lib/mutator/negationMutator.js +43 -23
- package/lib/mutator/negationMutator.js.map +1 -1
- package/lib/service/mutantGenerator.d.ts +3 -2
- package/lib/service/mutantGenerator.js +2 -3
- package/lib/service/mutantGenerator.js.map +1 -1
- package/lib/service/mutationTestingService.js +12 -3
- package/lib/service/mutationTestingService.js.map +1 -1
- package/lib/service/typeGatherer.d.ts +12 -0
- package/lib/service/typeGatherer.js +142 -0
- package/lib/service/typeGatherer.js.map +1 -0
- package/lib/service/typeMatcher.d.ts +13 -0
- package/lib/service/typeMatcher.js +19 -0
- package/lib/service/typeMatcher.js.map +1 -0
- package/lib/type/ApexMethod.d.ts +1 -2
- package/lib/type/ApexMethod.js +0 -2
- package/lib/type/ApexMethod.js.map +1 -1
- package/npm-shrinkwrap.json +242 -180
- package/oclif.manifest.json +1 -1
- package/package.json +7 -5
- package/lib/mutator/methodTypeListener.d.ts +0 -12
- package/lib/mutator/methodTypeListener.js +0 -114
- package/lib/mutator/methodTypeListener.js.map +0 -1
- package/lib/service/apexTypeResolver.d.ts +0 -9
- package/lib/service/apexTypeResolver.js +0 -18
- package/lib/service/apexTypeResolver.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.3.0-dev-83.
|
|
177
|
+
_See code: [src/commands/apex/mutation/test/run.ts](https://github.com/scolladon/apex-mutation-testing/blob/v1.3.0-dev-83.22024108564-1/src/commands/apex/mutation/test/run.ts)_
|
|
178
178
|
<!-- commandsstop -->
|
|
179
179
|
|
|
180
180
|
## Backlog
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Connection } from '@salesforce/core';
|
|
2
|
+
import { ApexType } from '../type/ApexMethod.js';
|
|
3
|
+
export declare class SObjectDescribeRepository {
|
|
4
|
+
private readonly connection;
|
|
5
|
+
private readonly fieldTypes;
|
|
6
|
+
constructor(connection: Connection);
|
|
7
|
+
describe(sObjectNames: string[]): Promise<void>;
|
|
8
|
+
isSObject(typeName: string): boolean;
|
|
9
|
+
resolveFieldType(sObjectTypeName: string, fieldPath: string): ApexType | undefined;
|
|
10
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { mapLimit } from 'async';
|
|
2
|
+
import { ApexType } from '../type/ApexMethod.js';
|
|
3
|
+
const DESCRIBE_FIELD_TYPE_MAP = {
|
|
4
|
+
int: ApexType.INTEGER,
|
|
5
|
+
double: ApexType.DOUBLE,
|
|
6
|
+
currency: ApexType.DECIMAL,
|
|
7
|
+
percent: ApexType.DOUBLE,
|
|
8
|
+
date: ApexType.DATE,
|
|
9
|
+
datetime: ApexType.DATETIME,
|
|
10
|
+
boolean: ApexType.BOOLEAN,
|
|
11
|
+
id: ApexType.ID,
|
|
12
|
+
reference: ApexType.ID,
|
|
13
|
+
string: ApexType.STRING,
|
|
14
|
+
textarea: ApexType.STRING,
|
|
15
|
+
email: ApexType.STRING,
|
|
16
|
+
phone: ApexType.STRING,
|
|
17
|
+
url: ApexType.STRING,
|
|
18
|
+
picklist: ApexType.STRING,
|
|
19
|
+
multipicklist: ApexType.STRING,
|
|
20
|
+
encryptedstring: ApexType.STRING,
|
|
21
|
+
};
|
|
22
|
+
const MAX_CONCURRENT_DESCRIBE_CALLS = 25;
|
|
23
|
+
export class SObjectDescribeRepository {
|
|
24
|
+
connection;
|
|
25
|
+
fieldTypes = new Map();
|
|
26
|
+
constructor(connection) {
|
|
27
|
+
this.connection = connection;
|
|
28
|
+
}
|
|
29
|
+
async describe(sObjectNames) {
|
|
30
|
+
await mapLimit(sObjectNames, MAX_CONCURRENT_DESCRIBE_CALLS, async (name) => {
|
|
31
|
+
try {
|
|
32
|
+
const describeResult = await this.connection.describe(name);
|
|
33
|
+
const fieldMap = new Map();
|
|
34
|
+
for (const field of describeResult.fields) {
|
|
35
|
+
fieldMap.set(field.name.toLowerCase(), DESCRIBE_FIELD_TYPE_MAP[field.type] ?? ApexType.OBJECT);
|
|
36
|
+
}
|
|
37
|
+
this.fieldTypes.set(name.toLowerCase(), fieldMap);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Skip sObjects that fail to describe (graceful degradation)
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
isSObject(typeName) {
|
|
45
|
+
return this.fieldTypes.has(typeName.toLowerCase());
|
|
46
|
+
}
|
|
47
|
+
resolveFieldType(sObjectTypeName, fieldPath) {
|
|
48
|
+
return this.fieldTypes
|
|
49
|
+
.get(sObjectTypeName.toLowerCase())
|
|
50
|
+
?.get(fieldPath.toLowerCase());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=sObjectDescribeRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sObjectDescribeRepository.js","sourceRoot":"","sources":["../../src/adapter/sObjectDescribeRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAqB,MAAM,uBAAuB,CAAA;AAEnE,MAAM,uBAAuB,GAA6B;IACxD,GAAG,EAAE,QAAQ,CAAC,OAAO;IACrB,MAAM,EAAE,QAAQ,CAAC,MAAM;IACvB,QAAQ,EAAE,QAAQ,CAAC,OAAO;IAC1B,OAAO,EAAE,QAAQ,CAAC,MAAM;IACxB,IAAI,EAAE,QAAQ,CAAC,IAAI;IACnB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;IAC3B,OAAO,EAAE,QAAQ,CAAC,OAAO;IACzB,EAAE,EAAE,QAAQ,CAAC,EAAE;IACf,SAAS,EAAE,QAAQ,CAAC,EAAE;IACtB,MAAM,EAAE,QAAQ,CAAC,MAAM;IACvB,QAAQ,EAAE,QAAQ,CAAC,MAAM;IACzB,KAAK,EAAE,QAAQ,CAAC,MAAM;IACtB,KAAK,EAAE,QAAQ,CAAC,MAAM;IACtB,GAAG,EAAE,QAAQ,CAAC,MAAM;IACpB,QAAQ,EAAE,QAAQ,CAAC,MAAM;IACzB,aAAa,EAAE,QAAQ,CAAC,MAAM;IAC9B,eAAe,EAAE,QAAQ,CAAC,MAAM;CACjC,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,QAAQ,CAAC,MAAM,CACvD,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,9 +1,21 @@
|
|
|
1
1
|
import { ParserRuleContext } from 'antlr4ts';
|
|
2
|
-
import {
|
|
3
|
-
export declare class ArithmeticOperatorMutator extends
|
|
2
|
+
import { ReturnTypeAwareBaseListener } from './returnTypeAwareBaseListener.js';
|
|
3
|
+
export declare class ArithmeticOperatorMutator extends ReturnTypeAwareBaseListener {
|
|
4
4
|
private readonly REPLACEMENT_MAP;
|
|
5
|
+
private static readonly NUMERIC_TYPES;
|
|
6
|
+
private methodScopeVariables;
|
|
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;
|
|
5
13
|
enterArth1Expression(ctx: ParserRuleContext): void;
|
|
6
14
|
enterArth2Expression(ctx: ParserRuleContext): void;
|
|
7
15
|
enterAssignExpression(_ctx: ParserRuleContext): void;
|
|
8
16
|
private processArithmeticOperation;
|
|
17
|
+
private isNonNumericContext;
|
|
18
|
+
private isNonNumericOperand;
|
|
19
|
+
private resolveApexType;
|
|
20
|
+
private trackVariableDeclaration;
|
|
9
21
|
}
|
|
@@ -1,12 +1,45 @@
|
|
|
1
1
|
import { TerminalNode } from 'antlr4ts/tree/index.js';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { ApexType } from '../type/ApexMethod.js';
|
|
3
|
+
import { ReturnTypeAwareBaseListener } from './returnTypeAwareBaseListener.js';
|
|
4
|
+
export class ArithmeticOperatorMutator extends ReturnTypeAwareBaseListener {
|
|
4
5
|
REPLACEMENT_MAP = {
|
|
5
6
|
'+': ['-', '*', '/'],
|
|
6
7
|
'-': ['+', '*', '/'],
|
|
7
8
|
'*': ['+', '-', '/'],
|
|
8
9
|
'/': ['+', '-', '*'],
|
|
9
10
|
};
|
|
11
|
+
static NUMERIC_TYPES = new Set([
|
|
12
|
+
ApexType.INTEGER,
|
|
13
|
+
ApexType.LONG,
|
|
14
|
+
ApexType.DOUBLE,
|
|
15
|
+
ApexType.DECIMAL,
|
|
16
|
+
]);
|
|
17
|
+
methodScopeVariables = new Map();
|
|
18
|
+
classFields = new Map();
|
|
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
|
+
}
|
|
42
|
+
}
|
|
10
43
|
// Handle MUL, DIV, and MOD operations (*, /, %)
|
|
11
44
|
enterArth1Expression(ctx) {
|
|
12
45
|
this.processArithmeticOperation(ctx);
|
|
@@ -25,6 +58,9 @@ export class ArithmeticOperatorMutator extends BaseListener {
|
|
|
25
58
|
const operatorText = operatorNode.text;
|
|
26
59
|
const replacements = this.REPLACEMENT_MAP[operatorText];
|
|
27
60
|
if (replacements) {
|
|
61
|
+
if (operatorText === '+' && this.isNonNumericContext(ctx)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
28
64
|
for (const replacement of replacements) {
|
|
29
65
|
this.createMutationFromTerminalNode(operatorNode, replacement);
|
|
30
66
|
}
|
|
@@ -32,5 +68,70 @@ export class ArithmeticOperatorMutator extends BaseListener {
|
|
|
32
68
|
}
|
|
33
69
|
}
|
|
34
70
|
}
|
|
71
|
+
isNonNumericContext(ctx) {
|
|
72
|
+
const leftText = ctx.getChild(0).text;
|
|
73
|
+
const rightText = ctx.getChild(2).text;
|
|
74
|
+
return (this.isNonNumericOperand(leftText) || this.isNonNumericOperand(rightText));
|
|
75
|
+
}
|
|
76
|
+
isNonNumericOperand(text) {
|
|
77
|
+
if (text.includes("'")) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
const variableType = this.methodScopeVariables.get(text) ?? this.classFields.get(text);
|
|
81
|
+
if (variableType !== undefined) {
|
|
82
|
+
return !ArithmeticOperatorMutator.NUMERIC_TYPES.has(this.resolveApexType(variableType));
|
|
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);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
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
|
+
}
|
|
35
136
|
}
|
|
36
137
|
//# 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;AACrD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"arithmeticOperatorMutator.js","sourceRoot":"","sources":["../../src/mutator/arithmeticOperatorMutator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,12 @@
|
|
|
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';
|
|
4
5
|
import { ApexMutation } from '../type/ApexMutation.js';
|
|
5
6
|
export declare class BaseListener implements ApexParserListener {
|
|
6
7
|
_mutations: ApexMutation[];
|
|
8
|
+
_sObjectDescribeRepository?: SObjectDescribeRepository;
|
|
9
|
+
setSObjectDescribeRepository(repository: SObjectDescribeRepository): void;
|
|
7
10
|
protected createMutation(startToken: Token, endToken: Token, originalText: string, replacement: string): void;
|
|
8
11
|
protected createMutationFromParserRuleContext(ctx: ParserRuleContext, replacement: string): void;
|
|
9
12
|
protected createMutationFromTerminalNode(node: TerminalNode, replacement: string): void;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// @ts-ignore: Base type with just a common _mutations property
|
|
2
2
|
export class BaseListener {
|
|
3
3
|
_mutations = [];
|
|
4
|
+
_sObjectDescribeRepository;
|
|
5
|
+
setSObjectDescribeRepository(repository) {
|
|
6
|
+
this._sObjectDescribeRepository = repository;
|
|
7
|
+
}
|
|
4
8
|
createMutation(startToken, endToken, originalText, replacement) {
|
|
5
9
|
this._mutations.push({
|
|
6
10
|
mutationName: this.constructor.name,
|
|
@@ -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":"AAMA,+DAA+D;AAC/D,MAAM,OAAO,YAAY;IACvB,UAAU,GAAmB,EAAE,CAAA;IAC/B,0BAA0B,CAA4B;IAEtD,4BAA4B,CAAC,UAAqC;QAChE,IAAI,CAAC,0BAA0B,GAAG,UAAU,CAAA;IAC9C,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"}
|
|
@@ -55,8 +55,7 @@ export class EmptyReturnMutator extends ReturnTypeAwareBaseListener {
|
|
|
55
55
|
case ApexType.LIST:
|
|
56
56
|
case ApexType.SET:
|
|
57
57
|
case ApexType.MAP:
|
|
58
|
-
case ApexType.
|
|
59
|
-
case ApexType.STANDARD_ENTITY:
|
|
58
|
+
case ApexType.SOBJECT:
|
|
60
59
|
return `new ${typeInfo.returnType}()`;
|
|
61
60
|
default:
|
|
62
61
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emptyReturnMutator.js","sourceRoot":"","sources":["../../src/mutator/emptyReturnMutator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAc,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAA;AAE9E,MAAM,OAAO,kBAAmB,SAAQ,2BAA2B;IACjE,oBAAoB,CAAC,GAAsB;QACzC,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;YACrC,OAAM;QACR,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,8BAA8B,EAAE,CAAA;QACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAM;QACR,CAAC;QAED,oCAAoC;QACpC,IACE;YACE,QAAQ,CAAC,IAAI;YACb,QAAQ,CAAC,OAAO;YAChB,QAAQ,CAAC,OAAO;YAChB,QAAQ,CAAC,MAAM;YACf,QAAQ,CAAC,UAAU;YACnB,QAAQ,CAAC,IAAI;YACb,QAAQ,CAAC,QAAQ;YACjB,QAAQ,CAAC,IAAI;SACd,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EACzB,CAAC;YACD,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,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YAChE,OAAM;QACR,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAA;QACpD,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,mCAAmC,CAAC,cAAc,EAAE,UAAU,CAAC,CAAA;QACtE,CAAC;IACH,CAAC;IAEO,kBAAkB,CAAC,QAAoB;QAC7C,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;YACtB,KAAK,QAAQ,CAAC,MAAM,CAAC;YACrB,KAAK,QAAQ,CAAC,EAAE;gBACd,OAAO,IAAI,CAAA;YAEb,KAAK,QAAQ,CAAC,OAAO;gBACnB,OAAO,GAAG,CAAA;YAEZ,KAAK,QAAQ,CAAC,IAAI;gBAChB,OAAO,IAAI,CAAA;YAEb,KAAK,QAAQ,CAAC,MAAM,CAAC;YACrB,KAAK,QAAQ,CAAC,OAAO;gBACnB,OAAO,KAAK,CAAA;YAEd,KAAK,QAAQ,CAAC,IAAI;gBAChB,OAAO,kBAAkB,CAAA;YAE3B,KAAK,QAAQ,CAAC,IAAI,CAAC;YACnB,KAAK,QAAQ,CAAC,GAAG,CAAC;YAClB,KAAK,QAAQ,CAAC,GAAG,CAAC;YAClB,KAAK,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"emptyReturnMutator.js","sourceRoot":"","sources":["../../src/mutator/emptyReturnMutator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ApexParserListener } from 'apex-parser';
|
|
2
|
+
import { SObjectDescribeRepository } from '../adapter/sObjectDescribeRepository.js';
|
|
2
3
|
import { ApexMethod } from '../type/ApexMethod.js';
|
|
3
4
|
import { ApexMutation } from '../type/ApexMutation.js';
|
|
4
5
|
import { BaseListener } from './baseListener.js';
|
|
@@ -7,6 +8,7 @@ export declare class MutationListener implements ApexParserListener {
|
|
|
7
8
|
protected readonly typeTable?: Map<string, ApexMethod> | undefined;
|
|
8
9
|
private listeners;
|
|
9
10
|
_mutations: ApexMutation[];
|
|
11
|
+
private static readonly ALWAYS_FORWARD_METHODS;
|
|
10
12
|
getMutations(): ApexMutation[];
|
|
11
|
-
constructor(listeners: BaseListener[], coveredLines: Set<number>, typeTable?: Map<string, ApexMethod> | undefined);
|
|
13
|
+
constructor(listeners: BaseListener[], coveredLines: Set<number>, typeTable?: Map<string, ApexMethod> | undefined, sObjectDescribeRepository?: SObjectDescribeRepository);
|
|
12
14
|
}
|
|
@@ -5,10 +5,20 @@ export class MutationListener {
|
|
|
5
5
|
typeTable;
|
|
6
6
|
listeners;
|
|
7
7
|
_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
|
+
]);
|
|
8
18
|
getMutations() {
|
|
9
19
|
return this._mutations;
|
|
10
20
|
}
|
|
11
|
-
constructor(listeners, coveredLines, typeTable) {
|
|
21
|
+
constructor(listeners, coveredLines, typeTable, sObjectDescribeRepository) {
|
|
12
22
|
this.coveredLines = coveredLines;
|
|
13
23
|
this.typeTable = typeTable;
|
|
14
24
|
this.listeners = listeners;
|
|
@@ -19,6 +29,11 @@ export class MutationListener {
|
|
|
19
29
|
}
|
|
20
30
|
});
|
|
21
31
|
}
|
|
32
|
+
if (sObjectDescribeRepository) {
|
|
33
|
+
this.listeners.forEach(listener => {
|
|
34
|
+
listener.setSObjectDescribeRepository(sObjectDescribeRepository);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
22
37
|
// Share mutations array across all listeners
|
|
23
38
|
this.listeners
|
|
24
39
|
.filter(listener => '_mutations' in listener)
|
|
@@ -36,7 +51,9 @@ export class MutationListener {
|
|
|
36
51
|
return (...args) => {
|
|
37
52
|
if (Array.isArray(args) && args.length > 0) {
|
|
38
53
|
const ctx = args[0];
|
|
39
|
-
|
|
54
|
+
const shouldForward = MutationListener.ALWAYS_FORWARD_METHODS.has(prop) ||
|
|
55
|
+
this.coveredLines.has(ctx?.start?.line);
|
|
56
|
+
if (shouldForward) {
|
|
40
57
|
this.listeners.forEach(listener => {
|
|
41
58
|
if (prop in listener && typeof listener[prop] === 'function') {
|
|
42
59
|
;
|
|
@@ -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":"AAMA,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAA;AAE9E,2DAA2D;AAC3D,MAAM,OAAO,gBAAgB;IAqBN;IACA;IArBb,SAAS,CAAgB;IACjC,UAAU,GAAmB,EAAE,CAAA;IAE/B,mEAAmE;IACnE,sEAAsE;IAC9D,MAAM,CAAU,sBAAsB,GAAG,IAAI,GAAG,CAAC;QACvD,wBAAwB;QACxB,uBAAuB;QACvB,+BAA+B;QAC/B,sBAAsB;QACtB,uBAAuB;QACvB,yBAAyB;KAC1B,CAAC,CAAA;IAEK,YAAY;QACjB,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;IAED,YACE,SAAyB,EACN,YAAyB,EACzB,SAAmC,EACtD,yBAAqD;QAFlC,iBAAY,GAAZ,YAAY,CAAa;QACzB,cAAS,GAAT,SAAS,CAA0B;QAGtD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAE1B,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAChC,IAAI,QAAQ,YAAY,2BAA2B,EAAE,CAAC;oBACpD,QAAQ,CAAC,YAAY,CAAC,SAAS,CAAC,CAAA;gBAClC,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,yBAAyB,EAAE,CAAC;YAC9B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAChC,QAAQ,CAAC,4BAA4B,CAAC,yBAAyB,CAAC,CAAA;YAClE,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,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,MAAM,aAAa,GACjB,gBAAgB,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAc,CAAC;4BAC3D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;wBAEzC,IAAI,aAAa,EAAE,CAAC;4BAClB,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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { ParserRuleContext } from 'antlr4ts';
|
|
2
|
-
import {
|
|
3
|
-
export declare class NegationMutator extends
|
|
4
|
-
private readonly
|
|
2
|
+
import { ReturnTypeAwareBaseListener } from './returnTypeAwareBaseListener.js';
|
|
3
|
+
export declare class NegationMutator extends ReturnTypeAwareBaseListener {
|
|
4
|
+
private static readonly NUMERIC_TYPES;
|
|
5
|
+
private static readonly ZERO_LITERAL;
|
|
5
6
|
enterReturnStatement(ctx: ParserRuleContext): void;
|
|
6
|
-
private
|
|
7
|
+
private isNegatedExpression;
|
|
8
|
+
private formatNegation;
|
|
7
9
|
}
|
|
@@ -1,36 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { ParserRuleContext } from 'antlr4ts';
|
|
2
|
+
import { TerminalNode } from 'antlr4ts/tree/index.js';
|
|
3
|
+
import { ApexType } from '../type/ApexMethod.js';
|
|
4
|
+
import { ReturnTypeAwareBaseListener } from './returnTypeAwareBaseListener.js';
|
|
5
|
+
export class NegationMutator extends ReturnTypeAwareBaseListener {
|
|
6
|
+
static NUMERIC_TYPES = new Set([
|
|
7
|
+
ApexType.INTEGER,
|
|
8
|
+
ApexType.LONG,
|
|
9
|
+
ApexType.DOUBLE,
|
|
10
|
+
ApexType.DECIMAL,
|
|
11
|
+
]);
|
|
12
|
+
static ZERO_LITERAL = /^0+(\.0+)?[lLdD]?$/;
|
|
6
13
|
enterReturnStatement(ctx) {
|
|
7
|
-
|
|
8
|
-
const expression = ctx.expression?.();
|
|
9
|
-
if (!expression) {
|
|
14
|
+
if (!this.isCurrentMethodTypeKnown()) {
|
|
10
15
|
return;
|
|
11
16
|
}
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
if (expressionText.startsWith('-')) {
|
|
17
|
+
const typeInfo = this.getCurrentMethodReturnTypeInfo();
|
|
18
|
+
if (!typeInfo || !NegationMutator.NUMERIC_TYPES.has(typeInfo.type)) {
|
|
15
19
|
return;
|
|
16
20
|
}
|
|
17
|
-
|
|
18
|
-
if (this.shouldSkipExpression(expressionText)) {
|
|
21
|
+
if (!ctx.children || ctx.children.length < 2) {
|
|
19
22
|
return;
|
|
20
23
|
}
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
const expressionNode = ctx.children[1];
|
|
25
|
+
if (!(expressionNode instanceof ParserRuleContext)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (this.isNegatedExpression(expressionNode)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const expressionText = expressionNode.text;
|
|
32
|
+
if (NegationMutator.ZERO_LITERAL.test(expressionText)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const replacement = this.formatNegation(expressionText, expressionNode);
|
|
36
|
+
this.createMutationFromParserRuleContext(expressionNode, replacement);
|
|
23
37
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return true;
|
|
38
|
+
isNegatedExpression(expr) {
|
|
39
|
+
if (expr.childCount !== 2) {
|
|
40
|
+
return false;
|
|
28
41
|
}
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
return
|
|
42
|
+
const firstChild = expr.getChild(0);
|
|
43
|
+
if (!(firstChild instanceof TerminalNode)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
return firstChild.text === '-';
|
|
47
|
+
}
|
|
48
|
+
formatNegation(expressionText, expressionNode) {
|
|
49
|
+
const isComplexExpression = expressionNode.childCount > 1;
|
|
50
|
+
if (isComplexExpression) {
|
|
51
|
+
return `-(${expressionText})`;
|
|
32
52
|
}
|
|
33
|
-
return
|
|
53
|
+
return `-${expressionText}`;
|
|
34
54
|
}
|
|
35
55
|
}
|
|
36
56
|
//# sourceMappingURL=negationMutator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"negationMutator.js","sourceRoot":"","sources":["../../src/mutator/negationMutator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"negationMutator.js","sourceRoot":"","sources":["../../src/mutator/negationMutator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAA;AAE9E,MAAM,OAAO,eAAgB,SAAQ,2BAA2B;IACtD,MAAM,CAAU,aAAa,GAAG,IAAI,GAAG,CAAC;QAC9C,QAAQ,CAAC,OAAO;QAChB,QAAQ,CAAC,IAAI;QACb,QAAQ,CAAC,MAAM;QACf,QAAQ,CAAC,OAAO;KACjB,CAAC,CAAA;IAEM,MAAM,CAAU,YAAY,GAAG,oBAAoB,CAAA;IAE3D,oBAAoB,CAAC,GAAsB;QACzC,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAE,CAAC;YACrC,OAAM;QACR,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,8BAA8B,EAAE,CAAA;QACtD,IAAI,CAAC,QAAQ,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACnE,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,IAAI,CAAC,mBAAmB,CAAC,cAAc,CAAC,EAAE,CAAC;YAC7C,OAAM;QACR,CAAC;QAED,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,CAAA;QAC1C,IAAI,eAAe,CAAC,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YACtD,OAAM;QACR,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,cAAc,CAAC,CAAA;QAEvE,IAAI,CAAC,mCAAmC,CAAC,cAAc,EAAE,WAAW,CAAC,CAAA;IACvE,CAAC;IAEO,mBAAmB,CAAC,IAAuB;QACjD,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAA;QACd,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QACnC,IAAI,CAAC,CAAC,UAAU,YAAY,YAAY,CAAC,EAAE,CAAC;YAC1C,OAAO,KAAK,CAAA;QACd,CAAC;QAED,OAAO,UAAU,CAAC,IAAI,KAAK,GAAG,CAAA;IAChC,CAAC;IAEO,cAAc,CACpB,cAAsB,EACtB,cAAiC;QAEjC,MAAM,mBAAmB,GAAG,cAAc,CAAC,UAAU,GAAG,CAAC,CAAA;QAEzD,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAO,KAAK,cAAc,GAAG,CAAA;QAC/B,CAAC;QAED,OAAO,IAAI,cAAc,EAAE,CAAA;IAC7B,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { CommonTokenStream } from 'apex-parser';
|
|
2
|
+
import { SObjectDescribeRepository } from '../adapter/sObjectDescribeRepository.js';
|
|
3
|
+
import { ApexMethod } from '../type/ApexMethod.js';
|
|
2
4
|
import { ApexMutation } from '../type/ApexMutation.js';
|
|
3
|
-
import { ApexTypeResolver } from './apexTypeResolver.js';
|
|
4
5
|
export declare class MutantGenerator {
|
|
5
6
|
private tokenStream?;
|
|
6
7
|
getTokenStream(): CommonTokenStream | undefined;
|
|
7
|
-
compute(classContent: string, coveredLines: Set<number>,
|
|
8
|
+
compute(classContent: string, coveredLines: Set<number>, methodTypeTable?: Map<string, ApexMethod>, sObjectDescribeRepository?: SObjectDescribeRepository): ApexMutation[];
|
|
8
9
|
mutate(mutation: ApexMutation): string;
|
|
9
10
|
}
|
|
@@ -23,12 +23,11 @@ export class MutantGenerator {
|
|
|
23
23
|
getTokenStream() {
|
|
24
24
|
return this.tokenStream;
|
|
25
25
|
}
|
|
26
|
-
compute(classContent, coveredLines,
|
|
26
|
+
compute(classContent, coveredLines, methodTypeTable, sObjectDescribeRepository) {
|
|
27
27
|
const lexer = new ApexLexer(new CaseInsensitiveInputStream('other', classContent));
|
|
28
28
|
this.tokenStream = new CommonTokenStream(lexer);
|
|
29
29
|
const parser = new ApexParser(this.tokenStream);
|
|
30
30
|
const tree = parser.compilationUnit();
|
|
31
|
-
const methodTypeTable = typeResolver?.analyzeMethodTypes(tree);
|
|
32
31
|
const incrementListener = new IncrementMutator();
|
|
33
32
|
const boundaryListener = new BoundaryConditionMutator();
|
|
34
33
|
const emptyReturnListener = new EmptyReturnMutator();
|
|
@@ -64,7 +63,7 @@ export class MutantGenerator {
|
|
|
64
63
|
removeConditionalsListener,
|
|
65
64
|
switchListener,
|
|
66
65
|
experimentalSwitchListener,
|
|
67
|
-
], coveredLines, methodTypeTable);
|
|
66
|
+
], coveredLines, methodTypeTable, sObjectDescribeRepository);
|
|
68
67
|
ParseTreeWalker.DEFAULT.walk(listener, tree);
|
|
69
68
|
return listener.getMutations();
|
|
70
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutantGenerator.js","sourceRoot":"","sources":["../../src/service/mutantGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,EACL,SAAS,EACT,UAAU,EAEV,0BAA0B,EAC1B,iBAAiB,EACjB,eAAe,GAChB,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"mutantGenerator.js","sourceRoot":"","sources":["../../src/service/mutantGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,EACL,SAAS,EACT,UAAU,EAEV,0BAA0B,EAC1B,iBAAiB,EACjB,eAAe,GAChB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAA;AACnF,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAA;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAA;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAA;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAA;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAA;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAA;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAA;AACnF,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAA;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAA;AAI3E,MAAM,OAAO,eAAe;IAClB,WAAW,CAAoB;IAEhC,cAAc;QACnB,OAAO,IAAI,CAAC,WAAW,CAAA;IACzB,CAAC;IAEM,OAAO,CACZ,YAAoB,EACpB,YAAyB,EACzB,eAAyC,EACzC,yBAAqD;QAErD,MAAM,KAAK,GAAG,IAAI,SAAS,CACzB,IAAI,0BAA0B,CAAC,OAAO,EAAE,YAAY,CAAC,CACtD,CAAA;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAA;QAC/C,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,eAAe,EAAE,CAAA;QAErC,MAAM,iBAAiB,GAAG,IAAI,gBAAgB,EAAE,CAAA;QAChD,MAAM,gBAAgB,GAAG,IAAI,wBAAwB,EAAE,CAAA;QACvD,MAAM,mBAAmB,GAAG,IAAI,kBAAkB,EAAE,CAAA;QACpD,MAAM,kBAAkB,GAAG,IAAI,iBAAiB,EAAE,CAAA;QAClD,MAAM,mBAAmB,GAAG,IAAI,kBAAkB,EAAE,CAAA;QACpD,MAAM,kBAAkB,GAAG,IAAI,iBAAiB,EAAE,CAAA;QAClD,MAAM,gBAAgB,GAAG,IAAI,wBAAwB,EAAE,CAAA;QACvD,MAAM,kBAAkB,GAAG,IAAI,yBAAyB,EAAE,CAAA;QAC1D,MAAM,uBAAuB,GAAG,IAAI,sBAAsB,EAAE,CAAA;QAC5D,MAAM,uBAAuB,GAAG,IAAI,sBAAsB,EAAE,CAAA;QAC5D,MAAM,gBAAgB,GAAG,IAAI,eAAe,EAAE,CAAA;QAC9C,MAAM,wBAAwB,GAAG,IAAI,uBAAuB,EAAE,CAAA;QAC9D,MAAM,sBAAsB,GAAG,IAAI,qBAAqB,EAAE,CAAA;QAC1D,MAAM,uBAAuB,GAAG,IAAI,sBAAsB,EAAE,CAAA;QAC5D,MAAM,0BAA0B,GAAG,IAAI,yBAAyB,EAAE,CAAA;QAClE,MAAM,cAAc,GAAG,IAAI,aAAa,EAAE,CAAA;QAC1C,MAAM,0BAA0B,GAAG,IAAI,yBAAyB,EAAE,CAAA;QAElE,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CACnC;YACE,gBAAgB;YAChB,iBAAiB;YACjB,gBAAgB;YAChB,mBAAmB;YACnB,kBAAkB;YAClB,mBAAmB;YACnB,kBAAkB;YAClB,kBAAkB;YAClB,uBAAuB;YACvB,uBAAuB;YACvB,gBAAgB;YAChB,wBAAwB;YACxB,sBAAsB;YACtB,uBAAuB;YACvB,0BAA0B;YAC1B,cAAc;YACd,0BAA0B;SAC3B,EACD,YAAY,EACZ,eAAe,EACf,yBAAyB,CAC1B,CAAA;QAED,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,QAA8B,EAAE,IAAI,CAAC,CAAA;QAElE,OAAO,QAAQ,CAAC,YAAY,EAAE,CAAA;IAChC,CAAC;IAEM,MAAM,CAAC,QAAsB;QAClC,qCAAqC;QACrC,MAAM,QAAQ,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,WAAY,CAAC,CAAA;QAE3D,QAAQ,CAAC,OAAO,CACd,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EACrC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,EACnC,QAAQ,CAAC,WAAW,CACrB,CAAA;QAED,uBAAuB;QACvB,OAAO,QAAQ,CAAC,OAAO,EAAE,CAAA;IAC3B,CAAC;CACF"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { ApexClassRepository } from '../adapter/apexClassRepository.js';
|
|
2
2
|
import { ApexTestRunner } from '../adapter/apexTestRunner.js';
|
|
3
|
-
import {
|
|
3
|
+
import { SObjectDescribeRepository } from '../adapter/sObjectDescribeRepository.js';
|
|
4
4
|
import { MutantGenerator } from './mutantGenerator.js';
|
|
5
|
+
import { TypeGatherer } from './typeGatherer.js';
|
|
6
|
+
import { ApexClassTypeMatcher, SObjectTypeMatcher } from './typeMatcher.js';
|
|
5
7
|
const errorStrategies = [
|
|
6
8
|
{
|
|
7
9
|
matches: msg => msg.startsWith('Deployment failed:'),
|
|
@@ -65,7 +67,14 @@ export class MutationTestingService {
|
|
|
65
67
|
const customObjectTypes = dependencies
|
|
66
68
|
.filter(dep => dep.RefMetadataComponentType === 'CustomObject')
|
|
67
69
|
.map(dep => dep.RefMetadataComponentName);
|
|
68
|
-
const
|
|
70
|
+
const apexClassMatcher = new ApexClassTypeMatcher(new Set(apexClassTypes));
|
|
71
|
+
const sObjectMatcher = new SObjectTypeMatcher(new Set([...standardEntityTypes, ...customObjectTypes]));
|
|
72
|
+
const typeGatherer = new TypeGatherer(apexClassMatcher, sObjectMatcher);
|
|
73
|
+
const { methodTypeTable, usedSObjectTypes } = typeGatherer.analyze(apexClass.Body);
|
|
74
|
+
this.spinner.stop('Done');
|
|
75
|
+
this.spinner.start(`Describing sObject field types for "${this.apexClassName}"`, undefined, { stdout: true });
|
|
76
|
+
const sObjectDescribeRepository = new SObjectDescribeRepository(this.connection);
|
|
77
|
+
await sObjectDescribeRepository.describe([...usedSObjectTypes]);
|
|
69
78
|
this.spinner.stop('Done');
|
|
70
79
|
this.spinner.start(`Testing original code"`, undefined, {
|
|
71
80
|
stdout: true,
|
|
@@ -96,7 +105,7 @@ export class MutationTestingService {
|
|
|
96
105
|
stdout: true,
|
|
97
106
|
});
|
|
98
107
|
const mutantGenerator = new MutantGenerator();
|
|
99
|
-
const mutations = mutantGenerator.compute(apexClass.Body, coveredLines,
|
|
108
|
+
const mutations = mutantGenerator.compute(apexClass.Body, coveredLines, methodTypeTable, sObjectDescribeRepository);
|
|
100
109
|
if (mutations.length === 0) {
|
|
101
110
|
this.spinner.stop('0 mutations generated');
|
|
102
111
|
throw new Error(this.messages.getMessage('error.noMutations', [
|