Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 71e1c26

Browse files
feat: default arg branches (#207)
Adds the default arg as branches to the CFG and instrumentation
1 parent 0632913 commit 71e1c26

File tree

5 files changed

+92
-13
lines changed

5 files changed

+92
-13
lines changed

‎libraries/analysis-javascript/lib/cfg/ControlFlowGraphVisitor.ts

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,9 @@ export class ControlFlowGraphVisitor extends AbstractSyntaxTreeVisitor {
332332
this._edges.push(
333333
this._createEdge(this._nodes.get(parent), node, this._edgeType)
334334
);
335-
this._edgeType = EdgeType.NORMAL;
336335
}
336+
337+
this._edgeType = EdgeType.NORMAL;
337338
}
338339

339340
public Block: (path: NodePath<t.Block>) => void = (path) => {
@@ -432,6 +433,59 @@ export class ControlFlowGraphVisitor extends AbstractSyntaxTreeVisitor {
432433
}
433434
};
434435

436+
public AssignmentPattern: (path: NodePath<t.AssignmentPattern>) => void = (
437+
path
438+
) => {
439+
ControlFlowGraphVisitor.LOGGER.debug(
440+
`Entering AssignmentPattern at ${this._getNodeId(path)}`
441+
);
442+
443+
const branchNode = this._createNode(path);
444+
this._connectToParents(branchNode);
445+
this._currentParents = [branchNode.id];
446+
447+
const testNode = this._createNode(path.get("left")); // bit odd because the test is essentially if the argument is given or not
448+
this._connectToParents(testNode);
449+
this._currentParents = [testNode.id];
450+
451+
// consequent
452+
this._edgeType = EdgeType.CONDITIONAL_TRUE;
453+
// there is no consequent since that is the usual case when an argument is give
454+
const consequent = this._createPlaceholderNode(path);
455+
this._connectToParents(consequent);
456+
this._currentParents = [consequent.id];
457+
458+
const consequentNodes = this._currentParents;
459+
460+
// alternate (the default argument)
461+
this._currentParents = [testNode.id];
462+
this._edgeType = EdgeType.CONDITIONAL_FALSE;
463+
464+
const sizeBefore = this._nodesList.length;
465+
path.get("right").visit();
466+
467+
// there either is no alternate or it is a literal
468+
if (sizeBefore === this._nodesList.length) {
469+
if (path.has("right")) {
470+
// this probably means the "right"/default value is a literal (or something else this visitor does not pick up on)
471+
const alternate = this._createNode(path.get("right"));
472+
this._connectToParents(alternate);
473+
this._currentParents = [alternate.id];
474+
} else {
475+
// there is no default value specified?? (should not be possible)
476+
throw new ImplementationError(
477+
"AssignmentPattern does not have a default value"
478+
);
479+
}
480+
}
481+
482+
const alternateNodes = this._currentParents;
483+
484+
this._currentParents = [...alternateNodes, ...consequentNodes];
485+
486+
path.skip();
487+
};
488+
435489
public Conditional: (path: NodePath<t.Conditional>) => void = (path) => {
436490
ControlFlowGraphVisitor.LOGGER.debug(
437491
`Entering IfStatement at ${this._getNodeId(path)}`
@@ -988,8 +1042,8 @@ export class ControlFlowGraphVisitor extends AbstractSyntaxTreeVisitor {
9881042

9891043
// alternate
9901044
// placeholder
991-
this._edgeType = EdgeType.CONDITIONAL_FALSE;
9921045
this._currentParents = [caseTestNode.id];
1046+
this._edgeType = EdgeType.CONDITIONAL_FALSE;
9931047
const alternateNode = this._createPlaceholderNode(caseNode);
9941048
this._connectToParents(alternateNode);
9951049
this._currentParents = [alternateNode.id]; // normal

‎libraries/instrumentation-javascript/lib/datastructures/InstrumentationData.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ export type InstrumentationData = {
6363
[id: string]: number;
6464
};
6565
b: {
66-
// 0 is true, 1 is false
67-
[id: string]: [number,number];
66+
// 0 is true, 1 is false (or more if switch for example)
67+
[id: string]: number[];
6868
};
6969
};
7070

‎libraries/instrumentation-javascript/lib/instrumentation/VisitState.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import { createHash } from "crypto";
2020

2121
import { SourceCoverage } from "./source-coverage";
22+
import { NodePath } from "@babel/traverse";
2223

2324
const SHA = "sha1";
2425

@@ -243,7 +244,7 @@ export class VisitState {
243244
]);
244245
}
245246

246-
insertCounter(path, increment) {
247+
insertCounter(path: NodePath, increment) {
247248
const T = this.types;
248249
if (path.isBlockStatement()) {
249250
path.node.body.unshift(T.expressionStatement(increment));
@@ -270,14 +271,11 @@ export class VisitState {
270271
} /* istanbul ignore else: not expected */ else if (path.isExpression()) {
271272
path.replaceWith(T.sequenceExpression([increment, path.node]));
272273
} else {
273-
console.error(
274-
"Unable to insert counter for node identifierDescription:",
275-
path.node.type
276-
);
274+
console.error("Unable to insert counter for node:", path.node.type);
277275
}
278276
}
279277

280-
insertStatementCounter(path) {
278+
insertStatementCounter(path: NodePath) {
281279
/* istanbul ignore if: paranoid check */
282280
if (!(path.node && path.node.loc)) {
283281
if (

‎libraries/instrumentation-javascript/lib/instrumentation/Visitor.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,40 @@ function entries(...enter) {
177177
};
178178
}
179179

180-
function coverStatement(path) {
180+
function coverStatement(path: NodePath<t.Statement>) {
181181
this.insertStatementCounter(path);
182182
}
183183

184+
function coverExpression(path: NodePath<t.Expression>) {
185+
if (path.isBinaryExpression()) {
186+
this.insertStatementCounter(path.get("left"));
187+
this.insertStatementCounter(path.get("right"));
188+
}
189+
}
190+
184191
/* istanbul ignore next: no node.js support */
185-
function coverAssignmentPattern(path) {
192+
function coverAssignmentPattern(path: NodePath<t.AssignmentPattern>) {
193+
const index = this.cov.newStatement(path.node.loc);
194+
const statementIncrement = this.increase("s", index, null);
195+
186196
const n = path.node;
187197
const b = this.cov.newBranch("default-arg", n.loc);
198+
199+
const increment = this.getBranchIncrement(path, b, undefined);
200+
201+
const parent = path.getFunctionParent();
202+
203+
const body = parent.get("body");
204+
205+
if (body.isBlockStatement()) {
206+
body.node.body.unshift(
207+
t.expressionStatement(statementIncrement),
208+
t.expressionStatement(increment)
209+
);
210+
} else {
211+
console.error("Unable to process function body node:", path.node.type);
212+
}
213+
188214
this.insertBranchCounter(path, path.get("right"), b);
189215
}
190216

@@ -667,6 +693,7 @@ const codeVisitor = {
667693
BlockStatement: entries(), // ignore processing only
668694
ExportDefaultDeclaration: entries(), // ignore processing only
669695
ExportNamedDeclaration: entries(), // ignore processing only
696+
Expression: entries(coverExpression),
670697
ClassMethod: entries(coverFunction),
671698
ClassDeclaration: entries(parenthesizedExpressionProp("superClass")),
672699
ClassProperty: entries(coverClassPropDeclarator),

‎libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ export class JavaScriptRunner implements EncodingRunner<JavaScriptTestCase> {
267267
const traces: Trace[] = [];
268268
for (const branchKey of Object.keys(instrumentationData.branchMap)) {
269269
const branch = instrumentationData.branchMap[branchKey];
270-
const hits = <number[]>instrumentationData.b[branchKey];
270+
const hits = instrumentationData.b[branchKey];
271271
let meta;
272272

273273
if (metaData !== undefined) {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /