From 6e29c8bea98197588e55e601d13c221d88e570db Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Mon, 30 Mar 2020 15:54:27 -0400 Subject: [PATCH] `@0x/sol-compiler`: Make source paths in output artifacts nicer if they're within modules. `@0x/sol-compiler`: Makea Add v0.6 solidity test. --- packages/sol-compiler/src/utils/compiler.ts | 23 ++++++++---- packages/sol-compiler/test/compiler_test.ts | 20 +++++++++- .../test/fixtures/contracts/V6Contract.sol | 37 +++++++++++++++++++ 3 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 packages/sol-compiler/test/fixtures/contracts/V6Contract.sol diff --git a/packages/sol-compiler/src/utils/compiler.ts b/packages/sol-compiler/src/utils/compiler.ts index 622a0bd01d..7c5805283f 100644 --- a/packages/sol-compiler/src/utils/compiler.ts +++ b/packages/sol-compiler/src/utils/compiler.ts @@ -315,9 +315,12 @@ function recursivelyGatherDependencySources( importRemappings: { [prefix: string]: string }, compiledImports: CompiledImports, visitedAbsolutePaths: { [absPath: string]: boolean } = {}, + importRootDir?: string, ): void { if (visitedAbsolutePaths[contractPath]) { return; + } else { + visitedAbsolutePaths[contractPath] = true; } const contractSource = sourcesByAbsolutePath[contractPath].content; const importStatementMatches = contractSource.match(/\nimport[^;]*;/g); @@ -334,25 +337,30 @@ function recursivelyGatherDependencySources( let importPath = importPathMatches[1]; let absPath = importPath; + let _importRootDir = importRootDir; if (importPath.startsWith('.')) { absPath = path.join(contractFolder, importPath); - // Express relative imports paths as paths from the root directory. - importPath = path.relative(rootDir, absPath); - if (!importPath.startsWith('.')) { - importPath = `./${importPath}`; + if (_importRootDir) { + // If there's an `_importRootDir`, we're in a package, so express + // the import path as within the package. + importPath = path.join(_importRootDir, importPath); + } else { + // Express relative imports paths as paths from the root directory. + importPath = path.relative(rootDir, absPath); + if (!importPath.startsWith('.')) { + importPath = `./${importPath}`; + } } } else { for (const [prefix, replacement] of Object.entries(importRemappings)) { if (importPath.startsWith(prefix)) { absPath = `${replacement}${importPath.substr(prefix.length)}`; + _importRootDir = path.dirname(importPath); break; } } } - compiledImports[importPath] = sourcesByAbsolutePath[absPath]; - visitedAbsolutePaths[absPath] = true; - recursivelyGatherDependencySources( absPath, rootDir, @@ -360,6 +368,7 @@ function recursivelyGatherDependencySources( importRemappings, compiledImports, visitedAbsolutePaths, + _importRootDir, ); } } diff --git a/packages/sol-compiler/test/compiler_test.ts b/packages/sol-compiler/test/compiler_test.ts index cae6bce053..7dcecd2cbf 100644 --- a/packages/sol-compiler/test/compiler_test.ts +++ b/packages/sol-compiler/test/compiler_test.ts @@ -26,7 +26,7 @@ describe('#Compiler', function(): void { it('should create a Compiler with empty opts', async () => { const _compiler = new Compiler(); // tslint:disable-line no-unused-variable }); - it('should create an Exchange artifact with the correct unlinked binary', async () => { + it.only('should create an Exchange artifact with the correct unlinked binary', async () => { compilerOpts.contracts = ['Exchange']; const exchangeArtifactPath = `${artifactsDir}/Exchange.json`; @@ -114,4 +114,22 @@ describe('#Compiler', function(): void { expect(artifact).to.equal('EmptyContract.json'); } }); + it('should compile a V0.6 contract', async () => { + compilerOpts.contracts = ['V6Contract']; + + const artifactPath = `${artifactsDir}/V6Contract.json`; + if (fsWrapper.doesPathExistSync(artifactPath)) { + await fsWrapper.removeFileAsync(artifactPath); + } + + await new Compiler(compilerOpts).compileAsync(); + + const opts = { + encoding: 'utf8', + }; + const exchangeArtifactString = await fsWrapper.readFileAsync(artifactPath, opts); + const exchangeArtifact: ContractArtifact = JSON.parse(exchangeArtifactString); + const bin = exchangeArtifact.compilerOutput.evm.bytecode.object; + expect(bin.slice(2)).to.length.to.be.gt(0); + }); }); diff --git a/packages/sol-compiler/test/fixtures/contracts/V6Contract.sol b/packages/sol-compiler/test/fixtures/contracts/V6Contract.sol new file mode 100644 index 0000000000..de9f038a59 --- /dev/null +++ b/packages/sol-compiler/test/fixtures/contracts/V6Contract.sol @@ -0,0 +1,37 @@ +/* + + Copyright 2020 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.6.4; + + +contract V6Contract { + + uint256 private _privateNumber; + + constructor(uint256 privateNumber) public { + _privateNumber = privateNumber; + } + + fallback() external { + revert('nope'); + } + + receive() payable external { + // no-op + } +}