diff --git a/lib/merger.js b/lib/merger.js index 82bd48e..1b8dd61 100644 --- a/lib/merger.js +++ b/lib/merger.js @@ -22,18 +22,25 @@ class Merger { getPragmaRegex() { return /(pragma solidity (.+?);)/g; } + getABIEncoderPragmaRegex() { + return /(pragma experimental ABIEncoderV2;)/g; + } getImportRegex() { - return /import ['"](.+?)['"];/g; + return /import .*['"](.+?)['"];/g; } getPragma(contents) { let group = this.getPragmaRegex().exec(contents); return group && group[1]; } + getABIEncoderPragma(contents) { + let group = this.getABIEncoderPragmaRegex().exec(contents); + return group && group[1]; + } stripPragma(contents) { - return contents.replace(this.getPragmaRegex(), '').trim(); + return contents.replace(this.getPragmaRegex(), '').replace(this.getABIEncoderPragmaRegex(), '').trim(); } async processFile(file, isRoot) { @@ -51,21 +58,32 @@ class Merger { let contents = await fs.readFileAsync(file, { encoding: 'utf-8' }); let result = ''; + let importedContents = ''; + + let imports = await this.processImports(file, contents); + + for (let i = 0; i < imports.length; i++) { + importedContents += imports[i] + this.delimeter; + } if (isRoot) { let pragma = this.getPragma(contents); result = pragma + this.delimeter; - } - contents = this.stripPragma(contents); - let imports = await this.processImports(file, contents); - for (let i = 0; i < imports.length; i++) { - result += imports[i] + this.delimeter; + let hasExperimentalPragma = this.getABIEncoderPragma(contents) || this.getABIEncoderPragma(importedContents); + if (hasExperimentalPragma) { + result = result + 'pragma experimental ABIEncoderV2;' + this.delimeter; + } + + contents = this.stripPragma(contents); + importedContents = this.stripPragma(importedContents); } contents = this.stripImports(contents); - result += contents; - + importedContents = this.stripImports(importedContents); + + result += importedContents + this.delimeter + contents; + result = result.replace(/^\s*[\r\n]/gm, '\n'); return result; } diff --git a/test/compiled/LocalImports.sol b/test/compiled/LocalImports.sol index 5da0a25..6e8da22 100644 --- a/test/compiled/LocalImports.sol +++ b/test/compiled/LocalImports.sol @@ -1,5 +1,7 @@ pragma solidity ^0.4.11; +pragma experimental ABIEncoderV2; + contract Ownable { address public owner; diff --git a/test/compiled/MultiImports.sol b/test/compiled/MultiImports.sol index 9b20a2d..1e9ab2e 100644 --- a/test/compiled/MultiImports.sol +++ b/test/compiled/MultiImports.sol @@ -136,7 +136,6 @@ contract StandardToken is ERC20, BasicToken { mapping (address => mapping (address => uint256)) internal allowed; - /** * @dev Transfer tokens from one address to another * @param _from address The address which you want to send tokens from diff --git a/test/contracts/NamedImports.sol b/test/contracts/NamedImports.sol new file mode 100644 index 0000000..3ed1679 --- /dev/null +++ b/test/contracts/NamedImports.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.4.11; + +import {Ownable} from "./imports/ownable.sol"; + +contract MyOwned is Ownable { + string public constant name = "My Owned"; + + function MyOwned() {} +} diff --git a/test/contracts/imports/ownable.sol b/test/contracts/imports/ownable.sol index cb0e78f..21c8732 100644 --- a/test/contracts/imports/ownable.sol +++ b/test/contracts/imports/ownable.sol @@ -1,4 +1,5 @@ pragma solidity ^0.4.11; +pragma experimental ABIEncoderV2; contract Ownable { address public owner; diff --git a/test/index.js b/test/index.js index 3c07ceb..6afab69 100644 --- a/test/index.js +++ b/test/index.js @@ -32,8 +32,15 @@ describe('Solidity Merger', () => { let file = path.join(__dirname, '/contracts/MultiImports.sol'); let result = await merger.processFile(file, true); - assertWithFile(result, 'MultiImports.sol'); }); + it('should import named contract', async () => { + let merger = new Merger({ delimeter: '\n\n' }); + let file = path.join(__dirname, '/contracts/NamedImports.sol'); + + let result = await merger.processFile(file, true); + + assertWithFile(result, 'LocalImports.sol'); + }); });