feat(@embark/embark-solc): Support recursively remapping imports

Changes include:
- Before compilation, for each contract file being compiled, recursively remaps the contract's imports.
- Allowed directories for compilation updated based on the remapped import paths for the contract file.
- Support for code coverage flag.
- Fix for unhandled promise rejection when attempting to use an insufficient version of solc.
This commit is contained in:
emizzle 2019-01-31 13:37:20 +11:00
parent fa05706f47
commit d6c2035b54
2 changed files with 34 additions and 51 deletions

View File

@ -6,31 +6,26 @@ module.exports = (embark) => {
if (embark.config.embarkConfig.versions.solc) { if (embark.config.embarkConfig.versions.solc) {
const versionPromise = new Promise(function(resolve, reject) { const versionPromise = new Promise(function(resolve, reject) {
// Check solc version // Check solc version
Compiler.getSolcVersion(embark.logger, (err, version) => {
if (err) {
embark.logger.error(err);
embark.logger.error("Error getting solc's version. Will default back to Embark's compiler");
return reject(err);
}
if (semver.lt(version, embark.config.embarkConfig.versions.solc)) {
embark.logger.warn(`Current version of solc lower than version in embark.json`);
embark.logger.warn(`Current: ${version} | Wanted: ${embark.config.embarkConfig.versions.solc}`);
embark.logger.warn('Will default back to Embark\'s compiler');
return reject(new Error('Bad version'));
}
resolve();
});
}); });
embark.registerCompiler('.sol', (contractFiles, options, cb) => { embark.registerCompiler('.sol', (contractFiles, options, cb) => {
if (!contractFiles || !contractFiles.length) { if (!contractFiles || !contractFiles.length) {
return cb(); return cb();
} }
versionPromise.then(() => { Compiler.getSolcVersion(embark.logger, (err, version) => {
Compiler.compileSolc(embark, contractFiles, embark.config.contractDirectories, cb); if (err) {
}).catch(_e => { embark.logger.error(err);
// Need to default to Embark's compiler embark.logger.error("Error getting solc's version. Will default back to Embark's compiler");
cb(null, false); return cb(null, false);
}
if (semver.lt(version, embark.config.embarkConfig.versions.solc)) {
embark.logger.warn(`Current version of solc lower than version in embark.json`);
embark.logger.warn(`Current: ${version} | Wanted: ${embark.config.embarkConfig.versions.solc}`);
embark.logger.warn('Will default back to Embark\'s compiler');
return cb(null, false);
}
Compiler.compileSolc(embark, contractFiles, embark.config.contractDirectories, options, cb);
}); });
}); });

View File

@ -42,7 +42,7 @@ function getSolcVersion(logger, callback) {
}); });
} }
function compileSolc(embark, contractFiles, contractDirectories, callback) { function compileSolc(embark, contractFiles, contractDirectories, options, callback) {
if (!contractFiles || !contractFiles.length) { if (!contractFiles || !contractFiles.length) {
return callback(); return callback();
} }
@ -52,7 +52,7 @@ function compileSolc(embark, contractFiles, contractDirectories, callback) {
const outputDir = embark.config.buildDir + embark.config.contractDirectories[0]; const outputDir = embark.config.buildDir + embark.config.contractDirectories[0];
const solcConfig = embark.config.embarkConfig.options.solc; const solcConfig = embark.config.embarkConfig.options.solc;
let allowedDirectories; let allowedDirectories = [];
const remappings = []; const remappings = [];
const compilationSettings = { const compilationSettings = {
language: 'Solidity', language: 'Solidity',
@ -94,43 +94,31 @@ function compileSolc(embark, contractFiles, contractDirectories, callback) {
next(); next();
}, },
function getAllowedDirectories(next) {
allowedDirectories = contractFiles.map((contractFile) => path.join(process.cwd(), path.dirname(contractFile.path) + '/'))
.filter((x, i, a) => a.indexOf(x) === i);
// Add default contract paths
allowedDirectories.push(
path.join(process.cwd(), 'node_modules/'),
path.join(process.cwd(), '.embark/contracts/')
);
next();
},
function getContentAndRemappings(next) { function getContentAndRemappings(next) {
async.each(contractFiles, (file, eachCb) => { async.each(contractFiles, (file, eachCb) => {
file.content(content => { file.prepareForCompilation(options.isCoverage).then((content) => {
file.parsedContent = content; // add contract directory and all it's recusrive import direcotries to allowed directories
let dir = path.dirname(file.path);
if (!allowedDirectories.includes(dir)) allowedDirectories.push(dir);
const newRemappings = file.importRemappings.map((mapping) => `${mapping.prefix}=${mapping.target}`); file.importRemappings.forEach((importRemapping) => {
newRemappings.forEach(newRemapping => { dir = path.dirname(importRemapping.target);
if (!remappings.includes(newRemapping)) { if (!allowedDirectories.includes(dir)) allowedDirectories.push(dir);
remappings.push(newRemapping);
const remapping = `${importRemapping.prefix}=${importRemapping.target}`;
if (!remappings.includes(remapping)) {
remappings.push(remapping);
} }
}); });
eachCb(); compilationSettings.sources[file.path] = {
}); content: content.replace(/\r\n/g, '\n'),
}, next); path: file.path
}, };
function getCompilationSettings(next) { eachCb();
contractFiles.forEach(file => { }).catch(eachCb);
const filename = file.pluginPath ? path.join(file.pluginPath, file.filename) : file.filename; }, next);
compilationSettings.sources[filename] = {
content: file.parsedContent.replace(/\r\n/g, '\n'),
path: filename
};
});
next();
}, },
function compile(next) { function compile(next) {