Skip to content

Commit

Permalink
Merge ed2022e into 45936de
Browse files Browse the repository at this point in the history
  • Loading branch information
katerberg committed Dec 29, 2017
2 parents 45936de + ed2022e commit 49847f5
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 31 deletions.
8 changes: 5 additions & 3 deletions packages/istanbul-api/lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ function defaultConfig() {
'include-all-sources': false,
'include-pid': false,
'es-modules': false,
'auto-wrap': false
'auto-wrap': false,
'ignore-class-methods': []
},
reporting: {
print: 'summary',
Expand Down Expand Up @@ -191,7 +192,7 @@ addMethods(InstrumentOptions,
'extensions', 'defaultExcludes', 'completeCopy',
'variable', 'compact', 'preserveComments',
'saveBaseline', 'baselineFile', 'esModules',
'includeAllSources', 'includePid', 'autoWrap');
'includeAllSources', 'includePid', 'autoWrap', 'ignoreClassMethods');

/**
* returns the root directory used by istanbul which is typically the root of the
Expand Down Expand Up @@ -225,7 +226,8 @@ InstrumentOptions.prototype.getInstrumenterOpts = function () {
compact: this.compact(),
preserveComments: this.preserveComments(),
esModules: this.esModules(),
autoWrap: this.autoWrap()
autoWrap: this.autoWrap(),
ignoreClassMethods: this.ignoreClassMethods()
};
};

Expand Down
52 changes: 27 additions & 25 deletions packages/istanbul-lib-instrument/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ supplied options.

**Parameters**

- `opts` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** instrumenter options. See the documentation
- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** instrumenter options. See the documentation
for the Instrumenter class.

## Instrumenter
Expand All @@ -29,16 +29,17 @@ instead.

**Parameters**

- `opts` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** optional. (optional, default `defaultOpts()`)
- `opts.coverageVariable` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** name of global coverage variable. (optional, default `__coverage__`)
- `opts.preserveComments` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** preserve comments in output (optional, default `false`)
- `opts.compact` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** generate compact code. (optional, default `true`)
- `opts.esModules` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** set to true to instrument ES6 modules. (optional, default `false`)
- `opts.autoWrap` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** set to true to allow `return` statements outside of functions. (optional, default `false`)
- `opts.produceSourceMap` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** set to true to produce a source map for the instrumented code. (optional, default `false`)
- `opts.sourceMapUrlCallback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** a callback function that is called when a source map URL
- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** optional. (optional, default `defaultOpts()`)
- `opts.coverageVariable` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** name of global coverage variable. (optional, default `__coverage__`)
- `opts.preserveComments` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** preserve comments in output (optional, default `false`)
- `opts.compact` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** generate compact code. (optional, default `true`)
- `opts.esModules` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** set to true to instrument ES6 modules. (optional, default `false`)
- `opts.autoWrap` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** set to true to allow `return` statements outside of functions. (optional, default `false`)
- `opts.produceSourceMap` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** set to true to produce a source map for the instrumented code. (optional, default `false`)
- `opts.ignoreClassMethods` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)** set to array of class method names to ignore for coverage. (optional, default `[]`)
- `opts.sourceMapUrlCallback` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** a callback function that is called when a source map URL
is found in the original code. This function is called with the source file name and the source map URL. (optional, default `null`)
- `opts.debug` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** turn debugging on (optional, default `false`)
- `opts.debug` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** turn debugging on (optional, default `false`)

### instrumentSync

Expand All @@ -49,13 +50,13 @@ is supported. To instrument ES6 modules, make sure that you set the

**Parameters**

- `code` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the code to instrument
- `filename` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the filename against which to track coverage.
- `inputSourceMap` **[object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)?** the source map that maps the not instrumented code back to it's original form.
- `code` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the code to instrument
- `filename` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the filename against which to track coverage.
- `inputSourceMap` **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** the source map that maps the not instrumented code back to it's original form.
Is assigned to the coverage object and therefore, is available in the json output and can be used to remap the
coverage to the untranspiled source.

Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the instrumented code.
Returns **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the instrumented code.

### instrument

Expand All @@ -65,24 +66,24 @@ the callback will be called in the same process tick and is not asynchronous.

**Parameters**

- `code` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the code to instrument
- `filename` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the filename against which to track coverage.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** the callback
- `inputSourceMap` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** the source map that maps the not instrumented code back to it's original form.
- `code` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the code to instrument
- `filename` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the filename against which to track coverage.
- `callback` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** the callback
- `inputSourceMap` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the source map that maps the not instrumented code back to it's original form.
Is assigned to the coverage object and therefore, is available in the json output and can be used to remap the
coverage to the untranspiled source.

### lastFileCoverage

returns the file coverage object for the last file instrumented.

Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** the file coverage object.
Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the file coverage object.

### lastSourceMap

returns the source map produced for the last file instrumented.

Returns **(null | [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object))** the source map object.
Returns **(null | [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object))** the source map object.

## programVisitor

Expand All @@ -100,9 +101,10 @@ The exit function returns an object that currently has the following keys:

**Parameters**

- `types` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** an instance of babel-types
- `sourceFilePath` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the path to source file (optional, default `'unknown.js'`)
- `opts` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** additional options (optional, default `{coverageVariable:'__coverage__',inputSourceMap:undefined}`)
- `opts.coverageVariable` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** the global coverage variable name. (optional, default `__coverage__`)
- `opts.inputSourceMap` **[object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** the input source map, that maps the uninstrumented code back to the
- `types` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** an instance of babel-types
- `sourceFilePath` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the path to source file (optional, default `'unknown.js'`)
- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** additional options (optional, default `defaultProgramVisitorOpts`)
- `opts.coverageVariable` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the global coverage variable name. (optional, default `__coverage__`)
- `opts.ignoreClassMethods` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)** names of methods to ignore by default on classes. (optional, default `[]`)
- `opts.inputSourceMap` **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the input source map, that maps the uninstrumented code back to the
original code. (optional, default `undefined`)
3 changes: 3 additions & 0 deletions packages/istanbul-lib-instrument/src/instrumenter.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function defaultOpts() {
esModules: false,
autoWrap: false,
produceSourceMap: false,
ignoreClassMethods: [],
sourceMapUrlCallback: null,
debug: false
};
Expand All @@ -32,6 +33,7 @@ function defaultOpts() {
* @param {boolean} [opts.esModules=false] set to true to instrument ES6 modules.
* @param {boolean} [opts.autoWrap=false] set to true to allow `return` statements outside of functions.
* @param {boolean} [opts.produceSourceMap=false] set to true to produce a source map for the instrumented code.
* @param {Array} [opts.ignoreClassMethods=[]] set to array of class method names to ignore for coverage.
* @param {Function} [opts.sourceMapUrlCallback=null] a callback function that is called when a source map URL
* is found in the original code. This function is called with the source file name and the source map URL.
* @param {boolean} [opts.debug=false] - turn debugging on
Expand Down Expand Up @@ -91,6 +93,7 @@ class Instrumenter {
});
const ee = programVisitor(t, filename, {
coverageVariable: opts.coverageVariable,
ignoreClassMethods: opts.ignoreClassMethods,
inputSourceMap: inputSourceMap
});
let output = {};
Expand Down
25 changes: 22 additions & 3 deletions packages/istanbul-lib-instrument/src/visitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function genVar(filename) {
// VisitState holds the state of the visitor, provides helper functions
// and is the `this` for the individual coverage visitors.
class VisitState {
constructor(types, sourceFilePath, inputSourceMap) {
constructor(types, sourceFilePath, inputSourceMap, ignoreClassMethods) {
this.varName = genVar(sourceFilePath);
this.attrs = {};
this.nextIgnore = null;
Expand All @@ -29,6 +29,7 @@ class VisitState {
if (typeof (inputSourceMap) !== "undefined") {
this.cov.inputSourceMap(inputSourceMap);
}
this.ignoreClassMethods = ignoreClassMethods;
this.types = types;
this.sourceMappingURL = null;
}
Expand Down Expand Up @@ -72,6 +73,7 @@ class VisitState {
extractURL(node.leadingComments);
extractURL(node.trailingComments);
}


// for these expressions the statement counter needs to be hoisted, so
// function name inference can be preserved
Expand Down Expand Up @@ -99,6 +101,16 @@ class VisitState {
if (this.getAttr(path.node, 'skip-all') !== null) {
this.nextIgnore = n;
}

// else check for ignored class methods
if (path.isFunctionExpression() && this.ignoreClassMethods.some(name => path.node.id && name === path.node.id.name)) {
this.nextIgnore = n;
return;
}
if (path.isClassMethod() && this.ignoreClassMethods.some(name => name === path.node.key.name)) {
this.nextIgnore = n;
return;
}
}

// all the generic stuff on exit of a node,
Expand Down Expand Up @@ -488,6 +500,12 @@ function alreadyInstrumented(path, visitState) {
function shouldIgnoreFile(programNode) {
return programNode.parent && programNode.parent.comments.some(c => COMMENT_FILE_RE.test(c.value));
}

const defaultProgramVisitorOpts = {
coverageVariable: '__coverage__',
ignoreClassMethods: [],
inputSourceMap: undefined
};
/**
* programVisitor is a `babel` adaptor for instrumentation.
* It returns an object with two methods `enter` and `exit`.
Expand All @@ -505,12 +523,13 @@ function shouldIgnoreFile(programNode) {
* @param {string} sourceFilePath - the path to source file
* @param {Object} opts - additional options
* @param {string} [opts.coverageVariable=__coverage__] the global coverage variable name.
* @param {Array} [opts.ignoreClassMethods=[]] names of methods to ignore by default on classes.
* @param {object} [opts.inputSourceMap=undefined] the input source map, that maps the uninstrumented code back to the
* original code.
*/
function programVisitor(types, sourceFilePath = 'unknown.js', opts = {coverageVariable: '__coverage__', inputSourceMap: undefined }) {
function programVisitor(types, sourceFilePath = 'unknown.js', opts = defaultProgramVisitorOpts) {
const T = types;
const visitState = new VisitState(types, sourceFilePath, opts.inputSourceMap);
const visitState = new VisitState(types, sourceFilePath, opts.inputSourceMap, opts.ignoreClassMethods);
return {
enter(path) {
if (shouldIgnoreFile(path.find(p => p.isProgram()))) {
Expand Down
43 changes: 43 additions & 0 deletions packages/istanbul-lib-instrument/test/specs/statement-hints.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,46 @@ tests:
lines: {'1': 1, '2': 1, '4': 0}
branches: {'0': [1, 0] }
statements: {'0': 1, '1': 1, '2': 0}
---
name: ignore class methods
guard: isClassAvailable
code: |
class TestClass {
dummy(i) {return i;}
nonIgnored(i) {return i;}
}
var testClass = new TestClass();
testClass.nonIgnored();
output = testClass.dummy(args[0]);
instrumentOpts:
ignoreClassMethods: ['dummy']
tests:
- name: ignores only specified es6 methods
args: [10]
out: 10
lines: {'3': 1, '5': 1, '6': 1, '7': 1}
functions: {'0': 1}
branches: {}
statements: {'0': 1, '1': 1, '2': 1, '3': 1}
---
name: ignore class methods
code: |
function TestClass() {}
TestClass.prototype.testMethod = function testMethod(i) {
return i;
};
TestClass.prototype.goodMethod = function goodMethod(i) {return i;};
var testClass = new TestClass();
testClass.goodMethod();
output = testClass.testMethod(args[0]);
instrumentOpts:
ignoreClassMethods: ['testMethod']
tests:
- name: ignores only specified es5 methods
args: [10]
out: 10
lines: {'2': 1, '5': 1, '6': 1, '7': 1, '8': 1}
functions: {'0': 1, '1': 1}
branches: {}
statements: {'0': 1, '1': 1, '2': 1, '3': 1, '4': 1, '5': 1}

0 comments on commit 49847f5

Please sign in to comment.