Commit 67d840bc by lxyang

feat: 上传bat版本

parents
lib/
node_modules/
*tgz
.history
dist
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
!fixtures/node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
package-lock=false
Copyright (c) 2016, Istanbul Code Coverage
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of babel-plugin-istanbul nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# babel-plugin-istanbul
[![Coverage Status](https://coveralls.io/repos/github/istanbuljs/babel-plugin-istanbul/badge.svg?branch=master)](https://coveralls.io/github/istanbuljs/babel-plugin-istanbul?branch=master)
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)
[![community slack](http://devtoolscommunity.herokuapp.com/badge.svg)](http://devtoolscommunity.herokuapp.com)
_Having problems? want to contribute? join our [community slack](http://devtoolscommunity.herokuapp.com)_.
A Babel plugin that instruments your code with Istanbul coverage.
It can instantly be used with [karma-coverage](https://github.com/karma-runner/karma-coverage) and mocha on Node.js (through [nyc](https://github.com/bcoe/nyc)).
__Note:__ This plugin does not generate any report or save any data to any file;
it only adds instrumenting code to your JavaScript source code.
To integrate with testing tools, please see the [Integrations](#integrations) section.
## 新增目录istanlibment
此目录为插桩方法,日后优化时使用,现使用原版本文件
新增方法:增量插桩两种方式
Serve packjson启动增加配置到时候不需要可以更改IS_PITCHING_PILE为false即可
"serve": "cross-env IS_PITCHING_PILE=true;cross-env INCREMENT=true;cross-env BRANCH=origin/master; vue-cli-service serve --mode dev"
IS_PITCHING_PILE是否插桩
INCREMENT是否过滤增量文件
BRANCH需要对比的分支isPitchingPile为true时默认origin/master当ISPITCHINGPILE为false的时候可以不穿
第二种(第一种后期优化加上现在使用第二种如参方式)
[
babel-plugin-ry-istanbul,
{
extension: ['.js', '.vue'],
instrmenttation: { IS_PITCHING_PILE: true, INCREMENT: true, BRANCH: 'origin/master' }
}
]
]
## Usage
Install it:
```
npm install --save-dev babel-plugin-istanbul
```
Add it to `.babelrc` in test mode:
```js
{
"env": {
"test": {
"plugins": [ "istanbul" ]
}
}
}
```
Optionally, use [cross-env](https://www.npmjs.com/package/cross-env) to set
`NODE_ENV=test`:
```json
{
"scripts": {
"test": "cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text mocha test/*.js"
}
}
```
## Integrations
### karma
It _just works_ with Karma. First, make sure that the code is already transpiled by Babel (either using `karma-babel-preprocessor`, `karma-webpack`, or `karma-browserify`). Then, simply set up [karma-coverage](https://github.com/karma-runner/karma-coverage) according to the docs, but __don’t add the `coverage` preprocessor.__ This plugin has already instrumented your code, and Karma should pick it up automatically.
It has been tested with [bemusic/bemuse](https://codecov.io/github/bemusic/bemuse) project, which contains ~2400 statements.
### mocha on node.js (through nyc)
Configure Mocha to transpile JavaScript code using Babel, then you can run your tests with [`nyc`](https://github.com/bcoe/nyc), which will collect all the coverage report.
babel-plugin-istanbul respects the `include`/`exclude` configuration options from nyc,
but you also need to __configure NYC not to instrument your code__ by adding these settings in your `package.json`:
```js
"nyc": {
"sourceMap": false,
"instrument": false
},
```
## Ignoring files
You don't want to cover your test files as this will skew your coverage results. You can configure this by providing plugin options matching nyc's [`exclude`/`include` rules](https://github.com/bcoe/nyc#excluding-files):
```json
{
"env": {
"test": {
"plugins": [
["istanbul", {
"exclude": [
"**/*.spec.js"
]
}]
]
}
}
}
```
If you don't provide options in your Babel config, the plugin will look for `exclude`/`include` config under an `"nyc"` key in `package.json`.
You can also use [istanbul's ignore hints](https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes) to specify specific lines of code to skip instrumenting.
## Source Maps
By default, this plugin will pick up inline source maps and attach them to the instrumented code such that code coverage can be remapped back to the original source, even for multi-step build processes. This can be memory intensive. Set `useInlineSourceMaps` to prevent this behavior.
```json
{
"env": {
"test": {
"plugins": [
["istanbul", {
"useInlineSourceMaps": false
}]
]
}
}
}
```
If you're instrumenting code programatically, you can pass a source map explicitly.
```js
import babelPluginIstanbul from 'babel-plugin-istanbul';
function instrument(sourceCode, sourceMap, fileName) {
return babel.transform(sourceCode, {
filename,
plugins: [
[babelPluginIstanbul, {
inputSourceMap: sourceMap
}]
]
})
}
```
## Credit where credit is due
The approach used in `babel-plugin-istanbul` was inspired by [Thai Pangsakulyanont](https://github.com/dtinth)'s original library [`babel-plugin-__coverage__`](https://github.com/dtinth/babel-plugin-__coverage__).
## `babel-plugin-istanbul` for enterprise
Available as part of the Tidelift Subscription.
The maintainers of `babel-plugin-istanbul` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-babel-plugin-istanbul?utm_source=npm-babel-plugin-istanbul&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
'use strict'
module.exports = {
plugins: ['@babel/plugin-transform-modules-commonjs'],
env: {
test: {
plugins: ['./lib']
}
}
}
class Foo1 {
bar() {}
barz() {}
}
class Foo2 {
bar() {}
barz() {}
}
module.exports = { Foo1, Foo2 }
console.log('file1')
console.log('file2')
'use strict'
module.exports = {
include: ['file2.js']
}
'use strict'
module.exports = {
include: ['file1.js']
}
"use strict";
var Say = (function () {
function Say() {
}
Say.prototype.hello = function () {
console.log('hello');
};
return Say;
}());
exports.__esModule = true;
exports["default"] = Say;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2hlY2tib3gudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIkNoZWNrYm94LnRlc3QudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtJQUFBO0lBSUEsQ0FBQztJQUhDLG1CQUFLLEdBQUw7UUFDRSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZCLENBQUM7SUFDSCxVQUFDO0FBQUQsQ0FBQyxBQUpELElBSUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBjbGFzcyBTYXkge1xyXG4gIGhlbGxvKCkge1xyXG4gICAgY29uc29sZS5sb2coJ2hlbGxvJyk7XHJcbiAgfVxyXG59Il19"
\ No newline at end of file
import { resolve } from 'path'
function test () {
const _path = 'path'
return resolve(_path)
}
test()
export const updateName = (name) => {
return {
type: 'UPDATE_NAME',
name
}
}
export const updateName2 = (name) => {
return {
type: 'UPDATE_NAME',
name
}
}
const foo = function () {
console.log('foo')
}
foo()
const bar = function () {
console.log('bar')
}
bar()
const foo = function () {
console.log('foo')
}
foo()
const bar = function () {
console.log('bar')
}
bar()
const foo = function () {
console.log('foo')
}
foo()
const bar = function () {
console.log('bar')
}
bar()
const foo = function () {
console.log('foo')
}
foo()
{
"name": "babel-plugin-ry-istanbul",
"version": "0.0.1-bat",
"author": "Thai Pangsakulyanont @dtinth",
"license": "BSD-3-Clause",
"description": "A babel plugin that adds istanbul instrumentation to ES6 code",
"main": "lib/index.js",
"files": [
"lib"
],
"dependencies": {
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/parser": "^7.14.7",
"@istanbuljs/load-nyc-config": "^1.0.0",
"@istanbuljs/schema": "^0.1.2",
"babel-generator": "^6.18.0",
"babel-template": "^6.26.0",
"babel-traverse": "^6.18.0",
"babel-types": "^6.18.0",
"babylon": "^6.13.0",
"cross-env": "^7.0.3",
"istanbul-lib-coverage": "^1.0.0",
"onchange": "^7.1.0",
"parse-diff": "^0.9.0",
"ry-istanbul-web": "^0.0.1",
"semver": "^6.3.0",
"test-exclude": "^6.0.0"
},
"devDependencies": {
"@babel/cli": "^7.7.5",
"@babel/core": "^7.7.5",
"@babel/plugin-proposal-optional-chaining": "^7.16.7",
"@babel/plugin-transform-modules-commonjs": "^7.7.5",
"@babel/register": "^7.7.4",
"chai": "^4.2.0",
"coveralls": "^3.0.9",
"cross-env": "^6.0.3",
"gaze": "^1.1.3",
"mocha": "^6.2.2",
"nyc": "^15.0.0",
"pmock": "^0.2.3",
"standard": "^14.3.1",
"pass-diff": "^0.9.0",
"babel-cli": "^6.3.17",
"babel-plugin-istanbul": "^2.0.3",
"babel-preset-es2015": "^6.3.13",
"babel-register": "^6.16.3",
"clone": "^2.0.0",
"documentation": "^4.0.0-beta9",
"js-yaml": "^3.3.1",
"jshint": "^2.8.0",
"nopt": "^3.0.6",
"standard-version": "^3.0.0"
},
"scripts": {
"coverage": "nyc report --reporter=text-lcov | coveralls",
"release": "babel src --out-dir lib",
"pretest": "standard && npm run release",
"test": "cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text mocha --timeout 5000 test/*.js",
"prepublish": "npm test && npm run release",
"build:watch": "onchange ./src -- npm run release"
},
"standard": {
"ignore": [
"fixtures/*.js"
]
},
"keywords": [
"istanbul",
"babel",
"plugin",
"instrumentation"
],
"nyc": {
"include": [
"src/*.js",
"fixtures/should-cover.js"
],
"require": [
"@babel/register"
],
"sourceMap": false,
"instrument": false
},
"engines": {
"node": ">=8"
}
}
const path = require('path')
import { realpathSync } from 'fs'
import { execFileSync, execSync } from 'child_process'
import { declare } from '@babel/helper-plugin-utils'
// import { programVisitor } from './istanlibment'
import { programVisitor } from 'istanbul-lib-instrument'
import TestExclude from 'test-exclude'
import schema from '@istanbuljs/schema'
import parseDiffData from 'parse-diff'
function getRealpath(n) {
try {
return realpathSync(n) || /* istanbul ignore next */ n
} catch (e) {
/* istanbul ignore next */
return n
}
}
const memoize = new Map()
/* istanbul ignore next */
const memosep = path.sep === '/' ? ':' : ';'
function loadNycConfig (cwd, opts) {
let memokey = cwd
const args = [
path.resolve(__dirname, 'load-nyc-config-sync.js'),
cwd
]
if ('nycrcPath' in opts) {
args.push(opts.nycrcPath)
memokey += memosep + opts.nycrcPath
}
/* execFileSync is expensive, avoid it if possible! */
if (memoize.has(memokey)) {
return memoize.get(memokey)
}
const result = JSON.parse(execFileSync(process.execPath, args))
const error = result['load-nyc-config-sync-error']
if (error) {
throw new Error(error)
}
const config = {
...schema.defaults.babelPluginIstanbul,
cwd,
...result
}
memoize.set(memokey, config)
return config
}
function findConfig (opts) {
const cwd = getRealpath(opts.cwd || process.env.NYC_CWD || /* istanbul ignore next */ process.cwd())
const keys = Object.keys(opts)
const ignored = Object.keys(opts).filter(s => s === 'nycrcPath' || s === 'cwd')
if (keys.length > ignored.length) {
// explicitly configuring options in babel
// takes precedence.
return {
...schema.defaults.babelPluginIstanbul,
cwd,
...opts
}
}
if (ignored.length === 0 && process.env.NYC_CONFIG) {
// defaults were already applied by nyc
return JSON.parse(process.env.NYC_CONFIG)
}
return loadNycConfig(cwd, opts)
}
function makeShouldSkip () {
let exclude
return function shouldSkip (file, nycConfig) {
if (!exclude || (exclude.cwd !== nycConfig.cwd)) {
exclude = new TestExclude({
cwd: nycConfig.cwd,
include: nycConfig.include,
exclude: nycConfig.exclude,
extension: nycConfig.extension,
// Make sure this is true unless explicitly set to `false`. `undefined` is still `true`.
excludeNodeModules: nycConfig.excludeNodeModules !== false
})
}
return !exclude.shouldInstrument(file)
}
}
export default declare(api => {
api.assertVersion(7)
const shouldSkip = makeShouldSkip()
const t = api.types
return {
visitor: {
Program: {
enter(path) {
// 筛选后的数据增量文件
let diffScreen = null
this.__dv__ = null
this.nycConfig = findConfig(this.opts)
const realPath = getRealpath(this.file.opts.filename)
const { instrmenttation } = this.nycConfig // npm引入参数
const {
IS_PITCHING_PILE = false,
INCREMENT = false,
BRANCH = 'origin/master'
} = instrmenttation || {} // 是否全量代码和对比分支
console.log(IS_PITCHING_PILE, INCREMENT, BRANCH, 'IS_PITCHING_PILE, INCREMENT, BRANCH')
// instrumenttation (branch: git diff 跟那个分支对比, increment 是否开启增量代码检测) 拿配置到底是全量代码还是增量代码
if (!IS_PITCHING_PILE) {
return
}
// const changeList = []
// 下面的是零时的
// const gitDiffCode = execSync(`git diff ${branch}`)
// const diffData = parseDiffData(gitDiffCode.toString())
// diffScreen = diffData.find(item => {
// return realPath.indexOf(item.to) > -1
// })
// 后面解开
if (INCREMENT && BRANCH) {
const gitDiffCode = execSync(`git diff ${BRANCH}`)
const diffData = parseDiffData(gitDiffCode.toString())
diffScreen = diffData.find(item => {
return realPath.indexOf(item.to) > -1
})
}
if (shouldSkip(realPath, this.nycConfig)) {
return
}
let { inputSourceMap } = this.opts
if (this.opts.useInlineSourceMaps) {
if (!inputSourceMap && this.file.inputMap) {
inputSourceMap = this.file.inputMap.sourcemap
}
}
const visitorOptions = {}
Object.entries(schema.defaults.instrumentVisitor).forEach(([name, defaultValue]) => {
if (name in this.nycConfig) {
visitorOptions[name] = this.nycConfig[name]
} else {
visitorOptions[name] = schema.defaults.instrumentVisitor[name]
}
})
// 后增加|| !increment这个条件判断条件后面加上
// if (diffScreen !== null && increment) {
// if (diffScreen) {
// if (Array.isArray(diffScreen && diffScreen.chunks)) {
// diffScreen.chunks.forEach(item => {
// let changes = Array.isArray(item.changes) ? item.changes : []
// changes.forEach(items => {
// if (items && items.add) {
// changeList.push(items.ln)
// }
// })
// })
// }
// changeList
this.__dv__ = programVisitor(t, realPath, {
...visitorOptions,
inputSourceMap
})
this.__dv__.enter(path)
// } else {
// this.__dv__ = programVisitor(t, realPath, {
// ...visitorOptions,
// inputSourceMap
// })
// this.__dv__.enter(path)
// }
},
exit(path) {
if (!this.__dv__) {
return
}
const result = this.__dv__.exit(path)
if (this.opts.onCover) {
this.opts.onCover(getRealpath(this.file.opts.filename), result.fileCoverage)
}
}
}
}
}
})
// 增量代码babel引入方法 babel.js 或 babel.config.js
// 'plugins': [
// ['@hliang/babel-plugin-transfrom-modules-commonjs', {
// extension: ['.js', '.vue'],
// instrmenttation: {
// increment: true, // 是否全量插桩
// branch: 'origin/master' // 对比分支
// }
// }]
// ]
// import { major } from 'semver';
// import { name, version } from '../package.json';
const { createHash } = require('crypto')
// function to use for creating hashes
const VERSION = '4'
const SHA = 'sha1'
// name of coverage data magic key
// const MAGIC_KEY = '_coverageSchema'
// name of coverage data magic value
// export const MAGIC_VALUE = createHash(SHA).update(name + '@' + major(version)).digest('hex');
module.exports = {
SHA,
MAGIC_KEY: '_coverageSchema',
MAGIC_VALUE: createHash(SHA)
.update('name' + '@' + VERSION)
.digest('hex')
}
const { defaults } = require('@istanbuljs/schema')
const Instrumenter = require('./instrumenter')
const programVisitor = require('./visitor')
const readInitialCoverage = require('./read-coverage')
/**
* createInstrumenter creates a new instrumenter with the
* supplied options.
* @param {Object} opts - instrumenter options. See the documentation
* for the Instrumenter class.
*/
function createInstrumenter(opts) {
return new Instrumenter(opts)
}
module.exports = {
createInstrumenter,
programVisitor,
readInitialCoverage,
defaultOpts: defaults.instrumenter
}
/*
Copyright 2012-2015, Yahoo Inc.
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
const babylon = require('babylon');
const t = require('babel-types');
const traverse = require('babel-traverse');
const generate = require('babel-generator');
const programVisitor = require('./visitor');
function defaultOpts() {
return {
coverageVariable: "__coverage__",
preserveComments: false,
compact: true,
esModules: false,
autoWrap: false,
produceSourceMap: false,
sourceMapUrlCallback: null,
debug: false
};
}
/**
* Instrumenter is the public API for the instrument library.
* It is typically used for ES5 code. For ES6 code that you
* are already running under `babel` use the coverage plugin
* instead.
* @param {Object} opts optional.
* @param {string} [opts.coverageVariable=__coverage__] name of global coverage variable.
* @param {boolean} [opts.preserveComments=false] preserve comments in output
* @param {boolean} [opts.compact=true] generate compact code.
* @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 {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
*/
class Instrumenter {
constructor(opts=defaultOpts()) {
this.opts = this.normalizeOpts(opts);
this.fileCoverage = null;
this.sourceMap = null;
}
/**
* normalize options passed in and assign defaults.
* @param opts
* @private
*/
normalizeOpts(opts) {
const normalize = (name, defaultValue) => {
if (!opts.hasOwnProperty(name)) {
opts[name] = defaultValue;
}
};
const defOpts = defaultOpts();
Object.keys(defOpts).forEach(function (k) {
normalize(k, defOpts[k]);
});
return opts;
}
/**
* instrument the supplied code and track coverage against the supplied
* filename. It throws if invalid code is passed to it. ES5 and ES6 syntax
* is supported. To instrument ES6 modules, make sure that you set the
* `esModules` property to `true` when creating the instrumenter.
*
* @param {string} code - the code to instrument
* @param {string} filename - the filename against which to track coverage.
* @param {object} [inputSourceMap] - 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} the instrumented code.
*/
instrumentSync(code, filename, inputSourceMap) {
if (typeof code !== 'string') {
throw new Error('Code must be a string');
}
filename = filename || String(new Date().getTime()) + '.js';
const opts = this.opts;
const ast = babylon.parse(code, {
allowReturnOutsideFunction: opts.autoWrap,
sourceType: opts.esModules ? "module" : "script"
});
const ee = programVisitor(t, filename, {
coverageVariable: opts.coverageVariable,
inputSourceMap: inputSourceMap
});
let output = {};
const visitor = {
Program: {
enter: ee.enter,
exit: function (path) {
output = ee.exit(path);
}
}
};
traverse(ast, visitor);
const generateOptions = {
compact: opts.compact,
sourceMaps: opts.produceSourceMap,
sourceFileName: filename
};
const codeMap = generate(ast, generateOptions, code);
this.fileCoverage = output.fileCoverage;
this.sourceMap = codeMap.map;
const cb = this.opts.sourceMapUrlCallback;
if (cb && output.sourceMappingURL) {
cb(filename, output.sourceMappingURL);
}
return codeMap.code;
}
/**
* callback-style instrument method that calls back with an error
* as opposed to throwing one. Note that in the current implementation,
* the callback will be called in the same process tick and is not asynchronous.
*
* @param {string} code - the code to instrument
* @param {string} filename - the filename against which to track coverage.
* @param {Function} callback - the callback
* @param {Object} inputSourceMap - 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.
*/
instrument(code, filename, callback, inputSourceMap) {
if (!callback && typeof filename === 'function') {
callback = filename;
filename = null;
}
try {
var out = this.instrumentSync(code, filename, inputSourceMap);
callback(null, out);
} catch (ex) {
callback(ex);
}
}
/**
* returns the file coverage object for the last file instrumented.
* @returns {Object} the file coverage object.
*/
lastFileCoverage() {
return this.fileCoverage;
}
/**
* returns the source map produced for the last file instrumented.
* @returns {null|Object} the source map object.
*/
lastSourceMap() {
return this.sourceMap;
}
}
export default Instrumenter;
// import { MAGIC_KEY, MAGIC_VALUE } from './constants';
// import { parse } from 'babylon';
const traverse = require('babel-traverse')
// import * as t from 'babel-types';
const { parseSync } = require('@babel/core')
const { defaults } = require('@istanbuljs/schema')
const { MAGIC_KEY, MAGIC_VALUE } = require('./constants')
function getAst (code) {
if (typeof code === 'object' && typeof code.type === 'string') {
return code
}
if (typeof code !== 'string') {
throw new Error('Code must be a string')
}
return parseSync(code, {
babelrc: false,
configFile: false,
parserOpts: {
allowAwaitOutsideFunction: true,
allowImportExportEverywhere: true,
allowReturnOutsideFunction: true,
allowSuperOutsideMethod: true,
sourceType: 'script',
plugins: defaults.instrumenter.parserPlugins
}
})
}
module.exports = function readInitialCoverage (code) {
const ast = getAst(code)
let covScope
traverse(ast, {
ObjectProperty: function (path) {
const { node } = path;
if (!node.computed &&
path.get('key').isIdentifier() &&
node.key.name === MAGIC_KEY)
{
const magicValue = path.get('value').evaluate()
if (!magicValue.confident || magicValue.value !== MAGIC_VALUE) {
return
}
covScope = path.scope.getFunctionParent() || path.scope.getProgramParent()
path.stop()
}
}
})
if (!covScope) {
return null
}
const result = {}
for (const key of ['path', 'hash', 'gcv', 'coverageData']) {
const binding = covScope.getOwnBinding(key)
if (!binding) {
return null
}
const valuePath = binding.path.get('init')
const value = valuePath.evaluate()
if (!value.confident) {
return null
}
result[key] = value.value
}
delete result.coverageData[MAGIC_KEY]
delete result.coverageData.hash
return result
}
// export default function readInitialCoverage (code) {
// if (typeof code !== 'string') {
// throw new Error('Code must be a string');
// }
// // Parse as leniently as possible
// const ast = parse(code, {
// allowImportExportEverywhere: true,
// allowReturnOutsideFunction: true,
// allowSuperOutsideMethod: true,
// sourceType: "script", // I think ?
// plugins: ["*"]
// });
// let covScope;
// traverse(ast, {
// ObjectProperty: function (path) {
// const { node } = path;
// if (!node.computed &&
// t.isIdentifier(node.key) &&
// node.key.name === MAGIC_KEY)
// {
// const magicValue = path.get('value').evaluate();
// if (!magicValue.confident || magicValue.value !== MAGIC_VALUE) {
// return;
// }
// covScope = path.scope.getFunctionParent();
// path.stop();
// }
// }
// });
// if (!covScope) {
// return null;
// }
// const result = {};
// for (const key of ['path', 'hash', 'gcv', 'coverageData']) {
// const binding = covScope.getOwnBinding(key);
// if (!binding) {
// return null;
// }
// const valuePath = binding.path.get('init');
// const value = valuePath.evaluate();
// if (!value.confident) {
// return null;
// }
// result[key] = value.value;
// }
// delete result.coverageData[MAGIC_KEY];
// return result;
// }
const { classes } = require('istanbul-lib-coverage');
function cloneLocation(loc) {
return {
start: {
line: loc && loc.start.line,
column: loc && loc.start.column
},
end: {
line: loc && loc.end.line,
column: loc && loc.end.column
}
};
}
function isExistIncrementStartmentCode(changeList, loc) {
for (let i = 0; i < changeList.length; i++) {
if (changeList[i] > loc.start.line && changeList[i] <= loc.end.line) {
return true
}
}
return false
}
/**
* SourceCoverage provides mutation methods to manipulate the structure of
* a file coverage object. Used by the instrumenter to create a full coverage
* object for a file incrementally.
*
* @private
* @param pathOrObj {String|Object} - see the argument for {@link FileCoverage}
* @extends FileCoverage
* @constructor
*/
class SourceCoverage extends classes.FileCoverage {
constructor(pathOrObj, changeList) {
super(pathOrObj);
this.data.changeList = changeList ? changeList : [];
this.meta = {
last: {
s: 0,
f: 0,
b: 0
}
};
}
newStatement(loc) {
var s = this.meta.last.s;
this.data.statementMap[s] = cloneLocation(loc);
this.data.s[s] = 0;
this.meta.last.s += 1;
return s;
}
newFunction(name, decl, loc) {
var f = this.meta.last.f;
name = name || '(anonymous_' + f + ')';
this.data.fnMap[f] = {
name: name,
decl: cloneLocation(decl),
loc: cloneLocation(loc)
};
this.data.f[f] = 0;
this.meta.last.f += 1;
return f;
}
newBranch(type, loc) {
var b = this.meta.last.b;
this.data.b[b] = [];
this.data.branchMap[b] = {
loc: cloneLocation(loc),
type: type,
locations: []
};
this.meta.last.b += 1;
return b;
}
addBranchPath(name, location) {
var bMeta = this.data.branchMap[name],
counts = this.data.b[name];
/* istanbul ignore if: paranoid check */
if (!bMeta) {
throw new Error("Invalid branch " + name);
}
bMeta.locations.push(cloneLocation(location));
counts.push(0);
return counts.length - 1;
}
/**
* Assigns an input source map to the coverage that can be used
* to remap the coverage output to the original source
* @param sourceMap {object} the source map
*/
inputSourceMap(sourceMap) {
this.data.inputSourceMap = sourceMap;
}
freeze() {
// prune empty branches
var map = this.data.branchMap,
branches = this.data.b;
Object.keys(map).forEach(function (b) {
if (map[b].locations.length === 0) {
delete map[b];
delete branches[b];
}
});
}
}
export { SourceCoverage };
#!/usr/bin/env node
'use strict'
const { loadNycConfig } = require('@istanbuljs/load-nyc-config')
async function main () {
const [cwd, nycrcPath] = process.argv.slice(2)
console.log(JSON.stringify(await loadNycConfig({ cwd, nycrcPath })))
}
main().catch(error => {
console.log(JSON.stringify({ 'load-nyc-config-sync-error': error.message }))
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment