|
|
|
@ -21,39 +21,84 @@ function writeTestAccountsContract (accounts: string[]) { |
|
|
|
|
return testAccountContract.replace('>accounts<', body) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @dev Check if path includes name of a remix test file |
|
|
|
|
* @param path file path to check |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
function isRemixTestFile(path: string) { |
|
|
|
|
return ['tests.sol', 'remix_tests.sol', 'remix_accounts.sol'].some(name => path.includes(name)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @dev Process file to prepare sources object to be passed in solc compiler input |
|
|
|
|
*
|
|
|
|
|
* See: https://solidity.readthedocs.io/en/latest/using-the-compiler.html#input-description
|
|
|
|
|
*
|
|
|
|
|
* @param filePath path of file to process |
|
|
|
|
* @param sources existing 'sources' object in which keys are the "global" names of the source files and
|
|
|
|
|
* value is object containing content of corresponding file with under key 'content' |
|
|
|
|
* @param isRoot True, If file is a root test contract file which is getting processed, not an imported file |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
function processFile(filePath: string, sources: SrcIfc, isRoot: boolean = false) { |
|
|
|
|
const importRegEx: RegExp = /import ['"](.+?)['"];/g; |
|
|
|
|
let group: RegExpExecArray| null = null; |
|
|
|
|
const isFileAlreadyInSources: boolean = Object.keys(sources).includes(filePath) |
|
|
|
|
|
|
|
|
|
// Return if file is a remix test file or already processed
|
|
|
|
|
if(isRemixTestFile(filePath) || isFileAlreadyInSources) |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
let content: string = fs.readFileSync(filePath, { encoding: 'utf-8' }); |
|
|
|
|
const testFileImportRegEx: RegExp = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm |
|
|
|
|
|
|
|
|
|
// import 'remix_tests.sol', if file is a root test contract file and doesn't already have it
|
|
|
|
|
if (isRoot && filePath.includes('_test.sol') && regexIndexOf(content, testFileImportRegEx) < 0) { |
|
|
|
|
const includeTestLibs: string = '\nimport \'remix_tests.sol\';\n' |
|
|
|
|
content = includeTestLibs.concat(content) |
|
|
|
|
} |
|
|
|
|
sources[filePath] = {content}; |
|
|
|
|
importRegEx.exec(''); // Resetting state of RegEx
|
|
|
|
|
|
|
|
|
|
// Process each 'import' in file content
|
|
|
|
|
while (group = importRegEx.exec(content)) { |
|
|
|
|
const importedFile: string = group[1]; |
|
|
|
|
const importedFilePath: string = path.join(path.dirname(filePath), importedFile); |
|
|
|
|
processFile(importedFilePath, sources) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const userAgent = (typeof (navigator) !== 'undefined') && navigator.userAgent ? navigator.userAgent.toLowerCase() : '-' |
|
|
|
|
const isBrowser = !(typeof (window) === 'undefined' || userAgent.indexOf(' electron/') > -1) |
|
|
|
|
|
|
|
|
|
// TODO: replace this with remix's own compiler code
|
|
|
|
|
export function compileFileOrFiles(filename: string, isDirectory: boolean, opts: any, cb: Function) { |
|
|
|
|
let compiler: any |
|
|
|
|
let accounts = opts.accounts || [] |
|
|
|
|
const sources = { |
|
|
|
|
const accounts: string[] = opts.accounts || [] |
|
|
|
|
const sources: SrcIfc = { |
|
|
|
|
'tests.sol': { content: require('../sol/tests.sol.js') }, |
|
|
|
|
'remix_tests.sol': { content: require('../sol/tests.sol.js') }, |
|
|
|
|
'remix_accounts.sol': { content: writeTestAccountsContract(accounts) } |
|
|
|
|
} |
|
|
|
|
const filepath = (isDirectory ? filename : path.dirname(filename)) |
|
|
|
|
// TODO: for now assumes filepath dir contains all tests, later all this
|
|
|
|
|
// should be replaced with remix's & browser solidity compiler code
|
|
|
|
|
|
|
|
|
|
// This logic is wrong
|
|
|
|
|
// We should only look into current file if a full file name with path is given
|
|
|
|
|
// We should only walk through directory if a directory name is passed
|
|
|
|
|
const filepath: string = (isDirectory ? filename : path.dirname(filename)) |
|
|
|
|
try { |
|
|
|
|
// walkSync only if it is a directory
|
|
|
|
|
fs.walkSync(filepath, (foundpath: string) => { |
|
|
|
|
// only process .sol files
|
|
|
|
|
if (foundpath.split('.').pop() === 'sol') { |
|
|
|
|
let c = fs.readFileSync(foundpath).toString() |
|
|
|
|
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm |
|
|
|
|
let includeTestLibs = '\nimport \'remix_tests.sol\';\n' |
|
|
|
|
if (foundpath.indexOf('_test.sol') > 0 && regexIndexOf(c, s) < 0) { |
|
|
|
|
c = includeTestLibs.concat(c) |
|
|
|
|
} |
|
|
|
|
sources[foundpath] = { content: c } |
|
|
|
|
if(!isDirectory && fs.existsSync(filename)) { |
|
|
|
|
if (filename.split('.').pop() === 'sol') { |
|
|
|
|
processFile(filename, sources, true) |
|
|
|
|
} else { |
|
|
|
|
throw new Error('Not a solidity file') |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} else { |
|
|
|
|
// walkSync only if it is a directory
|
|
|
|
|
fs.walkSync(filepath, (foundpath: string) => { |
|
|
|
|
// only process .sol files
|
|
|
|
|
if (foundpath.split('.').pop() === 'sol') { |
|
|
|
|
processFile(foundpath, sources, true) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
throw e |
|
|
|
|
} finally { |
|
|
|
@ -85,19 +130,20 @@ export function compileFileOrFiles(filename: string, isDirectory: boolean, opts: |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export function compileContractSources(sources: SrcIfc, versionUrl: any, usingWorker: any, importFileCb: any, opts: any, cb: Function) { |
|
|
|
|
export function compileContractSources(sources: SrcIfc, versionUrl: any, usingWorker: boolean, importFileCb: any, opts: any, cb: Function) { |
|
|
|
|
let compiler, filepath: string |
|
|
|
|
let accounts = opts.accounts || [] |
|
|
|
|
const accounts: string[] = opts.accounts || [] |
|
|
|
|
// Iterate over sources keys. Inject test libraries. Inject test library import statements.
|
|
|
|
|
if (!('remix_tests.sol' in sources) && !('tests.sol' in sources)) { |
|
|
|
|
sources['remix_tests.sol'] = { content: require('../sol/tests.sol.js') } |
|
|
|
|
sources['remix_accounts.sol'] = { content: writeTestAccountsContract(accounts) } |
|
|
|
|
} |
|
|
|
|
const s = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm |
|
|
|
|
let includeTestLibs = '\nimport \'remix_tests.sol\';\n' |
|
|
|
|
const testFileImportRegEx: RegExp = /^(import)\s['"](remix_tests.sol|tests.sol)['"];/gm |
|
|
|
|
|
|
|
|
|
let includeTestLibs: string = '\nimport \'remix_tests.sol\';\n' |
|
|
|
|
for (let file in sources) { |
|
|
|
|
const c = sources[file].content |
|
|
|
|
if (file.indexOf('_test.sol') > 0 && c && regexIndexOf(c, s) < 0) { |
|
|
|
|
const c: string = sources[file].content |
|
|
|
|
if (file.includes('_test.sol') && c && regexIndexOf(c, testFileImportRegEx) < 0) { |
|
|
|
|
sources[file].content = includeTestLibs.concat(c) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|