Skip to content

Commit

Permalink
chore: Use async functions where reasonable (#1184)
Browse files Browse the repository at this point in the history
  • Loading branch information
coreyfarrell committed Oct 6, 2019
1 parent 83eb629 commit 04334e2
Show file tree
Hide file tree
Showing 22 changed files with 429 additions and 295 deletions.
44 changes: 26 additions & 18 deletions bin/nyc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env node
'use strict'

const configUtil = require('../lib/config-util')
const foreground = require('foreground-child')
Expand All @@ -18,23 +19,34 @@ const config = configUtil.loadConfig(yargs.parse(instrumenterArgs))
configUtil.addCommandsAndHelp(yargs)
const argv = yargs.config(config).parse(instrumenterArgs)

if ([
'check-coverage', 'report', 'instrument', 'merge'
].indexOf(argv._[0]) !== -1) {
// look in lib/commands for logic.
} else if (argv._.length) {
async function main () {
if (['check-coverage', 'report', 'instrument', 'merge'].includes(argv._[0])) {
// look in lib/commands for logic.
return
}

if (argv._.length === 0) {
// I don't have a clue what you're doing.
process.exitCode = 1
yargs.showHelp()
return
}

// if instrument is set to false,
// enable a noop instrumenter.
if (!argv.instrument) argv.instrumenter = './lib/instrumenters/noop'
else argv.instrumenter = './lib/instrumenters/istanbul'

var nyc = (new NYC(argv))
if (argv.clean) {
nyc.reset()
await nyc.reset()
} else {
nyc.createTempDirectory()
await nyc.createTempDirectory()
}

if (argv.all) {
await nyc.addAllFiles()
}
if (argv.all) nyc.addAllFiles()

var env = {
// Support running nyc as a user without HOME (e.g. linux 'nobody'),
Expand All @@ -60,14 +72,14 @@ if ([
// use the same argv description, but don't exit
// for flags like --help.
configUtil.buildYargs().parse(process.argv.slice(2))
), function (done) {
), async () => {
var mainChildExitCode = process.exitCode

nyc.writeProcessIndex()
await nyc.writeProcessIndex()

nyc.maybePurgeSourceMapCache()
if (argv.checkCoverage) {
nyc.checkCoverage({
await nyc.checkCoverage({
lines: argv.lines,
functions: argv.functions,
branches: argv.branches,
Expand All @@ -77,13 +89,9 @@ if ([
}

if (!argv.silent) {
nyc.report()
await nyc.report()
}

return done()
})
} else {
// I don't have a clue what you're doing.
process.exitCode = 1
yargs.showHelp()
}

main()
164 changes: 89 additions & 75 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
const cachingTransform = require('caching-transform')
const cpFile = require('cp-file')
const findCacheDir = require('find-cache-dir')
const fs = require('fs')
const glob = require('glob')
const fs = require('./lib/fs-promises')
const os = require('os')
const { debuglog, promisify } = require('util')
const glob = promisify(require('glob'))
const Hash = require('./lib/hash')
const libCoverage = require('istanbul-lib-coverage')
const libHook = require('istanbul-lib-hook')
Expand All @@ -18,12 +20,12 @@ const onExit = require('signal-exit')
const path = require('path')
const reports = require('istanbul-reports')
const resolveFrom = require('resolve-from')
const rimraf = require('rimraf')
const rimraf = promisify(require('rimraf'))
const SourceMaps = require('./lib/source-maps')
const testExclude = require('test-exclude')
const util = require('util')
const pMap = require('p-map')

const debugLog = util.debuglog('nyc')
const debugLog = debuglog('nyc')

let selfCoverageHelper

Expand Down Expand Up @@ -168,11 +170,12 @@ class NYC {
return source
}

addAllFiles () {
async addAllFiles () {
this._loadAdditionalModules()

this.fakeRequire = true
this.exclude.globSync(this.cwd).forEach(relFile => {
const files = await this.exclude.glob(this.cwd)
files.forEach(relFile => {
const filename = path.resolve(this.cwd, relFile)
this.addFile(filename)
const coverage = coverageFinder()
Expand All @@ -190,46 +193,50 @@ class NYC {
this.writeCoverageFile()
}

instrumentAllFiles (input, output, cb) {
async instrumentAllFiles (input, output) {
let inputDir = '.' + path.sep
const visitor = relFile => {
const visitor = async relFile => {
const inFile = path.resolve(inputDir, relFile)
const inCode = fs.readFileSync(inFile, 'utf-8')
const inCode = await fs.readFile(inFile, 'utf-8')
const outCode = this._transform(inCode, inFile) || inCode

if (output) {
const mode = fs.statSync(inFile).mode
const { mode } = await fs.stat(inFile)
const outFile = path.resolve(output, relFile)
mkdirp.sync(path.dirname(outFile))
fs.writeFileSync(outFile, outCode)
fs.chmodSync(outFile, mode)

await mkdirp(path.dirname(outFile))
await fs.writeFile(outFile, outCode)
await fs.chmod(outFile, mode)
} else {
console.log(outCode)
}
}

this._loadAdditionalModules()

try {
const stats = fs.lstatSync(input)
if (stats.isDirectory()) {
inputDir = input

const filesToInstrument = this.exclude.globSync(input)

if (this.config.completeCopy && output) {
const globOptions = { dot: true, nodir: true, ignore: ['**/.git', '**/.git/**', path.join(output, '**')] }
glob.sync(path.resolve(input, '**'), globOptions)
.forEach(src => cpFile.sync(src, path.join(output, path.relative(input, src))))
}
filesToInstrument.forEach(visitor)
} else {
visitor(input)
const stats = await fs.lstat(input)
if (stats.isDirectory()) {
inputDir = input

const filesToInstrument = await this.exclude.glob(input)

const concurrency = output ? os.cpus().length : 1
if (this.config.completeCopy && output) {
await pMap(
await glob(path.resolve(input, '**'), {
dot: true,
nodir: true,
ignore: ['**/.git', '**/.git/**', path.join(output, '**')]
}),
src => cpFile(src, path.join(output, path.relative(input, src))),
{ concurrency }
)
}
} catch (err) {
return cb(err)

await pMap(filesToInstrument, visitor, { concurrency })
} else {
await visitor(input)
}
cb()
}

_transform (code, filename) {
Expand Down Expand Up @@ -307,26 +314,21 @@ class NYC {
}
}

cleanup () {
if (!process.env.NYC_CWD) rimraf.sync(this.tempDirectory())
}

clearCache () {
async createTempDirectory () {
await mkdirp(this.tempDirectory())
if (this.cache) {
rimraf.sync(this.cacheDirectory)
await mkdirp(this.cacheDirectory)
}
}

createTempDirectory () {
mkdirp.sync(this.tempDirectory())
if (this.cache) mkdirp.sync(this.cacheDirectory)

mkdirp.sync(this.processInfo.directory)
await mkdirp(this.processInfo.directory)
}

reset () {
this.cleanup()
this.createTempDirectory()
async reset () {
if (!process.env.NYC_CWD) {
await rimraf(this.tempDirectory())
}

await this.createTempDirectory()
}

_wrapExit () {
Expand Down Expand Up @@ -386,14 +388,15 @@ class NYC {
this.processInfo.save()
}

getCoverageMapFromAllCoverageFiles (baseDirectory) {
async getCoverageMapFromAllCoverageFiles (baseDirectory) {
const map = libCoverage.createCoverageMap({})

this.eachReport(undefined, (report) => {
const data = await this.coverageData(baseDirectory)
data.forEach(report => {
map.merge(report)
}, baseDirectory)
})

map.data = this.sourceMaps.remapCoverage(map.data)
map.data = await this.sourceMaps.remapCoverage(map.data)

// depending on whether source-code is pre-instrumented
// or instrumented using a JIT plugin like @babel/require
Expand All @@ -406,11 +409,11 @@ class NYC {
return map
}

report () {
async report () {
const context = libReport.createContext({
dir: this.reportDirectory(),
watermarks: this.config.watermarks,
coverageMap: this.getCoverageMapFromAllCoverageFiles()
coverageMap: await this.getCoverageMapFromAllCoverageFiles()
})

this.reporter.forEach((_reporter) => {
Expand All @@ -422,32 +425,31 @@ class NYC {
})

if (this._showProcessTree) {
this.showProcessTree()
await this.showProcessTree()
}
}

writeProcessIndex () {
async writeProcessIndex () {
const db = new ProcessDB(this.processInfo.directory)
db.writeIndex()
await db.writeIndex()
}

showProcessTree () {
async showProcessTree () {
const db = new ProcessDB(this.processInfo.directory)
console.log(db.renderTree(this))
console.log(await db.renderTree(this))
}

checkCoverage (thresholds, perFile) {
var map = this.getCoverageMapFromAllCoverageFiles()
var nyc = this
async checkCoverage (thresholds, perFile) {
const map = await this.getCoverageMapFromAllCoverageFiles()

if (perFile) {
map.files().forEach(function (file) {
map.files().forEach(file => {
// ERROR: Coverage for lines (90.12%) does not meet threshold (120%) for index.js
nyc._checkCoverage(map.fileCoverageFor(file).toSummary(), thresholds, file)
this._checkCoverage(map.fileCoverageFor(file).toSummary(), thresholds, file)
})
} else {
// ERROR: Coverage for lines (90.12%) does not meet global threshold (120%)
nyc._checkCoverage(map.getCoverageSummary(), thresholds)
this._checkCoverage(map.getCoverageSummary(), thresholds)
}
}

Expand All @@ -465,6 +467,28 @@ class NYC {
})
}

async coverageFiles (baseDirectory) {
const files = await fs.readdir(baseDirectory)

return files.map(f => path.resolve(baseDirectory, f))
}

async coverageFileLoad (filename) {
try {
const report = JSON.parse(await fs.readFile(filename), 'utf8')
await this.sourceMaps.reloadCachedSourceMaps(report)
return report
} catch (error) {
return {}
}
}

async coverageData (baseDirectory = this.tempDirectory()) {
const files = await this.coverageFiles(baseDirectory)
return pMap(files, f => this.coverageFileLoad(f), { concurrency: os.cpus().length })
}

/* istanbul ignore next: legacy function used by istanbul-lib-processinfo. */
eachReport (filenames, iterator, baseDirectory) {
baseDirectory = baseDirectory || this.tempDirectory()

Expand All @@ -484,7 +508,7 @@ class NYC {
'utf-8'
))

_this.sourceMaps.reloadCachedSourceMaps(report)
_this.sourceMaps.reloadCachedSourceMapsSync(report)
} catch (e) { // handle corrupt JSON output.
report = {}
}
Expand All @@ -493,16 +517,6 @@ class NYC {
})
}

loadReports (filenames) {
var reports = []

this.eachReport(filenames, (report) => {
reports.push(report)
})

return reports
}

tempDirectory () {
return path.resolve(this.cwd, this._tempDirectory)
}
Expand Down
8 changes: 5 additions & 3 deletions lib/commands/check-coverage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const testExclude = require('test-exclude')
const NYC = require('../../index.js')
const cliWrapper = require('./cli-wrapper.js')

exports.command = 'check-coverage'

Expand Down Expand Up @@ -65,13 +66,14 @@ exports.builder = function (yargs) {
.example('$0 check-coverage --lines 95', "check whether the JSON in nyc's output folder meets the thresholds provided")
}

exports.handler = function (argv) {
exports.handler = cliWrapper(async argv => {
process.env.NYC_CWD = process.cwd()

;(new NYC(argv)).checkCoverage({
const nyc = new NYC(argv)
await nyc.checkCoverage({
lines: argv.lines,
functions: argv.functions,
branches: argv.branches,
statements: argv.statements
}, argv['per-file'])
}
})

0 comments on commit 04334e2

Please sign in to comment.