diff --git a/remix-analyzer/test/analysis/astBlocks/assignment.json b/remix-analyzer/test/analysis/astBlocks/assignment.json new file mode 100644 index 0000000000..1e368adef7 --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/assignment.json @@ -0,0 +1,62 @@ +{ + "attributes": { + "operator": "=", + "type": "uint256" + }, + "children": [ + { + "attributes": { + "type": "uint256" + }, + "children": [ + { + "attributes": { + "type": "mapping(address => uint256)", + "value": "c" + }, + "id": 61, + "name": "Identifier", + "src": "873:1:0" + }, + { + "attributes": { + "member_name": "sender", + "type": "address" + }, + "children": [ + { + "attributes": { + "type": "msg", + "value": "msg" + }, + "id": 62, + "name": "Identifier", + "src": "875:3:0" + } + ], + "id": 63, + "name": "MemberAccess", + "src": "875:10:0" + } + ], + "id": 64, + "name": "IndexAccess", + "src": "873:13:0" + }, + { + "attributes": { + "hexvalue": "30", + "subdenomination": null, + "token": null, + "type": "int_const 0", + "value": "0" + }, + "id": 65, + "name": "Literal", + "src": "889:1:0" + } + ], + "id": 66, + "name": "Assignment", + "src": "873:17:0" + } \ No newline at end of file diff --git a/remix-analyzer/test/analysis/astBlocks/doWhileLoopNode.json b/remix-analyzer/test/analysis/astBlocks/doWhileLoopNode.json new file mode 100644 index 0000000000..4b5d880707 --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/doWhileLoopNode.json @@ -0,0 +1,204 @@ +{ + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "commonType": + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "operator": "<", + "type": "bool" + }, + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 69, + "type": "uint256", + "value": "i" + }, + "id": 82, + "name": "Identifier", + "src": "592:1:0" + }, + { + "attributes": + { + "argumentTypes": null, + "hexvalue": "3130", + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "subdenomination": null, + "token": "number", + "type": "int_const 10", + "value": "10" + }, + "id": 83, + "name": "Literal", + "src": "596:2:0" + } + ], + "id": 84, + "name": "BinaryOperation", + "src": "592:6:0" + }, + { + "children": + [ + { + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "isConstant": false, + "isLValue": false, + "isPure": false, + "isStructConstructorCall": false, + "lValueRequested": false, + "names": + [ + null + ], + "type": "uint256", + "type_conversion": false + }, + "children": + [ + { + "attributes": + { + "argumentTypes": + [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "member_name": "push", + "referencedDeclaration": null, + "type": "function (uint256) returns (uint256)" + }, + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 4, + "type": "uint256[] storage ref", + "value": "array" + }, + "id": 72, + "name": "Identifier", + "src": "544:5:0" + } + ], + "id": 74, + "name": "MemberAccess", + "src": "544:10:0" + }, + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 69, + "type": "uint256", + "value": "i" + }, + "id": 75, + "name": "Identifier", + "src": "555:1:0" + } + ], + "id": 76, + "name": "FunctionCall", + "src": "544:13:0" + } + ], + "id": 77, + "name": "ExpressionStatement", + "src": "544:13:0" + }, + { + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "operator": "++", + "prefix": false, + "type": "uint256" + }, + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 69, + "type": "uint256", + "value": "i" + }, + "id": 78, + "name": "Identifier", + "src": "571:1:0" + } + ], + "id": 79, + "name": "UnaryOperation", + "src": "571:3:0" + } + ], + "id": 80, + "name": "ExpressionStatement", + "src": "571:3:0" + } + ], + "id": 81, + "name": "Block", + "src": "530:55:0" + } + ], + "id": 85, + "name": "DoWhileStatement", + "src": "528:72:0" + } \ No newline at end of file diff --git a/remix-analyzer/test/analysis/astBlocks/externalDirect.json b/remix-analyzer/test/analysis/astBlocks/externalDirect.json new file mode 100644 index 0000000000..ceb1bf2cd2 --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/externalDirect.json @@ -0,0 +1,20 @@ +{ + "attributes": { + "member_name": "info", + "type": "function () payable external returns (uint256)" + }, + "children": [ + { + "attributes": { + "type": "contract InfoFeed", + "value": "f" + }, + "id": 30, + "name": "Identifier", + "src": "405:1:0" + } + ], + "id": 32, + "name": "MemberAccess", + "src": "405:6:0" +} \ No newline at end of file diff --git a/remix-analyzer/test/analysis/astBlocks/forLoopNode.json b/remix-analyzer/test/analysis/astBlocks/forLoopNode.json new file mode 100644 index 0000000000..214467cbae --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/forLoopNode.json @@ -0,0 +1,264 @@ +{ + "children": + [ + { + "attributes": + { + "assignments": + [ + 21 + ] + }, + "children": + [ + { + "attributes": + { + "constant": false, + "name": "i", + "scope": 39, + "stateVariable": false, + "storageLocation": "default", + "type": "uint256", + "value": null, + "visibility": "internal" + }, + "children": + [ + { + "attributes": + { + "name": "uint", + "type": "uint256" + }, + "id": 20, + "name": "ElementaryTypeName", + "src": "207:4:0" + } + ], + "id": 21, + "name": "VariableDeclaration", + "src": "207:6:0" + }, + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 17, + "type": "uint256", + "value": "index" + }, + "id": 22, + "name": "Identifier", + "src": "216:5:0" + } + ], + "id": 23, + "name": "VariableDeclarationStatement", + "src": "207:14:0" + }, + { + "attributes": + { + "argumentTypes": null, + "commonType": + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "operator": "<", + "type": "bool" + }, + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 21, + "type": "uint256", + "value": "i" + }, + "id": 24, + "name": "Identifier", + "src": "223:1:0" + }, + { + "attributes": + { + "argumentTypes": null, + "hexvalue": "3130", + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "subdenomination": null, + "token": "number", + "type": "int_const 10", + "value": "10" + }, + "id": 25, + "name": "Literal", + "src": "227:2:0" + } + ], + "id": 26, + "name": "BinaryOperation", + "src": "223:6:0" + }, + { + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "operator": "++", + "prefix": false, + "type": "uint256" + }, + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 21, + "type": "uint256", + "value": "i" + }, + "id": 27, + "name": "Identifier", + "src": "231:1:0" + } + ], + "id": 28, + "name": "UnaryOperation", + "src": "231:3:0" + } + ], + "id": 29, + "name": "ExpressionStatement", + "src": "231:3:0" + }, + { + "children": + [ + { + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "isConstant": false, + "isLValue": false, + "isPure": false, + "isStructConstructorCall": false, + "lValueRequested": false, + "names": + [ + null + ], + "type": "uint256", + "type_conversion": false + }, + "children": + [ + { + "attributes": + { + "argumentTypes": + [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "member_name": "push", + "referencedDeclaration": null, + "type": "function (uint256) returns (uint256)" + }, + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 4, + "type": "uint256[] storage ref", + "value": "array" + }, + "id": 30, + "name": "Identifier", + "src": "250:5:0" + } + ], + "id": 32, + "name": "MemberAccess", + "src": "250:10:0" + }, + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 21, + "type": "uint256", + "value": "i" + }, + "id": 33, + "name": "Identifier", + "src": "261:1:0" + } + ], + "id": 34, + "name": "FunctionCall", + "src": "250:13:0" + } + ], + "id": 35, + "name": "ExpressionStatement", + "src": "250:13:0" + } + ], + "id": 36, + "name": "Block", + "src": "236:38:0" + } + ], + "id": 37, + "name": "ForStatement", + "src": "202:72:0" + } \ No newline at end of file diff --git a/remix-analyzer/test/analysis/astBlocks/index.js b/remix-analyzer/test/analysis/astBlocks/index.js new file mode 100644 index 0000000000..35b468b3f2 --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/index.js @@ -0,0 +1,12 @@ +module.exports = { + localCall: require('./localCall.json'), + thisLocalCall: require('./thisLocalCall.json'), + libCall: require('./libCall.json'), + externalDirect: require('./externalDirect.json'), + superLocal: require('./superLocal.json'), + assignment: require('./assignment.json'), + inlineAssembly: require('./inlineAssembly.json'), + forLoopNode: require('./forLoopNode.json'), + whileLoopNode: require('./whileLoopNode.json'), + doWhileLoopNode: require('./doWhileLoopNode.json') +} diff --git a/remix-analyzer/test/analysis/astBlocks/inlineAssembly.json b/remix-analyzer/test/analysis/astBlocks/inlineAssembly.json new file mode 100644 index 0000000000..6136ab3060 --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/inlineAssembly.json @@ -0,0 +1,7 @@ +{ + "children": [ + ], + "id": 21, + "name": "InlineAssembly", + "src": "809:41:0" + } \ No newline at end of file diff --git a/remix-analyzer/test/analysis/astBlocks/libCall.json b/remix-analyzer/test/analysis/astBlocks/libCall.json new file mode 100644 index 0000000000..ebb7cfbbd1 --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/libCall.json @@ -0,0 +1,16 @@ +{ + "attributes": { + "member_name": "insert", + "type": "function (struct Set.Data storage pointer,uint256) returns (bool)" + }, + "children": [ + { + "attributes": { + "type": "type(library Set)", + "value": "Set" + }, + "name": "Identifier" + } + ], + "name": "MemberAccess" +} \ No newline at end of file diff --git a/remix-analyzer/test/analysis/astBlocks/localCall.json b/remix-analyzer/test/analysis/astBlocks/localCall.json new file mode 100644 index 0000000000..35372abe41 --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/localCall.json @@ -0,0 +1,29 @@ +{ + "attributes": { + "type": "tuple()", + "type_conversion": false + }, + "children": [ + { + "attributes": { + "type": "function (struct Ballot.Voter storage pointer)", + "value": "bli" + }, + "id": 37, + "name": "Identifier", + "src": "540:3:0" + }, + { + "attributes": { + "type": "struct Ballot.Voter storage pointer", + "value": "x" + }, + "id": 38, + "name": "Identifier", + "src": "544:1:0" + } + ], + "id": 39, + "name": "FunctionCall", + "src": "540:6:0" + } \ No newline at end of file diff --git a/remix-analyzer/test/analysis/astBlocks/superLocal.json b/remix-analyzer/test/analysis/astBlocks/superLocal.json new file mode 100644 index 0000000000..7a5b8b7bdf --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/superLocal.json @@ -0,0 +1,16 @@ +{ + "attributes": { + "member_name": "duper", + "type": "function ()" + }, + "children": [ + { + "attributes": { + "type": "contract super a", + "value": "super" + }, + "name": "Identifier" + } + ], + "name": "MemberAccess" +} \ No newline at end of file diff --git a/remix-analyzer/test/analysis/astBlocks/thisLocalCall.json b/remix-analyzer/test/analysis/astBlocks/thisLocalCall.json new file mode 100644 index 0000000000..df88de3247 --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/thisLocalCall.json @@ -0,0 +1,10 @@ +{ + "name": "MemberAccess", + "children": [ { + "attributes": { + "value": "this", + "type": "contract test" }, + "name": "Identifier" } ], + "attributes": { + "value": "b", + "type": "function (bytes32,address) returns (bool)" } } \ No newline at end of file diff --git a/remix-analyzer/test/analysis/astBlocks/whileLoopNode.json b/remix-analyzer/test/analysis/astBlocks/whileLoopNode.json new file mode 100644 index 0000000000..85dcb5a327 --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/whileLoopNode.json @@ -0,0 +1,204 @@ +{ + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "commonType": + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "operator": "<", + "type": "bool" + }, + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 45, + "type": "uint256", + "value": "i" + }, + "id": 48, + "name": "Identifier", + "src": "372:1:0" + }, + { + "attributes": + { + "argumentTypes": null, + "hexvalue": "3130", + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "subdenomination": null, + "token": "number", + "type": "int_const 10", + "value": "10" + }, + "id": 49, + "name": "Literal", + "src": "376:2:0" + } + ], + "id": 50, + "name": "BinaryOperation", + "src": "372:6:0" + }, + { + "children": + [ + { + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "isConstant": false, + "isLValue": false, + "isPure": false, + "isStructConstructorCall": false, + "lValueRequested": false, + "names": + [ + null + ], + "type": "uint256", + "type_conversion": false + }, + "children": + [ + { + "attributes": + { + "argumentTypes": + [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "member_name": "push", + "referencedDeclaration": null, + "type": "function (uint256) returns (uint256)" + }, + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 4, + "type": "uint256[] storage ref", + "value": "array" + }, + "id": 51, + "name": "Identifier", + "src": "394:5:0" + } + ], + "id": 53, + "name": "MemberAccess", + "src": "394:10:0" + }, + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 45, + "type": "uint256", + "value": "i" + }, + "id": 54, + "name": "Identifier", + "src": "405:1:0" + } + ], + "id": 55, + "name": "FunctionCall", + "src": "394:13:0" + } + ], + "id": 56, + "name": "ExpressionStatement", + "src": "394:13:0" + }, + { + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "operator": "++", + "prefix": false, + "type": "uint256" + }, + "children": + [ + { + "attributes": + { + "argumentTypes": null, + "overloadedDeclarations": + [ + null + ], + "referencedDeclaration": 45, + "type": "uint256", + "value": "i" + }, + "id": 57, + "name": "Identifier", + "src": "421:1:0" + } + ], + "id": 58, + "name": "UnaryOperation", + "src": "421:3:0" + } + ], + "id": 59, + "name": "ExpressionStatement", + "src": "421:3:0" + } + ], + "id": 60, + "name": "Block", + "src": "380:55:0" + } + ], + "id": 61, + "name": "WhileStatement", + "src": "365:70:0" + } \ No newline at end of file diff --git a/remix-analyzer/test/analysis/staticAnalysisCommon-test.js b/remix-analyzer/test/analysis/staticAnalysisCommon-test.js index b1b3b9e08b..9586c06e87 100644 --- a/remix-analyzer/test/analysis/staticAnalysisCommon-test.js +++ b/remix-analyzer/test/analysis/staticAnalysisCommon-test.js @@ -1,6 +1,7 @@ var test = require('tape') - var common = require('../../src/solidity-analyzer/modules/staticAnalysisCommon') +var { localCall, thisLocalCall, libCall, externalDirect, superLocal, assignment, + inlineAssembly, forLoopNode, whileLoopNode, doWhileLoopNode } = require('./astBlocks') function escapeRegExp (str) { return str.replace(/[-[\]/{}()+?.\\^$|]/g, '\\$&') @@ -157,1646 +158,420 @@ test('staticAnalysisCommon.getType', function (t) { test('staticAnalysisCommon.getFunctionCallType', function (t) { t.plan(5) - var localCall = { - 'attributes': { - 'type': 'tuple()', - 'type_conversion': false - }, + t.equal(common.getFunctionCallType(libCall), 'function (struct Set.Data storage pointer,uint256) returns (bool)', 'this lib call returns correct type') + t.equal(common.getFunctionCallType(thisLocalCall), 'function (bytes32,address) returns (bool)', 'this local call returns correct type') + t.equal(common.getFunctionCallType(externalDirect), 'function () payable external returns (uint256)', 'external direct call returns correct type') + t.equal(common.getFunctionCallType(localCall), 'function (struct Ballot.Voter storage pointer)', 'local call returns correct type') + t.throws(() => common.getFunctionCallType({ name: 'MemberAccess' }), undefined, 'throws on wrong type') +}) + +test('staticAnalysisCommon.getEffectedVariableName', function (t) { + t.plan(3) + t.throws(() => common.getEffectedVariableName(inlineAssembly), 'staticAnalysisCommon.js: not an effect Node or inline assembly', 'get from inline assembly should throw') + t.ok(common.getEffectedVariableName(assignment) === 'c', 'get right name for assignment') + t.throws(() => common.getEffectedVariableName({ name: 'MemberAccess' }), undefined, 'should throw on all other nodes') +}) + +test('staticAnalysisCommon.getLocalCallName', function (t) { + t.plan(3) + t.ok(common.getLocalCallName(localCall) === 'bli', 'getLocal call name from node') + t.throws(() => common.getLocalCallName(externalDirect), undefined, 'throws on other nodes') + t.throws(() => common.getLocalCallName(thisLocalCall), undefined, 'throws on other nodes') +}) + +test('staticAnalysisCommon.getThisLocalCallName', function (t) { + t.plan(3) + t.ok(common.getThisLocalCallName(thisLocalCall) === 'b', 'get this Local call name from node') + t.throws(() => common.getThisLocalCallName(externalDirect), undefined, 'throws on other nodes') + t.throws(() => common.getThisLocalCallName(localCall), undefined, 'throws on other nodes') +}) + +test('staticAnalysisCommon.getSuperLocalCallName', function (t) { + t.plan(4) + t.equal(common.getSuperLocalCallName(superLocal), 'duper', 'get local name from super local call') + t.throws(() => common.getSuperLocalCallName(thisLocalCall), 'throws on other nodes') + t.throws(() => common.getSuperLocalCallName(externalDirect), undefined, 'throws on other nodes') + t.throws(() => common.getSuperLocalCallName(localCall), undefined, 'throws on other nodes') +}) + +test('staticAnalysisCommon.getExternalDirectCallContractName', function (t) { + t.plan(3) + t.ok(common.getExternalDirectCallContractName(externalDirect) === 'InfoFeed', 'external direct call contract name from node') + t.throws(() => common.getExternalDirectCallContractName(thisLocalCall), undefined, 'throws on other nodes') + t.throws(() => common.getExternalDirectCallContractName(localCall), undefined, 'throws on other nodes') +}) + +test('staticAnalysisCommon.getThisLocalCallContractName', function (t) { + t.plan(3) + t.ok(common.getThisLocalCallContractName(thisLocalCall) === 'test', 'this local call contract name from node') + t.throws(() => common.getThisLocalCallContractName(localCall), undefined, 'throws on other nodes') + t.throws(() => common.getThisLocalCallContractName(externalDirect), undefined, 'throws on other nodes') +}) + +test('staticAnalysisCommon.getExternalDirectCallMemberName', function (t) { + t.plan(3) + t.ok(common.getExternalDirectCallMemberName(externalDirect) === 'info', 'external direct call name from node') + t.throws(() => common.getExternalDirectCallMemberName(thisLocalCall), undefined, 'throws on other nodes') + t.throws(() => common.getExternalDirectCallMemberName(localCall), undefined, 'throws on other nodes') +}) + +test('staticAnalysisCommon.getContractName', function (t) { + t.plan(2) + var contract = { name: 'ContractDefinition', attributes: { name: 'baz' } } + t.ok(common.getContractName(contract) === 'baz', 'returns right contract name') + t.throws(() => common.getContractName({ name: 'InheritanceSpecifier' }), undefined, 'throws on other nodes') +}) + +test('staticAnalysisCommon.getFunctionDefinitionName', function (t) { + t.plan(2) + var func = { name: 'FunctionDefinition', attributes: { name: 'foo' } } + t.ok(common.getFunctionDefinitionName(func) === 'foo', 'returns right contract name') + t.throws(() => common.getFunctionDefinitionName({ name: 'InlineAssembly' }), undefined, 'throws on other nodes') +}) + +test('staticAnalysisCommon.getInheritsFromName', function (t) { + t.plan(2) + var inh = { 'children': [ { 'attributes': { - 'type': 'function (struct Ballot.Voter storage pointer)', - 'value': 'bli' - }, - 'id': 37, - 'name': 'Identifier', - 'src': '540:3:0' - }, - { - 'attributes': { - 'type': 'struct Ballot.Voter storage pointer', - 'value': 'x' - }, - 'id': 38, - 'name': 'Identifier', - 'src': '544:1:0' - } - ], - 'id': 39, - 'name': 'FunctionCall', - 'src': '540:6:0' - } - var thisLocalCall = { name: 'MemberAccess', children: [ { attributes: { value: 'this', type: 'contract test' }, name: 'Identifier' } ], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } } - var externalDirect = { - attributes: { - member_name: 'info', - type: 'function () payable external returns (uint256)' - }, - children: [ - { - attributes: { - type: 'contract InfoFeed', - value: 'f' + 'name': 'r' }, - id: 30, - name: 'Identifier', - src: '405:1:0' + 'id': 7, + 'name': 'UserDefinedTypeName', + 'src': '84:1:0' } ], - id: 32, - name: 'MemberAccess', - src: '405:6:0' + 'id': 8, + 'name': 'InheritanceSpecifier', + 'src': '84:1:0' } - var libCall = { + t.ok(common.getInheritsFromName(inh) === 'r', 'returns right contract name') + t.throws(() => common.getInheritsFromName({ name: 'ElementaryTypeName' }), undefined, 'throws on other nodes') +}) + +test('staticAnalysisCommon.getDeclaredVariableName', function (t) { + t.plan(2) + var node1 = { 'attributes': { - 'member_name': 'insert', - 'type': 'function (struct Set.Data storage pointer,uint256) returns (bool)' + 'name': 'x', + 'type': 'struct Ballot.Voter storage pointer' }, 'children': [ { 'attributes': { - 'type': 'type(library Set)', - 'value': 'Set' + 'name': 'Voter' }, - 'name': 'Identifier' + 'id': 43, + 'name': 'UserDefinedTypeName', + 'src': '604:5:0' } ], - 'name': 'MemberAccess' + 'id': 44, + 'name': 'VariableDeclaration', + 'src': '604:15:0' } - t.equal(common.getFunctionCallType(libCall), 'function (struct Set.Data storage pointer,uint256) returns (bool)', 'this lib call returns correct type') - t.equal(common.getFunctionCallType(thisLocalCall), 'function (bytes32,address) returns (bool)', 'this local call returns correct type') - t.equal(common.getFunctionCallType(externalDirect), 'function () payable external returns (uint256)', 'external direct call returns correct type') - t.equal(common.getFunctionCallType(localCall), 'function (struct Ballot.Voter storage pointer)', 'local call returns correct type') - t.throws(() => common.getFunctionCallType({ name: 'MemberAccess' }), undefined, 'throws on wrong type') + t.ok(common.getDeclaredVariableName(node1) === 'x', 'extract right variable name') + node1.name = 'FunctionCall' + t.throws(() => common.getDeclaredVariableName(node1) === 'x', undefined, 'throw if wrong node') }) -test('staticAnalysisCommon.getEffectedVariableName', function (t) { - t.plan(3) - var assignment = { +test('staticAnalysisCommon.getStateVariableDeclarationsFormContractNode', function (t) { + t.plan(4) + var contract = { 'attributes': { - 'operator': '=', - 'type': 'uint256' + 'fullyImplemented': true, + 'isLibrary': false, + 'linearizedBaseContracts': [ + 274 + ], + 'name': 'Ballot' }, 'children': [ { 'attributes': { - 'type': 'uint256' + 'name': 'Voter' + }, + 'children': [], + 'name': 'StructDefinition' + }, + { + 'attributes': { + 'name': 'Proposal' + }, + 'children': [], + 'name': 'StructDefinition' + }, + { + 'attributes': { + 'name': 'chairperson', + 'type': 'address' }, 'children': [ { 'attributes': { - 'type': 'mapping(address => uint256)', - 'value': 'c' + 'name': 'address' }, - 'id': 61, - 'name': 'Identifier', - 'src': '873:1:0' - }, + 'name': 'ElementaryTypeName' + } + ], + 'name': 'VariableDeclaration' + }, + { + 'attributes': { + 'name': 'voters', + 'type': 'mapping(address => struct Ballot.Voter storage ref)' + }, + 'children': [ { - 'attributes': { - 'member_name': 'sender', - 'type': 'address' - }, 'children': [ { 'attributes': { - 'type': 'msg', - 'value': 'msg' + 'name': 'address' }, - 'id': 62, - 'name': 'Identifier', - 'src': '875:3:0' + 'name': 'ElementaryTypeName' + }, + { + 'attributes': { + 'name': 'Voter' + }, + 'name': 'UserDefinedTypeName' } ], - 'id': 63, - 'name': 'MemberAccess', - 'src': '875:10:0' + 'name': 'Mapping' } ], - 'id': 64, - 'name': 'IndexAccess', - 'src': '873:13:0' + 'name': 'VariableDeclaration' }, { 'attributes': { - 'hexvalue': '30', - 'subdenomination': null, - 'token': null, - 'type': 'int_const 0', - 'value': '0' + 'name': 'proposals', + 'type': 'struct Ballot.Proposal storage ref[] storage ref' }, - 'id': 65, - 'name': 'Literal', - 'src': '889:1:0' - } - ], - 'id': 66, - 'name': 'Assignment', - 'src': '873:17:0' - } - var inlineAssembly = { - 'children': [ - ], - 'id': 21, - 'name': 'InlineAssembly', - 'src': '809:41:0' - } - t.throws(() => common.getEffectedVariableName(inlineAssembly), 'staticAnalysisCommon.js: not an effect Node or inline assembly', 'get from inline assembly should throw') - t.ok(common.getEffectedVariableName(assignment) === 'c', 'get right name for assignment') - t.throws(() => common.getEffectedVariableName({ name: 'MemberAccess' }), undefined, 'should throw on all other nodes') -}) - -test('staticAnalysisCommon.getLocalCallName', function (t) { - t.plan(3) - var localCall = { - 'attributes': { - 'type': 'tuple()', - 'type_conversion': false - }, - 'children': [ + 'children': [ + { + 'children': [ + { + 'attributes': { + 'name': 'Proposal' + }, + 'name': 'UserDefinedTypeName' + } + ], + 'name': 'ArrayTypeName' + } + ], + 'name': 'VariableDeclaration' + }, { 'attributes': { - 'type': 'function (struct Ballot.Voter storage pointer)', - 'value': 'bli' + 'constant': false, + 'name': 'Ballot', + 'payable': false, + 'visibility': 'public' }, - 'id': 37, - 'name': 'Identifier', - 'src': '540:3:0' + 'children': [], + 'name': 'FunctionDefinition' }, { 'attributes': { - 'type': 'struct Ballot.Voter storage pointer', - 'value': 'x' - }, - 'id': 38, - 'name': 'Identifier', - 'src': '544:1:0' - } - ], - 'id': 39, - 'name': 'FunctionCall', - 'src': '540:6:0' - } - var thisLocalCall = { name: 'MemberAccess', children: [ { attributes: { value: 'this', type: 'contract test' }, name: 'Identifier' } ], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } } - var externalDirect = { - attributes: { - member_name: 'info', - type: 'function () payable external returns (uint256)' - }, - children: [ - { - attributes: { - type: 'contract InfoFeed', - value: 'f' + 'constant': false, + 'name': 'giveRightToVote', + 'payable': false, + 'visibility': 'public' }, - id: 30, - name: 'Identifier', - src: '405:1:0' + 'children': [], + 'name': 'FunctionDefinition' } ], - id: 32, - name: 'MemberAccess', - src: '405:6:0' + 'name': 'ContractDefinition' } - t.ok(common.getLocalCallName(localCall) === 'bli', 'getLocal call name from node') - t.throws(() => common.getLocalCallName(externalDirect), undefined, 'throws on other nodes') - t.throws(() => common.getLocalCallName(thisLocalCall), undefined, 'throws on other nodes') + var res = common.getStateVariableDeclarationsFormContractNode(contract).map(common.getDeclaredVariableName) + + t.ok(res[0] === 'chairperson', 'var 1 should be ') + t.ok(res[1] === 'voters', 'var 2 should be ') + t.ok(res[2] === 'proposals', 'var 3 should be ') + t.ok(res[3] === undefined, 'var 4 should be undefined') }) -test('staticAnalysisCommon.getThisLocalCallName', function (t) { - t.plan(3) - var localCall = { +test('staticAnalysisCommon.getFunctionOrModifierDefinitionParameterPart', function (t) { + t.plan(2) + var funDef = { 'attributes': { - 'type': 'tuple()', - 'type_conversion': false + 'constant': true, + 'name': 'winnerName', + 'payable': false, + 'visibility': 'public' }, 'children': [ { - 'attributes': { - 'type': 'function (struct Ballot.Voter storage pointer)', - 'value': 'bli' - }, - 'id': 37, - 'name': 'Identifier', - 'src': '540:3:0' + 'children': [ + ], + 'name': 'ParameterList' }, { - 'attributes': { - 'type': 'struct Ballot.Voter storage pointer', - 'value': 'x' - }, - 'id': 38, - 'name': 'Identifier', - 'src': '544:1:0' - } - ], - 'id': 39, - 'name': 'FunctionCall', - 'src': '540:6:0' - } - var thisLocalCall = { name: 'MemberAccess', children: [ { attributes: { value: 'this', type: 'contract test' }, name: 'Identifier' } ], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } } - var externalDirect = { - attributes: { - member_name: 'info', - type: 'function () payable external returns (uint256)' - }, - children: [ + 'children': [], + 'name': 'ParameterList' + }, { - attributes: { - type: 'contract InfoFeed', - value: 'f' - }, - id: 30, - name: 'Identifier', - src: '405:1:0' + 'children': [], + 'name': 'Block' } ], - id: 32, - name: 'MemberAccess', - src: '405:6:0' + 'name': 'FunctionDefinition' } - t.ok(common.getThisLocalCallName(thisLocalCall) === 'b', 'get this Local call name from node') - t.throws(() => common.getThisLocalCallName(externalDirect), undefined, 'throws on other nodes') - t.throws(() => common.getThisLocalCallName(localCall), undefined, 'throws on other nodes') + t.ok(common.helpers.nodeType(common.getFunctionOrModifierDefinitionParameterPart(funDef), 'ParameterList'), 'should return a parameterList') + t.throws(() => common.getFunctionOrModifierDefinitionParameterPart({ name: 'SourceUnit' }), undefined, 'throws on other nodes') }) -test('staticAnalysisCommon.getSuperLocalCallName', function (t) { +test('staticAnalysisCommon.getFunctionCallTypeParameterType', function (t) { t.plan(4) - var superLocal = { + t.ok(common.getFunctionCallTypeParameterType(thisLocalCall) === 'bytes32,address', 'this local call returns correct type') + t.ok(common.getFunctionCallTypeParameterType(externalDirect) === '', 'external direct call returns correct type') + t.ok(common.getFunctionCallTypeParameterType(localCall) === 'struct Ballot.Voter storage pointer', 'local call returns correct type') + t.throws(() => common.getFunctionCallTypeParameterType({ name: 'MemberAccess' }), undefined, 'throws on wrong type') +}) + +test('staticAnalysisCommon.getLibraryCallContractName', function (t) { + t.plan(2) + var node = { 'attributes': { - 'member_name': 'duper', - 'type': 'function ()' + 'member_name': 'insert', + 'type': 'function (struct Set.Data storage pointer,uint256) returns (bool)' }, 'children': [ { 'attributes': { - 'type': 'contract super a', - 'value': 'super' + 'type': 'type(library Set)', + 'value': 'Set' }, 'name': 'Identifier' } ], 'name': 'MemberAccess' } - var localCall = { - 'attributes': { - 'type': 'tuple()', - 'type_conversion': false - }, - 'children': [ - { - 'attributes': { - 'type': 'function (struct Ballot.Voter storage pointer)', - 'value': 'bli' - }, - 'id': 37, - 'name': 'Identifier', - 'src': '540:3:0' - }, - { - 'attributes': { - 'type': 'struct Ballot.Voter storage pointer', - 'value': 'x' - }, - 'id': 38, - 'name': 'Identifier', - 'src': '544:1:0' - } - ], - 'id': 39, - 'name': 'FunctionCall', - 'src': '540:6:0' - } - var thisLocalCall = { name: 'MemberAccess', children: [ { attributes: { value: 'this', type: 'contract test' }, name: 'Identifier' } ], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } } - var externalDirect = { - attributes: { - member_name: 'info', - type: 'function () payable external returns (uint256)' - }, - children: [ - { - attributes: { - type: 'contract InfoFeed', - value: 'f' - }, - id: 30, - name: 'Identifier', - src: '405:1:0' - } - ], - id: 32, - name: 'MemberAccess', - src: '405:6:0' - } - t.equal(common.getSuperLocalCallName(superLocal), 'duper', 'get local name from super local call') - t.throws(() => common.getSuperLocalCallName(thisLocalCall), 'throws on other nodes') - t.throws(() => common.getSuperLocalCallName(externalDirect), undefined, 'throws on other nodes') - t.throws(() => common.getSuperLocalCallName(localCall), undefined, 'throws on other nodes') + t.equal(common.getLibraryCallContractName(node), 'Set', 'should return correct contract name') + t.throws(() => common.getLibraryCallContractName({ name: 'Identifier' }), undefined, 'should throw on wrong node') }) -test('staticAnalysisCommon.getExternalDirectCallContractName', function (t) { - t.plan(3) - var localCall = { - 'attributes': { - 'type': 'tuple()', - 'type_conversion': false - }, - 'children': [ - { - 'attributes': { - 'type': 'function (struct Ballot.Voter storage pointer)', - 'value': 'bli' - }, - 'id': 37, - 'name': 'Identifier', - 'src': '540:3:0' - }, - { - 'attributes': { - 'type': 'struct Ballot.Voter storage pointer', - 'value': 'x' - }, - 'id': 38, - 'name': 'Identifier', - 'src': '544:1:0' - } - ], - 'id': 39, - 'name': 'FunctionCall', - 'src': '540:6:0' - } - var thisLocalCall = { name: 'MemberAccess', children: [ { attributes: { value: 'this', type: 'contract test' }, name: 'Identifier' } ], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } } - var externalDirect = { - attributes: { - member_name: 'info', - type: 'function () payable external returns (uint256)' - }, - children: [ - { - attributes: { - type: 'contract InfoFeed', - value: 'f' - }, - id: 30, - name: 'Identifier', - src: '405:1:0' - } - ], - id: 32, - name: 'MemberAccess', - src: '405:6:0' - } - - t.ok(common.getExternalDirectCallContractName(externalDirect) === 'InfoFeed', 'external direct call contract name from node') - t.throws(() => common.getExternalDirectCallContractName(thisLocalCall), undefined, 'throws on other nodes') - t.throws(() => common.getExternalDirectCallContractName(localCall), undefined, 'throws on other nodes') -}) - -test('staticAnalysisCommon.getThisLocalCallContractName', function (t) { - t.plan(3) - var localCall = { - 'attributes': { - 'type': 'tuple()', - 'type_conversion': false - }, - 'children': [ - { - 'attributes': { - 'type': 'function (struct Ballot.Voter storage pointer)', - 'value': 'bli' - }, - 'id': 37, - 'name': 'Identifier', - 'src': '540:3:0' - }, - { - 'attributes': { - 'type': 'struct Ballot.Voter storage pointer', - 'value': 'x' - }, - 'id': 38, - 'name': 'Identifier', - 'src': '544:1:0' - } - ], - 'id': 39, - 'name': 'FunctionCall', - 'src': '540:6:0' - } - var thisLocalCall = { name: 'MemberAccess', children: [ { attributes: { value: 'this', type: 'contract test' }, name: 'Identifier' } ], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } } - var externalDirect = { - attributes: { - member_name: 'info', - type: 'function () payable external returns (uint256)' - }, - children: [ - { - attributes: { - type: 'contract InfoFeed', - value: 'f' - }, - id: 30, - name: 'Identifier', - src: '405:1:0' - } - ], - id: 32, - name: 'MemberAccess', - src: '405:6:0' - } - t.ok(common.getThisLocalCallContractName(thisLocalCall) === 'test', 'this local call contract name from node') - t.throws(() => common.getThisLocalCallContractName(localCall), undefined, 'throws on other nodes') - t.throws(() => common.getThisLocalCallContractName(externalDirect), undefined, 'throws on other nodes') -}) - -test('staticAnalysisCommon.getExternalDirectCallMemberName', function (t) { - t.plan(3) - var localCall = { - 'attributes': { - 'type': 'tuple()', - 'type_conversion': false - }, - 'children': [ - { - 'attributes': { - 'type': 'function (struct Ballot.Voter storage pointer)', - 'value': 'bli' - }, - 'id': 37, - 'name': 'Identifier', - 'src': '540:3:0' - }, - { - 'attributes': { - 'type': 'struct Ballot.Voter storage pointer', - 'value': 'x' - }, - 'id': 38, - 'name': 'Identifier', - 'src': '544:1:0' - } - ], - 'id': 39, - 'name': 'FunctionCall', - 'src': '540:6:0' - } - var thisLocalCall = { name: 'MemberAccess', children: [ { attributes: { value: 'this', type: 'contract test' }, name: 'Identifier' } ], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } } - var externalDirect = { - attributes: { - member_name: 'info', - type: 'function () payable external returns (uint256)' - }, - children: [ - { - attributes: { - type: 'contract InfoFeed', - value: 'f' - }, - id: 30, - name: 'Identifier', - src: '405:1:0' - } - ], - id: 32, - name: 'MemberAccess', - src: '405:6:0' - } - t.ok(common.getExternalDirectCallMemberName(externalDirect) === 'info', 'external direct call name from node') - t.throws(() => common.getExternalDirectCallMemberName(thisLocalCall), undefined, 'throws on other nodes') - t.throws(() => common.getExternalDirectCallMemberName(localCall), undefined, 'throws on other nodes') -}) - -test('staticAnalysisCommon.getContractName', function (t) { - t.plan(2) - var contract = { name: 'ContractDefinition', attributes: { name: 'baz' } } - t.ok(common.getContractName(contract) === 'baz', 'returns right contract name') - t.throws(() => common.getContractName({ name: 'InheritanceSpecifier' }), undefined, 'throws on other nodes') -}) - -test('staticAnalysisCommon.getFunctionDefinitionName', function (t) { - t.plan(2) - var func = { name: 'FunctionDefinition', attributes: { name: 'foo' } } - t.ok(common.getFunctionDefinitionName(func) === 'foo', 'returns right contract name') - t.throws(() => common.getFunctionDefinitionName({ name: 'InlineAssembly' }), undefined, 'throws on other nodes') -}) - -test('staticAnalysisCommon.getInheritsFromName', function (t) { - t.plan(2) - var inh = { - 'children': [ - { - 'attributes': { - 'name': 'r' - }, - 'id': 7, - 'name': 'UserDefinedTypeName', - 'src': '84:1:0' - } - ], - 'id': 8, - 'name': 'InheritanceSpecifier', - 'src': '84:1:0' - } - t.ok(common.getInheritsFromName(inh) === 'r', 'returns right contract name') - t.throws(() => common.getInheritsFromName({ name: 'ElementaryTypeName' }), undefined, 'throws on other nodes') -}) - -test('staticAnalysisCommon.getDeclaredVariableName', function (t) { - t.plan(2) - var node1 = { - 'attributes': { - 'name': 'x', - 'type': 'struct Ballot.Voter storage pointer' - }, - 'children': [ - { - 'attributes': { - 'name': 'Voter' - }, - 'id': 43, - 'name': 'UserDefinedTypeName', - 'src': '604:5:0' - } - ], - 'id': 44, - 'name': 'VariableDeclaration', - 'src': '604:15:0' - } - t.ok(common.getDeclaredVariableName(node1) === 'x', 'extract right variable name') - node1.name = 'FunctionCall' - t.throws(() => common.getDeclaredVariableName(node1) === 'x', undefined, 'throw if wrong node') -}) - -test('staticAnalysisCommon.getStateVariableDeclarationsFormContractNode', function (t) { - t.plan(4) - var contract = { - 'attributes': { - 'fullyImplemented': true, - 'isLibrary': false, - 'linearizedBaseContracts': [ - 274 - ], - 'name': 'Ballot' - }, - 'children': [ - { - 'attributes': { - 'name': 'Voter' - }, - 'children': [], - 'name': 'StructDefinition' - }, - { - 'attributes': { - 'name': 'Proposal' - }, - 'children': [], - 'name': 'StructDefinition' - }, - { - 'attributes': { - 'name': 'chairperson', - 'type': 'address' - }, - 'children': [ - { - 'attributes': { - 'name': 'address' - }, - 'name': 'ElementaryTypeName' - } - ], - 'name': 'VariableDeclaration' - }, - { - 'attributes': { - 'name': 'voters', - 'type': 'mapping(address => struct Ballot.Voter storage ref)' - }, - 'children': [ - { - 'children': [ - { - 'attributes': { - 'name': 'address' - }, - 'name': 'ElementaryTypeName' - }, - { - 'attributes': { - 'name': 'Voter' - }, - 'name': 'UserDefinedTypeName' - } - ], - 'name': 'Mapping' - } - ], - 'name': 'VariableDeclaration' - }, - { - 'attributes': { - 'name': 'proposals', - 'type': 'struct Ballot.Proposal storage ref[] storage ref' - }, - 'children': [ - { - 'children': [ - { - 'attributes': { - 'name': 'Proposal' - }, - 'name': 'UserDefinedTypeName' - } - ], - 'name': 'ArrayTypeName' - } - ], - 'name': 'VariableDeclaration' - }, - { - 'attributes': { - 'constant': false, - 'name': 'Ballot', - 'payable': false, - 'visibility': 'public' - }, - 'children': [], - 'name': 'FunctionDefinition' - }, - { - 'attributes': { - 'constant': false, - 'name': 'giveRightToVote', - 'payable': false, - 'visibility': 'public' - }, - 'children': [], - 'name': 'FunctionDefinition' - } - ], - 'name': 'ContractDefinition' - } - var res = common.getStateVariableDeclarationsFormContractNode(contract).map(common.getDeclaredVariableName) - - t.ok(res[0] === 'chairperson', 'var 1 should be ') - t.ok(res[1] === 'voters', 'var 2 should be ') - t.ok(res[2] === 'proposals', 'var 3 should be ') - t.ok(res[3] === undefined, 'var 4 should be undefined') -}) - -test('staticAnalysisCommon.getFunctionOrModifierDefinitionParameterPart', function (t) { - t.plan(2) - var funDef = { - 'attributes': { - 'constant': true, - 'name': 'winnerName', - 'payable': false, - 'visibility': 'public' - }, - 'children': [ - { - 'children': [ - ], - 'name': 'ParameterList' - }, - { - 'children': [], - 'name': 'ParameterList' - }, - { - 'children': [], - 'name': 'Block' - } - ], - 'name': 'FunctionDefinition' - } - t.ok(common.helpers.nodeType(common.getFunctionOrModifierDefinitionParameterPart(funDef), 'ParameterList'), 'should return a parameterList') - t.throws(() => common.getFunctionOrModifierDefinitionParameterPart({ name: 'SourceUnit' }), undefined, 'throws on other nodes') -}) - -test('staticAnalysisCommon.getFunctionCallTypeParameterType', function (t) { - t.plan(4) - var localCall = { - 'attributes': { - 'type': 'tuple()', - 'type_conversion': false - }, - 'children': [ - { - 'attributes': { - 'type': 'function (struct Ballot.Voter storage pointer)', - 'value': 'bli' - }, - 'id': 37, - 'name': 'Identifier', - 'src': '540:3:0' - }, - { - 'attributes': { - 'type': 'struct Ballot.Voter storage pointer', - 'value': 'x' - }, - 'id': 38, - 'name': 'Identifier', - 'src': '544:1:0' - } - ], - 'id': 39, - 'name': 'FunctionCall', - 'src': '540:6:0' - } - var thisLocalCall = { name: 'MemberAccess', children: [ { attributes: { value: 'this', type: 'contract test' }, name: 'Identifier' } ], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } } - var externalDirect = { - attributes: { - member_name: 'info', - type: 'function () payable external returns (uint256)' - }, - children: [ - { - attributes: { - type: 'contract InfoFeed', - value: 'f' - }, - id: 30, - name: 'Identifier', - src: '405:1:0' - } - ], - id: 32, - name: 'MemberAccess', - src: '405:6:0' - } - t.ok(common.getFunctionCallTypeParameterType(thisLocalCall) === 'bytes32,address', 'this local call returns correct type') - t.ok(common.getFunctionCallTypeParameterType(externalDirect) === '', 'external direct call returns correct type') - t.ok(common.getFunctionCallTypeParameterType(localCall) === 'struct Ballot.Voter storage pointer', 'local call returns correct type') - t.throws(() => common.getFunctionCallTypeParameterType({ name: 'MemberAccess' }), undefined, 'throws on wrong type') -}) - -test('staticAnalysisCommon.getLibraryCallContractName', function (t) { - t.plan(2) - var node = { - 'attributes': { - 'member_name': 'insert', - 'type': 'function (struct Set.Data storage pointer,uint256) returns (bool)' - }, - 'children': [ - { - 'attributes': { - 'type': 'type(library Set)', - 'value': 'Set' - }, - 'name': 'Identifier' - } - ], - 'name': 'MemberAccess' - } - t.equal(common.getLibraryCallContractName(node), 'Set', 'should return correct contract name') - t.throws(() => common.getLibraryCallContractName({ name: 'Identifier' }), undefined, 'should throw on wrong node') -}) - -test('staticAnalysisCommon.getLibraryCallMemberName', function (t) { - t.plan(2) - var node = { +test('staticAnalysisCommon.getLibraryCallMemberName', function (t) { + t.plan(2) + var node = { 'attributes': { 'member_name': 'insert', - 'type': 'function (struct Set.Data storage pointer,uint256) returns (bool)' - }, - 'children': [ - { - 'attributes': { - 'type': 'type(library Set)', - 'value': 'Set' - }, - 'name': 'Identifier' - } - ], - 'name': 'MemberAccess' - } - t.equal(common.getLibraryCallMemberName(node), 'insert', 'should return correct member name') - t.throws(() => common.getLibraryCallMemberName({ name: 'Identifier' }), undefined, 'should throw on wrong node') -}) - -test('staticAnalysisCommon.getFullQualifiedFunctionCallIdent', function (t) { - t.plan(4) - var contract = { name: 'ContractDefinition', attributes: { name: 'baz' } } - var localCall = { - 'attributes': { - 'type': 'tuple()', - 'type_conversion': false - }, - 'children': [ - { - 'attributes': { - 'type': 'function (struct Ballot.Voter storage pointer)', - 'value': 'bli' - }, - 'id': 37, - 'name': 'Identifier', - 'src': '540:3:0' - }, - { - 'attributes': { - 'type': 'struct Ballot.Voter storage pointer', - 'value': 'x' - }, - 'id': 38, - 'name': 'Identifier', - 'src': '544:1:0' - } - ], - 'id': 39, - 'name': 'FunctionCall', - 'src': '540:6:0' - } - var thisLocalCall = { name: 'MemberAccess', children: [ { attributes: { value: 'this', type: 'contract test' }, name: 'Identifier' } ], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } } - var externalDirect = { - attributes: { - member_name: 'info', - type: 'function () payable external returns (uint256)' - }, - children: [ - { - attributes: { - type: 'contract InfoFeed', - value: 'f' - }, - id: 30, - name: 'Identifier', - src: '405:1:0' - } - ], - id: 32, - name: 'MemberAccess', - src: '405:6:0' - } - - t.ok(common.getFullQualifiedFunctionCallIdent(contract, thisLocalCall) === 'test.b(bytes32,address)', 'this local call returns correct type') - t.ok(common.getFullQualifiedFunctionCallIdent(contract, externalDirect) === 'InfoFeed.info()', 'external direct call returns correct type') - t.ok(common.getFullQualifiedFunctionCallIdent(contract, localCall) === 'baz.bli(struct Ballot.Voter storage pointer)', 'local call returns correct type') - t.throws(() => common.getFullQualifiedFunctionCallIdent(contract, { name: 'MemberAccess' }), undefined, 'throws on wrong type') -}) - -test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) { - t.plan(3) - var contract = { name: 'ContractDefinition', attributes: { name: 'baz' } } - var funDef = { - 'attributes': { - 'constant': false, - 'name': 'getY', - 'payable': false, - 'visibility': 'public' - }, - 'children': [ - { - 'children': [ - { - 'attributes': { - 'name': 'z', - 'type': 'uint256' - }, - 'children': [ - { - 'attributes': { - 'name': 'uint' - }, - 'name': 'ElementaryTypeName' - } - ], - 'name': 'VariableDeclaration' - }, - { - 'attributes': { - 'name': 'r', - 'type': 'bool' - }, - 'children': [ - { - 'attributes': { - 'name': 'bool' - }, - 'name': 'ElementaryTypeName' - } - ], - 'name': 'VariableDeclaration' - } - ], - 'name': 'ParameterList' - }, - { - 'children': [ - { - 'attributes': { - 'name': '', - 'type': 'uint256' - }, - 'children': [ - { - 'attributes': { - 'name': 'uint' - }, - 'id': 34, - 'name': 'ElementaryTypeName', - 'src': '285:4:0' - } - ], - 'id': 35, - 'name': 'VariableDeclaration', - 'src': '285:4:0' - } - ], - 'name': 'ParameterList' - }, - { - 'children': [], - 'name': 'Block' - } - ], - 'name': 'FunctionDefinition' - } - t.ok(common.getFullQuallyfiedFuncDefinitionIdent(contract, funDef, ['uint256', 'bool']) === 'baz.getY(uint256,bool)', 'creates right signature') - t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent(contract, { name: 'MemberAccess' }, ['uint256', 'bool']), undefined, 'throws on wrong nodes') - t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent({ name: 'FunctionCall' }, funDef, ['uint256', 'bool']), undefined, 'throws on wrong nodes') -}) - -test('staticAnalysisCommon.getLoopBlockStartIndex', function (t) { - t.plan(3) - var node1 = { - 'children': - [ - { - 'attributes': - { - 'assignments': - [ - 21 - ] - }, - 'children': - [ - { - 'attributes': - { - 'constant': false, - 'name': 'i', - 'scope': 39, - 'stateVariable': false, - 'storageLocation': 'default', - 'type': 'uint256', - 'value': null, - 'visibility': 'internal' - }, - 'children': - [ - { - 'attributes': - { - 'name': 'uint', - 'type': 'uint256' - }, - 'id': 20, - 'name': 'ElementaryTypeName', - 'src': '207:4:0' - } - ], - 'id': 21, - 'name': 'VariableDeclaration', - 'src': '207:6:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 17, - 'type': 'uint256', - 'value': 'index' - }, - 'id': 22, - 'name': 'Identifier', - 'src': '216:5:0' - } - ], - 'id': 23, - 'name': 'VariableDeclarationStatement', - 'src': '207:14:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'commonType': - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - }, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '<', - 'type': 'bool' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 21, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 24, - 'name': 'Identifier', - 'src': '223:1:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'hexvalue': '3130', - 'isConstant': false, - 'isLValue': false, - 'isPure': true, - 'lValueRequested': false, - 'subdenomination': null, - 'token': 'number', - 'type': 'int_const 10', - 'value': '10' - }, - 'id': 25, - 'name': 'Literal', - 'src': '227:2:0' - } - ], - 'id': 26, - 'name': 'BinaryOperation', - 'src': '223:6:0' - }, - { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '++', - 'prefix': false, - 'type': 'uint256' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 21, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 27, - 'name': 'Identifier', - 'src': '231:1:0' - } - ], - 'id': 28, - 'name': 'UnaryOperation', - 'src': '231:3:0' - } - ], - 'id': 29, - 'name': 'ExpressionStatement', - 'src': '231:3:0' - }, - { - 'children': - [ - { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'isStructConstructorCall': false, - 'lValueRequested': false, - 'names': - [ - null - ], - 'type': 'uint256', - 'type_conversion': false - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': - [ - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - } - ], - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'member_name': 'push', - 'referencedDeclaration': null, - 'type': 'function (uint256) returns (uint256)' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 4, - 'type': 'uint256[] storage ref', - 'value': 'array' - }, - 'id': 30, - 'name': 'Identifier', - 'src': '250:5:0' - } - ], - 'id': 32, - 'name': 'MemberAccess', - 'src': '250:10:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 21, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 33, - 'name': 'Identifier', - 'src': '261:1:0' - } - ], - 'id': 34, - 'name': 'FunctionCall', - 'src': '250:13:0' - } - ], - 'id': 35, - 'name': 'ExpressionStatement', - 'src': '250:13:0' - } - ], - 'id': 36, - 'name': 'Block', - 'src': '236:38:0' + 'type': 'function (struct Set.Data storage pointer,uint256) returns (bool)' + }, + 'children': [ + { + 'attributes': { + 'type': 'type(library Set)', + 'value': 'Set' + }, + 'name': 'Identifier' } ], - 'id': 37, - 'name': 'ForStatement', - 'src': '202:72:0' + 'name': 'MemberAccess' } - var node2 = { - 'children': - [ + t.equal(common.getLibraryCallMemberName(node), 'insert', 'should return correct member name') + t.throws(() => common.getLibraryCallMemberName({ name: 'Identifier' }), undefined, 'should throw on wrong node') +}) + +test('staticAnalysisCommon.getFullQualifiedFunctionCallIdent', function (t) { + t.plan(4) + var contract = { name: 'ContractDefinition', attributes: { name: 'baz' } } + t.ok(common.getFullQualifiedFunctionCallIdent(contract, thisLocalCall) === 'test.b(bytes32,address)', 'this local call returns correct type') + t.ok(common.getFullQualifiedFunctionCallIdent(contract, externalDirect) === 'InfoFeed.info()', 'external direct call returns correct type') + t.ok(common.getFullQualifiedFunctionCallIdent(contract, localCall) === 'baz.bli(struct Ballot.Voter storage pointer)', 'local call returns correct type') + t.throws(() => common.getFullQualifiedFunctionCallIdent(contract, { name: 'MemberAccess' }), undefined, 'throws on wrong type') +}) + +test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) { + t.plan(3) + var contract = { name: 'ContractDefinition', attributes: { name: 'baz' } } + var funDef = { + 'attributes': { + 'constant': false, + 'name': 'getY', + 'payable': false, + 'visibility': 'public' + }, + 'children': [ { - 'attributes': - { - 'argumentTypes': null, - 'commonType': - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - }, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '<', - 'type': 'bool' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 69, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 82, - 'name': 'Identifier', - 'src': '592:1:0' - }, + 'children': [ { - 'attributes': - { - 'argumentTypes': null, - 'hexvalue': '3130', - 'isConstant': false, - 'isLValue': false, - 'isPure': true, - 'lValueRequested': false, - 'subdenomination': null, - 'token': 'number', - 'type': 'int_const 10', - 'value': '10' + 'attributes': { + 'name': 'z', + 'type': 'uint256' }, - 'id': 83, - 'name': 'Literal', - 'src': '596:2:0' - } - ], - 'id': 84, - 'name': 'BinaryOperation', - 'src': '592:6:0' - }, - { - 'children': - [ - { - 'children': - [ + 'children': [ { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'isStructConstructorCall': false, - 'lValueRequested': false, - 'names': - [ - null - ], - 'type': 'uint256', - 'type_conversion': false + 'attributes': { + 'name': 'uint' }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': - [ - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - } - ], - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'member_name': 'push', - 'referencedDeclaration': null, - 'type': 'function (uint256) returns (uint256)' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 4, - 'type': 'uint256[] storage ref', - 'value': 'array' - }, - 'id': 72, - 'name': 'Identifier', - 'src': '544:5:0' - } - ], - 'id': 74, - 'name': 'MemberAccess', - 'src': '544:10:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 69, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 75, - 'name': 'Identifier', - 'src': '555:1:0' - } - ], - 'id': 76, - 'name': 'FunctionCall', - 'src': '544:13:0' + 'name': 'ElementaryTypeName' } ], - 'id': 77, - 'name': 'ExpressionStatement', - 'src': '544:13:0' + 'name': 'VariableDeclaration' }, { - 'children': - [ + 'attributes': { + 'name': 'r', + 'type': 'bool' + }, + 'children': [ { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '++', - 'prefix': false, - 'type': 'uint256' + 'attributes': { + 'name': 'bool' }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 69, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 78, - 'name': 'Identifier', - 'src': '571:1:0' - } - ], - 'id': 79, - 'name': 'UnaryOperation', - 'src': '571:3:0' + 'name': 'ElementaryTypeName' } ], - 'id': 80, - 'name': 'ExpressionStatement', - 'src': '571:3:0' - } - ], - 'id': 81, - 'name': 'Block', - 'src': '530:55:0' - } - ], - 'id': 85, - 'name': 'DoWhileStatement', - 'src': '528:72:0' - } - var node3 = { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'commonType': - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - }, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '<', - 'type': 'bool' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 45, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 48, - 'name': 'Identifier', - 'src': '372:1:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'hexvalue': '3130', - 'isConstant': false, - 'isLValue': false, - 'isPure': true, - 'lValueRequested': false, - 'subdenomination': null, - 'token': 'number', - 'type': 'int_const 10', - 'value': '10' - }, - 'id': 49, - 'name': 'Literal', - 'src': '376:2:0' + 'name': 'VariableDeclaration' } ], - 'id': 50, - 'name': 'BinaryOperation', - 'src': '372:6:0' + 'name': 'ParameterList' }, { - 'children': - [ - { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'isStructConstructorCall': false, - 'lValueRequested': false, - 'names': - [ - null - ], - 'type': 'uint256', - 'type_conversion': false - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': - [ - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - } - ], - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'member_name': 'push', - 'referencedDeclaration': null, - 'type': 'function (uint256) returns (uint256)' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 4, - 'type': 'uint256[] storage ref', - 'value': 'array' - }, - 'id': 51, - 'name': 'Identifier', - 'src': '394:5:0' - } - ], - 'id': 53, - 'name': 'MemberAccess', - 'src': '394:10:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 45, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 54, - 'name': 'Identifier', - 'src': '405:1:0' - } - ], - 'id': 55, - 'name': 'FunctionCall', - 'src': '394:13:0' - } - ], - 'id': 56, - 'name': 'ExpressionStatement', - 'src': '394:13:0' - }, + 'children': [ { - 'children': - [ + 'attributes': { + 'name': '', + 'type': 'uint256' + }, + 'children': [ { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '++', - 'prefix': false, - 'type': 'uint256' + 'attributes': { + 'name': 'uint' }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 45, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 57, - 'name': 'Identifier', - 'src': '421:1:0' - } - ], - 'id': 58, - 'name': 'UnaryOperation', - 'src': '421:3:0' + 'id': 34, + 'name': 'ElementaryTypeName', + 'src': '285:4:0' } ], - 'id': 59, - 'name': 'ExpressionStatement', - 'src': '421:3:0' + 'id': 35, + 'name': 'VariableDeclaration', + 'src': '285:4:0' } ], - 'id': 60, - 'name': 'Block', - 'src': '380:55:0' + 'name': 'ParameterList' + }, + { + 'children': [], + 'name': 'Block' } ], - 'id': 61, - 'name': 'WhileStatement', - 'src': '365:70:0' + 'name': 'FunctionDefinition' } + t.ok(common.getFullQuallyfiedFuncDefinitionIdent(contract, funDef, ['uint256', 'bool']) === 'baz.getY(uint256,bool)', 'creates right signature') + t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent(contract, { name: 'MemberAccess' }, ['uint256', 'bool']), undefined, 'throws on wrong nodes') + t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent({ name: 'FunctionCall' }, funDef, ['uint256', 'bool']), undefined, 'throws on wrong nodes') +}) - t.equal(common.getLoopBlockStartIndex(node1), 3) // 'for' loop - t.equal(common.getLoopBlockStartIndex(node2), 1) // 'do-while' loop - t.equal(common.getLoopBlockStartIndex(node3), 1) // 'while' loop +test('staticAnalysisCommon.getLoopBlockStartIndex', function (t) { + t.plan(3) + t.equal(common.getLoopBlockStartIndex(forLoopNode), 3) // 'for' loop + t.equal(common.getLoopBlockStartIndex(doWhileLoopNode), 1) // 'do-while' loop + t.equal(common.getLoopBlockStartIndex(whileLoopNode), 1) // 'while' loop }) // #################### Trivial Node Identification @@ -1891,682 +666,9 @@ test('staticAnalysisCommon.isInlineAssembly', function (t) { test('staticAnalysisCommon.isLoop', function (t) { t.plan(3) - var node1 = { - 'children': - [ - { - 'attributes': - { - 'assignments': - [ - 21 - ] - }, - 'children': - [ - { - 'attributes': - { - 'constant': false, - 'name': 'i', - 'scope': 39, - 'stateVariable': false, - 'storageLocation': 'default', - 'type': 'uint256', - 'value': null, - 'visibility': 'internal' - }, - 'children': - [ - { - 'attributes': - { - 'name': 'uint', - 'type': 'uint256' - }, - 'id': 20, - 'name': 'ElementaryTypeName', - 'src': '207:4:0' - } - ], - 'id': 21, - 'name': 'VariableDeclaration', - 'src': '207:6:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 17, - 'type': 'uint256', - 'value': 'index' - }, - 'id': 22, - 'name': 'Identifier', - 'src': '216:5:0' - } - ], - 'id': 23, - 'name': 'VariableDeclarationStatement', - 'src': '207:14:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'commonType': - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - }, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '<', - 'type': 'bool' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 21, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 24, - 'name': 'Identifier', - 'src': '223:1:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'hexvalue': '3130', - 'isConstant': false, - 'isLValue': false, - 'isPure': true, - 'lValueRequested': false, - 'subdenomination': null, - 'token': 'number', - 'type': 'int_const 10', - 'value': '10' - }, - 'id': 25, - 'name': 'Literal', - 'src': '227:2:0' - } - ], - 'id': 26, - 'name': 'BinaryOperation', - 'src': '223:6:0' - }, - { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '++', - 'prefix': false, - 'type': 'uint256' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 21, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 27, - 'name': 'Identifier', - 'src': '231:1:0' - } - ], - 'id': 28, - 'name': 'UnaryOperation', - 'src': '231:3:0' - } - ], - 'id': 29, - 'name': 'ExpressionStatement', - 'src': '231:3:0' - }, - { - 'children': - [ - { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'isStructConstructorCall': false, - 'lValueRequested': false, - 'names': - [ - null - ], - 'type': 'uint256', - 'type_conversion': false - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': - [ - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - } - ], - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'member_name': 'push', - 'referencedDeclaration': null, - 'type': 'function (uint256) returns (uint256)' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 4, - 'type': 'uint256[] storage ref', - 'value': 'array' - }, - 'id': 30, - 'name': 'Identifier', - 'src': '250:5:0' - } - ], - 'id': 32, - 'name': 'MemberAccess', - 'src': '250:10:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 21, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 33, - 'name': 'Identifier', - 'src': '261:1:0' - } - ], - 'id': 34, - 'name': 'FunctionCall', - 'src': '250:13:0' - } - ], - 'id': 35, - 'name': 'ExpressionStatement', - 'src': '250:13:0' - } - ], - 'id': 36, - 'name': 'Block', - 'src': '236:38:0' - } - ], - 'id': 37, - 'name': 'ForStatement', - 'src': '202:72:0' - } - var node2 = { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'commonType': - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - }, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '<', - 'type': 'bool' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 69, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 82, - 'name': 'Identifier', - 'src': '592:1:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'hexvalue': '3130', - 'isConstant': false, - 'isLValue': false, - 'isPure': true, - 'lValueRequested': false, - 'subdenomination': null, - 'token': 'number', - 'type': 'int_const 10', - 'value': '10' - }, - 'id': 83, - 'name': 'Literal', - 'src': '596:2:0' - } - ], - 'id': 84, - 'name': 'BinaryOperation', - 'src': '592:6:0' - }, - { - 'children': - [ - { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'isStructConstructorCall': false, - 'lValueRequested': false, - 'names': - [ - null - ], - 'type': 'uint256', - 'type_conversion': false - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': - [ - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - } - ], - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'member_name': 'push', - 'referencedDeclaration': null, - 'type': 'function (uint256) returns (uint256)' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 4, - 'type': 'uint256[] storage ref', - 'value': 'array' - }, - 'id': 72, - 'name': 'Identifier', - 'src': '544:5:0' - } - ], - 'id': 74, - 'name': 'MemberAccess', - 'src': '544:10:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 69, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 75, - 'name': 'Identifier', - 'src': '555:1:0' - } - ], - 'id': 76, - 'name': 'FunctionCall', - 'src': '544:13:0' - } - ], - 'id': 77, - 'name': 'ExpressionStatement', - 'src': '544:13:0' - }, - { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '++', - 'prefix': false, - 'type': 'uint256' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 69, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 78, - 'name': 'Identifier', - 'src': '571:1:0' - } - ], - 'id': 79, - 'name': 'UnaryOperation', - 'src': '571:3:0' - } - ], - 'id': 80, - 'name': 'ExpressionStatement', - 'src': '571:3:0' - } - ], - 'id': 81, - 'name': 'Block', - 'src': '530:55:0' - } - ], - 'id': 85, - 'name': 'DoWhileStatement', - 'src': '528:72:0' - } - var node3 = { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'commonType': - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - }, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '<', - 'type': 'bool' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 45, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 48, - 'name': 'Identifier', - 'src': '372:1:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'hexvalue': '3130', - 'isConstant': false, - 'isLValue': false, - 'isPure': true, - 'lValueRequested': false, - 'subdenomination': null, - 'token': 'number', - 'type': 'int_const 10', - 'value': '10' - }, - 'id': 49, - 'name': 'Literal', - 'src': '376:2:0' - } - ], - 'id': 50, - 'name': 'BinaryOperation', - 'src': '372:6:0' - }, - { - 'children': - [ - { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'isStructConstructorCall': false, - 'lValueRequested': false, - 'names': - [ - null - ], - 'type': 'uint256', - 'type_conversion': false - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': - [ - { - 'typeIdentifier': 't_uint256', - 'typeString': 'uint256' - } - ], - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'member_name': 'push', - 'referencedDeclaration': null, - 'type': 'function (uint256) returns (uint256)' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 4, - 'type': 'uint256[] storage ref', - 'value': 'array' - }, - 'id': 51, - 'name': 'Identifier', - 'src': '394:5:0' - } - ], - 'id': 53, - 'name': 'MemberAccess', - 'src': '394:10:0' - }, - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 45, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 54, - 'name': 'Identifier', - 'src': '405:1:0' - } - ], - 'id': 55, - 'name': 'FunctionCall', - 'src': '394:13:0' - } - ], - 'id': 56, - 'name': 'ExpressionStatement', - 'src': '394:13:0' - }, - { - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'isConstant': false, - 'isLValue': false, - 'isPure': false, - 'lValueRequested': false, - 'operator': '++', - 'prefix': false, - 'type': 'uint256' - }, - 'children': - [ - { - 'attributes': - { - 'argumentTypes': null, - 'overloadedDeclarations': - [ - null - ], - 'referencedDeclaration': 45, - 'type': 'uint256', - 'value': 'i' - }, - 'id': 57, - 'name': 'Identifier', - 'src': '421:1:0' - } - ], - 'id': 58, - 'name': 'UnaryOperation', - 'src': '421:3:0' - } - ], - 'id': 59, - 'name': 'ExpressionStatement', - 'src': '421:3:0' - } - ], - 'id': 60, - 'name': 'Block', - 'src': '380:55:0' - } - ], - 'id': 61, - 'name': 'WhileStatement', - 'src': '365:70:0' - } - - t.equal(common.isLoop(node1), true) - t.equal(common.isLoop(node2), true) - t.equal(common.isLoop(node3), true) + t.equal(common.isLoop(forLoopNode), true) + t.equal(common.isLoop(doWhileLoopNode), true) + t.equal(common.isLoop(whileLoopNode), true) }) // #################### Complex Node Identification