diff --git a/HARDHAT_README.md b/HARDHAT_README.md index 2420f1e7..f182a53b 100644 --- a/HARDHAT_README.md +++ b/HARDHAT_README.md @@ -69,11 +69,13 @@ module.exports = { | istanbulFolder | *String* | `./coverage` | Folder location for Istanbul coverage reports. | | istanbulReporter | *Array* | `['html', 'lcov', 'text', 'json']` | [Istanbul coverage reporters][2] | | mocha | *Object* | `{ }` | [Mocha options][3] to merge into existing mocha config. `grep` and `invert` are useful for skipping certain tests under coverage using tags in the test descriptions.| +| coverageContractsTemp | *String* | `.coverage_contracts` | Temporary folder location for instrumented contracts - Note that this directory will automatically be deleted when coverage completes. | | onServerReady[*][14] | *Function* | | Hook run *after* server is launched, *before* the tests execute. Useful if you need to use the Oraclize bridge or have setup scripts which rely on the server's availability. [More...][23] | +| onPreCompile[*][14] | *Function* | | Hook run *after* filesystem and compiler configuration is applied, *before* the compiler is run. Can be used with the other hooks to be able to generate coverage reports on non-standard / customized directory structures, as well as contracts with absolute import paths. [More...][23] | | onCompileComplete[*][14] | *Function* | | Hook run *after* compilation completes, *before* tests are run. Useful if you have secondary compilation steps or need to modify built artifacts. [More...][23]| | onTestsComplete[*][14] | *Function* | | Hook run *after* the tests complete, *before* Istanbul reports are generated. [More...][23]| | onIstanbulComplete[*][14] | *Function* | | Hook run *after* the Istanbul reports are generated, *before* the ganache server is shut down. Useful if you need to clean resources up. [More...][23]| -| configureYulOptimizer | *Boolean* | false | (Experimental) Setting to `true` should resolve "stack too deep" compiler errrors in large projects using ABIEncoderV2 | +| configureYulOptimizer | *Boolean* | false | (Experimental) Setting to `true` should resolve "stack too deep" compiler errors in large projects using ABIEncoderV2 | [* Advanced use][14] diff --git a/README.md b/README.md index df6e3519..0f6d4128 100644 --- a/README.md +++ b/README.md @@ -125,11 +125,13 @@ module.exports = { | istanbulFolder | *String* | `./coverage` | Folder location for Istanbul coverage reports. | | istanbulReporter | *Array* | `['html', 'lcov', 'text', 'json']` | [Istanbul coverage reporters][2] | | mocha | *Object* | `{ }` | [Mocha options][3] to merge into existing mocha config. `grep` and `invert` are useful for skipping certain tests under coverage using tags in the test descriptions.| +| coverageContractsTemp | *String* | `.coverage_contracts` | Temporary folder location for instrumented contracts - Note that this directory will automatically be deleted when coverage completes. | | onServerReady[*][14] | *Function* | | Hook run *after* server is launched, *before* the tests execute. Useful if you need to use the Oraclize bridge or have setup scripts which rely on the server's availability. [More...][23] | +| onPreCompile[*][14] | *Function* | | Hook run *after* filesystem and compiler configuration is applied, *before* the compiler is run. Can be used with the other hooks to be able to generate coverage reports on non-standard / customized directory structures, as well as contracts with absolute import paths. [More...][23] | | onCompileComplete[*][14] | *Function* | | Hook run *after* compilation completes, *before* tests are run. Useful if you have secondary compilation steps or need to modify built artifacts. [More...][23]| | onTestsComplete[*][14] | *Function* | | Hook run *after* the tests complete, *before* Istanbul reports are generated. [More...][23]| | onIstanbulComplete[*][14] | *Function* | | Hook run *after* the Istanbul reports are generated, *before* the ganache server is shut down. Useful if you need to clean resources up. [More...][23]| -| configureYulOptimizer | *Boolean* | false | (Experimental) Setting to `true` should resolve "stack too deep" compiler errrors in large projects using ABIEncoderV2 | +| configureYulOptimizer | *Boolean* | false | (Experimental) Setting to `true` should resolve "stack too deep" compiler errors in large projects using ABIEncoderV2 | [* Advanced use][14] diff --git a/docs/advanced.md b/docs/advanced.md index c267e7f4..f1820026 100644 --- a/docs/advanced.md +++ b/docs/advanced.md @@ -34,6 +34,7 @@ The stages/hooks are (in order of execution): | Stage | Post-stage hook | |----------------------------------------|--------------------| +| Before compiling | onPreCompile | | Launch server | onServerReady | | Instrument and compile contracts | onCompileComplete | | Run tests using instrumented artifacts | onTestsComplete | @@ -85,6 +86,14 @@ This option allows you to avoid that but it's important to realise that the temp folder is **automatically deleted** when coverage completes. You shouldn't use it if your preferred build target contains information you want to preserve between test runs. +## Setting a custom temporary contracts directory + +A custom disposable folder to be used for the contracts can be specified by setting the +``` +coverageContractsTemp +``` +property in the configuration file. If not set, this directory defaults to `.coverage_contracts`. + ## Reducing the instrumentation footprint If your project is very large or if you have logic that's gas sensitive, it can be useful to diff --git a/lib/api.js b/lib/api.js index cbc83c4e..13ad991f 100644 --- a/lib/api.js +++ b/lib/api.js @@ -36,6 +36,7 @@ class API { this.onTestsComplete = config.onTestsComplete || this.defaultHook; this.onCompileComplete = config.onCompileComplete || this.defaultHook; this.onIstanbulComplete = config.onIstanbulComplete || this.defaultHook; + this.onPreCompile = config.onPreCompile || this.defaultHook; this.server = null; this.defaultPort = 8555; diff --git a/plugins/resources/plugin.utils.js b/plugins/resources/plugin.utils.js index 39c5586c..8ef73105 100644 --- a/plugins/resources/plugin.utils.js +++ b/plugins/resources/plugin.utils.js @@ -94,7 +94,7 @@ function toRelativePath(pathToFile, pathToParent){ function getTempLocations(config){ const contractsRoot = path.parse(config.contractsDir).dir const cwd = config.workingDir; - const contractsDirName = '.coverage_contracts'; + const contractsDirName = config.coverageContractsTemp || '.coverage_contracts'; const artifactsDirName = config.temp || '.coverage_artifacts'; return { diff --git a/plugins/truffle.plugin.js b/plugins/truffle.plugin.js index 6888d67d..aebd9df6 100644 --- a/plugins/truffle.plugin.js +++ b/plugins/truffle.plugin.js @@ -93,6 +93,9 @@ async function plugin(config){ config.all = true; config.compilers.solc.settings.optimizer.enabled = false; + // Run pre-compile hook; + await api.onPreCompile(config); + // Compile Instrumented Contracts await truffle.contracts.compile(config); await api.onCompileComplete(config); diff --git a/test/integration/projects/test-files/.solcover.js b/test/integration/projects/test-files/.solcover.js index 42903c81..7d813ad6 100644 --- a/test/integration/projects/test-files/.solcover.js +++ b/test/integration/projects/test-files/.solcover.js @@ -5,6 +5,7 @@ module.exports = { skipFiles: ['Migrations.sol'], silent: process.env.SILENT ? true : false, istanbulReporter: ['json-summary', 'text'], + onPreCompile: fn.bind(null, 'running onPreCompile'), onServerReady: fn.bind(null, 'running onServerReady'), onTestsComplete: fn.bind(null, 'running onTestsComplete'), onCompileComplete: fn.bind(null, 'running onCompileComplete'), diff --git a/test/units/truffle/standard.js b/test/units/truffle/standard.js index f1946ac1..909c9007 100644 --- a/test/units/truffle/standard.js +++ b/test/units/truffle/standard.js @@ -420,6 +420,7 @@ describe('Truffle Plugin: standard use cases', function() { await plugin(truffleConfig); assert( + mock.loggerOutput.val.includes('running onPreCompile') && mock.loggerOutput.val.includes('running onServerReady') && mock.loggerOutput.val.includes('running onTestsComplete') && mock.loggerOutput.val.includes('running onCompileComplete') &&