diff options
author | Anders-T | 0x80.eth <95024805+anders-torbjornsen@users.noreply.github.com> | 2022-04-26 03:20:13 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-26 04:20:13 +0200 |
commit | fb35d64a92d2f4c2dcf0109ddaf1b999563a0b3c (patch) | |
tree | 24abc9ecca97d68b958ba9d698b2841e0166a0df /lib/compilers/solidity.js | |
parent | 21b764f392e4b1062e61ec910c590f3dfba4d544 (diff) | |
download | compiler-explorer-fb35d64a92d2f4c2dcf0109ddaf1b999563a0b3c.tar.gz compiler-explorer-fb35d64a92d2f4c2dcf0109ddaf1b999563a0b3c.zip |
Fix Solidity compilers and line numbers in versions 0.4.x - 0.8.x (#3561)gh-2523
* fixing compilers 0.4.x - 0.8.x
* update contributors file
Diffstat (limited to 'lib/compilers/solidity.js')
-rw-r--r-- | lib/compilers/solidity.js | 119 |
1 files changed, 84 insertions, 35 deletions
diff --git a/lib/compilers/solidity.js b/lib/compilers/solidity.js index 383177ff0..fd926742d 100644 --- a/lib/compilers/solidity.js +++ b/lib/compilers/solidity.js @@ -46,7 +46,7 @@ export class SolidityCompiler extends BaseCompiler { return [ // We use --combined-json instead of `--asm-json` to have compacted json '--combined-json', - 'asm,ast,generated-sources,generated-sources-runtime', + this.compiler.semver.split('.')[1] < 8 ? 'asm,ast' : 'asm,ast,generated-sources,generated-sources-runtime', '-o', 'contracts', ]; @@ -79,6 +79,9 @@ export class SolidityCompiler extends BaseCompiler { return line; }); + let compilerVersion = {}; + [compilerVersion.major, compilerVersion.minor, compilerVersion.patch] = this.compiler.semver.split('.'); + const asm = JSON.parse(result.asm); return { asm: Object.entries(asm.contracts) @@ -92,37 +95,73 @@ export class SolidityCompiler extends BaseCompiler { // tags (jumpdests) to show what function they're // part of. here we parse the AST so we know what // range of characters belongs to each function. - const contractFunctions = asm.sources[sourceName].AST.nodes - .find(node => { - return node.nodeType === 'ContractDefinition' && node.name === contractName; - }) - .nodes.filter(node => { - return node.nodeType === 'FunctionDefinition'; - }) - .map(node => { - const [begin, length] = node.src.split(':').map(x => parseInt(x)); - - let name = node.kind === 'constructor' ? 'constructor' : node.name; - - // encode the args into the name so we can - // differentiate between overloads - if (node.parameters.parameters.length > 0) { - name += - '_' + - node.parameters.parameters - .map(paramNode => { - return paramNode.typeName.name; - }) - .join('_'); - } + let contractFunctions; + // the layout of this JSON has changed between versions... + if (compilerVersion.major === 0 && compilerVersion.minor < 8) { + contractFunctions = asm.sources[sourceName].AST.children + .find(node => { + return node.name === 'ContractDefinition' && node.attributes.name === contractName; + }) + .children.filter(node => { + return node.name === 'FunctionDefinition'; + }) + .map(node => { + const [begin, length] = node.src.split(':').map(x => parseInt(x)); - return { - name: name, - begin: begin, - end: begin + length, - tagCount: 0, - }; - }); + let name = node.attributes.isConstructor ? 'constructor' : node.attributes.name; + + // encode the args into the name so we can + // differentiate between overloads + if (node.children[0].children.length > 0) { + name += + '_' + + node.children[0].children + .map(paramNode => { + return paramNode.attributes.type; + }) + .join('_'); + } + + return { + name: name, + begin: begin, + end: begin + length, + tagCount: 0, + }; + }); + } else { + contractFunctions = asm.sources[sourceName].AST.nodes + .find(node => { + return node.nodeType === 'ContractDefinition' && node.name === contractName; + }) + .nodes.filter(node => { + return node.nodeType === 'FunctionDefinition'; + }) + .map(node => { + const [begin, length] = node.src.split(':').map(x => parseInt(x)); + + let name = node.kind === 'constructor' ? 'constructor' : node.name; + + // encode the args into the name so we can + // differentiate between overloads + if (node.parameters.parameters.length > 0) { + name += + '_' + + node.parameters.parameters + .map(paramNode => { + return paramNode.typeName.name; + }) + .join('_'); + } + + return { + name: name, + begin: begin, + end: begin + length, + tagCount: 0, + }; + }); + } // solc generates some code, for things like detecting // and reverting if a multiplication results in @@ -143,11 +182,17 @@ export class SolidityCompiler extends BaseCompiler { return generatedSources; }; + // (0.8.x onwards only!) // there are two sets of generated sources, one for the code which deploys // the contract (i.e. the constructor) 'generated-sources', and the code // which is deployed and stored on-chain 'generated-sources-runtime' - const generatedSources = processGeneratedSources(data['generated-sources']); - const generatedSourcesRuntime = processGeneratedSources(data['generated-sources-runtime']); + const hasGeneratedSources = compilerVersion.major > 0 || compilerVersion.minor > 7; + const generatedSources = hasGeneratedSources + ? processGeneratedSources(data['generated-sources']) + : {}; + const generatedSourcesRuntime = hasGeneratedSources + ? processGeneratedSources(data['generated-sources-runtime']) + : {}; const processOpcodes = (opcodes, indent, generatedSources) => { // first iterate the opcodes to find all the tags, @@ -176,8 +221,12 @@ export class SolidityCompiler extends BaseCompiler { for (const opcode of opcodes) { // source 0 is the .sol file the user is // editing, everything else is generated - // sources - if (opcode.source === 0) { + // sources (from version 0.8.x onwards). + // if source is undefined, then this is + // a compiler version which doesn't + // provide one (< 0.6.x), but we can + // infer 0 in this case. + if (opcode.source === 0 || opcode.source === undefined) { opcode.line = charToLine[opcode.begin]; processPossibleTagOpcode(opcode, contractFunctions); |