diff --git a/lib/app.js b/lib/app.js index 9b19455c..af760e00 100644 --- a/lib/app.js +++ b/lib/app.js @@ -30,17 +30,19 @@ class App { // Other this.testrpcProcess = null; // ref to testrpc server we need to close on exit - this.events = null; // ref to string array loaded from 'allFiredEvents' + this.events = null; // ref to string array loaded from 'allFiredEvents' this.testsErrored = null; // flag set to non-null if truffle tests error this.coverage = new CoverageMap(); // initialize a coverage map this.originalArtifacts = []; // Artifacts from original build (we swap these in) this.skippedFolders = []; + this.forceParseFolders = []; // Config this.config = config || {}; this.workingDir = config.dir || '.'; // Relative path to contracts folder this.accounts = config.accounts || 35; // Number of accounts to testrpc launches with this.skipFiles = config.skipFiles || []; // Which files should be skipped during instrumentation + this.forceParse = config.forceParse || []; // Which files should be force parsed during instrumentation this.norpc = config.norpc || false; // Launch testrpc-sc internally? this.port = config.port || 8555; // Port testrpc should listen on this.buildDirPath = config.buildDirPath || '/build/contracts' // Build directory path for compiled smart contracts @@ -81,6 +83,12 @@ class App { this.skippedFolders.push(item); }); + // Identify folders to force parse + this.forceParse.forEach(item => { + if (path.extname(item) !== '.sol') + this.forceParseFolders.push(item); + }); + files = files.map(file => `${this.workingDir}/${file}`); shell.mkdir(this.coverageDir); shell.cp('-R', files, this.coverageDir); @@ -143,6 +151,7 @@ class App { instrumentTarget() { this.skipFiles = this.skipFiles.map(contract => `${this.coverageDir}/contracts/${contract}`); this.skipFiles.push(`${this.coverageDir}/contracts/Migrations.sol`); + this.forceParse = this.forceParse.map(contract => `${this.coverageDir}/contracts/${contract}`); const instrumentedFiles = []; let currentFile; @@ -155,7 +164,7 @@ class App { const contractPath = this.platformNeutralPath(file); const working = this.workingDir.substring(1); - const canonicalPath = contractPath.split('/coverageEnv').join(working); + const canonicalPath = file.split('/coverageEnv').join(working); const contract = fs.readFileSync(contractPath).toString(); const instrumentedContractInfo = getInstrumentedVersion(contract, canonicalPath); fs.writeFileSync(contractPath, instrumentedContractInfo.contract); @@ -178,8 +187,11 @@ class App { .forEach(file => { // Skip post-processing of skipped files - if (this.deepSkip && (this.skipFiles.includes(file) || this.inSkippedFolder(file))) return; - + if (this.deepSkip && (this.skipFiles.includes(file) || this.inSkippedFolder(file)) && !(this.forceParse.includes(file) || this.inForceParseFolder(file))) { + this.log('Skipping post-processing of ', file); + return; + } + this.log('Post-processing ', file); const contractPath = this.platformNeutralPath(file); const contract = fs.readFileSync(contractPath).toString(); const contractProcessed = preprocessor.run(contract); @@ -415,6 +427,21 @@ class App { return shouldSkip; } + /** + * Determines if a file is in a folder marked force parse. + * @param {String} file file path + * @return {Boolean} + */ + inForceParseFolder(file){ + let shouldParse; + this.forceParseFolders.forEach(folderToParse => { + folderToParse = `${this.coverageDir}/contracts/${folderToParse}`; + if (file.indexOf(folderToParse) === 0) + shouldParse = true; + }); + return shouldParse; + } + /** * Allows config to turn logging off (for CI) * @param {Boolean} isSilent @@ -463,4 +490,4 @@ class App { } } -module.exports = App; +module.exports = App; \ No newline at end of file