Skip to content

Commit

Permalink
feat(Merger): add support for circular dependencies
Browse files Browse the repository at this point in the history
Relates #27
  • Loading branch information
RyuuGan committed Jan 10, 2020
1 parent 1c233f7 commit a7dd280
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 11 deletions.
2 changes: 2 additions & 0 deletions lib/fileAnalyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export class FileAnalyzer {

return {
file,
importStatement,
globalRenameImport,
namedImports,
};
Expand Down Expand Up @@ -172,6 +173,7 @@ export interface FileAnalyzerResult {
}

export interface FileAnalyzerImportsResult {
importStatement: string;
file: string;
globalRenameImport: string | null;
namedImports: FileAnalyzerNamedImportResult[] | null;
Expand Down
33 changes: 28 additions & 5 deletions lib/merger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import {
} from './fileAnalyzer';

const error = Debug('sol-merger:error');
const log = Debug('sol-merge:log');
const debug = Debug('sol-merger:debug');

export class Merger {
delimeter: string = this.options.delimeter || '\n\n';
removeComments: boolean;

registeredImportStatements: string[] = [];
registeredImports: RegistredImport[] = [];
nodeModulesRoot: string = null;

Expand Down Expand Up @@ -59,15 +60,37 @@ export class Merger {
);
}

async init(file: string) {
this.registeredImports = [];
this.registeredImportStatements = [];
this.nodeModulesRoot = await this.getNodeModulesPath(file);
}

isImportProcessed(importStatement: string): boolean {
return this.registeredImportStatements.includes(importStatement);
}

registerImportStatement(importStatement: string) {
this.registeredImportStatements.push(importStatement);
}

async processFile(
file: string,
isRoot: boolean,
parentImport?: FileAnalyzerImportsResult,
) {
): Promise<string> {
if (isRoot) {
this.registeredImports = [];
this.nodeModulesRoot = await this.getNodeModulesPath(file);
await this.init(file);
}
if (this.isImportProcessed(parentImport?.importStatement)) {
return '';
}
if (parentImport) {
this.registerImportStatement(parentImport.importStatement);
}

debug('Processing file %s', file);

const analyzedFile = await new FileAnalyzer(
file,
this.removeComments,
Expand Down Expand Up @@ -159,7 +182,7 @@ export class Merger {
: null;
const isImported = this.isImported(analyzedFile.filename, e.name, rename);
if (isImported) {
log('%s %s %s', '⚠', e.name, analyzedFile.filename);
debug('%s Already imported: %s %s', '⚠', e.name, analyzedFile.filename);
return;
}
if (beImported) {
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"ts-node": "^8.3.0",
"tslib": "^1.10.0",
"tslint": "^5.17.0",
"typescript": "^3.5.2",
"typescript": "^3.7.4",
"zeppelin-solidity": "^1.12.0"
}
}
18 changes: 18 additions & 0 deletions test/compiled/circular/Circular1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pragma solidity >=0.4.21 <0.6.0;


contract Circular1 {
address public owner;

constructor() public {
owner = msg.sender;
}
}

contract Circular2 {
address public owner;

constructor() public {
owner = msg.sender;
}
}
11 changes: 11 additions & 0 deletions test/contracts/circular/Circular1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pragma solidity >=0.4.21 <0.6.0;

import "./Circular2.sol";

contract Circular1 {
address public owner;

constructor() public {
owner = msg.sender;
}
}
11 changes: 11 additions & 0 deletions test/contracts/circular/Circular2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pragma solidity >=0.4.21 <0.6.0;

import "./Circular1.sol";

contract Circular2 {
address public owner;

constructor() public {
owner = msg.sender;
}
}
12 changes: 10 additions & 2 deletions test/fileAnalyzer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ describe('FileAnalyzer', () => {
const result = fileAnalyzer.analyzeImport('import "filename.sol";');
assert.deepEqual(result, {
file: 'filename.sol',
importStatement: 'import "filename.sol";',
globalRenameImport: null,
namedImports: null,
});
Expand All @@ -30,6 +31,7 @@ describe('FileAnalyzer', () => {
result,
{
file: 'filename.sol',
importStatement: 'import "filename.sol" as myName;',
globalRenameImport: 'myName',
namedImports: null,
},
Expand All @@ -43,6 +45,7 @@ describe('FileAnalyzer', () => {
result,
{
file: 'filename.sol',
importStatement: 'import * as myName from "filename.sol";',
globalRenameImport: 'myName',
namedImports: null,
},
Expand All @@ -56,6 +59,7 @@ describe('FileAnalyzer', () => {
);
assert.deepEqual(result, {
file: 'filename.sol',
importStatement: 'import { A, B as Bingo, C as C1, D } from "filename.sol";',
globalRenameImport: null,
namedImports: [
{
Expand Down Expand Up @@ -95,21 +99,25 @@ describe('FileAnalyzer', () => {
assert.deepEqual(imports, [
{
file: 'filename.sol',
importStatement: 'import "filename.sol";',
globalRenameImport: null,
namedImports: null,
},
{
file: 'filename1.sol',
importStatement: 'import "filename1.sol" as myName;',
globalRenameImport: 'myName',
namedImports: null,
},
{
file: 'filename2.sol',
importStatement: 'import * as myName from "filename2.sol";',
globalRenameImport: 'myName',
namedImports: null,
},
{
file: 'filename3.sol',
importStatement: 'import { A, B as Bingo, C as C1, D } from "filename3.sol";',
globalRenameImport: null,
namedImports: [
{
Expand Down Expand Up @@ -189,9 +197,9 @@ describe('FileAnalyzer', () => {

it('should return empty array if there are no exports', () => {
const exports = fileAnalyzer.analyzeExports(`
Some contracts without exports
// Some contracts without exports
Some contract text that is not required here
// Some contract text that is not required here
`);

assert.deepEqual(exports, []);
Expand Down
5 changes: 5 additions & 0 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ describe('Solidity Merger', () => {
'Delimeter must be set to 2 new lines',
);
assert.isArray(merger.registeredImports, 'Must be initialized as array');
assert.isArray(merger.registeredImportStatements, 'Must be initialized as array');
});

it('should import relative files', async () => {
Expand Down Expand Up @@ -63,4 +64,8 @@ describe('Solidity Merger', () => {
it('should compile file leaving the comments inside exports', async () => {
await testFile('LocalImportsWithComments', { removeComments: false });
});

it('should compile while having circular dependencies', async () => {
await testFile('circular/Circular1');
})
});

0 comments on commit a7dd280

Please sign in to comment.