diff --git a/.circleci/config.yml b/.circleci/config.yml index 7f963545eb..6f2bd099f0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -44,6 +44,16 @@ jobs: - run: npm install && npm run bootstrap - run: cd remix-tests && npm test + remix-astwalker: + docker: + - image: circleci/node:10 + environment: + working_directory: ~/repo + steps: + - checkout + - run: npm install && npm run bootstrap + - run: cd remix-astwalker && npm test + remix-simulator: docker: - image: circleci/node:10 @@ -73,5 +83,6 @@ workflows: - remix-debug - remix-analyzer - remix-tests + - remix-astwalker - remix-simulator - remix-url-resolver diff --git a/lerna.json b/lerna.json index 5f360141ef..17307304c3 100644 --- a/lerna.json +++ b/lerna.json @@ -8,6 +8,7 @@ "remix-tests", "remix-simulator", "remix-url-resolver" + "remix-astwalker" ], "command": { "init": { diff --git a/remix-astwalker/.gitignore b/remix-astwalker/.gitignore new file mode 100644 index 0000000000..343b37acb1 --- /dev/null +++ b/remix-astwalker/.gitignore @@ -0,0 +1,3 @@ +.nyc_output +coverage +build diff --git a/remix-astwalker/README.md b/remix-astwalker/README.md new file mode 100644 index 0000000000..a3c674ac67 --- /dev/null +++ b/remix-astwalker/README.md @@ -0,0 +1,19 @@ +## Remix ASTwalker +`remix-astwalker` module walks through solidity AST and spits out AST nodes. + +#### Example +```ts +import { AstWalker } from "remix-astwalker"; + +const astWalker = new AstWalker(); +astWalker.on("node", node => { + if (node.nodeType === "ContractDefinition") { + checkContract(st, node); + } + + if (node.nodeType === "PragmaDirective") { + checkProgramDirective(st, node); + } +}); +``` +For more examples see `tests`. diff --git a/remix-astwalker/package.json b/remix-astwalker/package.json new file mode 100644 index 0000000000..5c9cddeb81 --- /dev/null +++ b/remix-astwalker/package.json @@ -0,0 +1,43 @@ +{ + "name": "remix-astwalker", + "version": "0.0.1", + "description": "Remix sub-module for walking through AST", + "main": "dist/index.js", + "scripts": { + "build": "tsc", + "test": "nyc --reporter=lcov --require ts-node/register tape ./tests/*.ts | tap-spec; nyc report ---reporter=text" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ethereum/remix.git" + }, + "keywords": [ + "Solidity", + "AST", + "remix" + ], + "author": "0mkara", + "license": "MIT", + "bugs": { + "url": "https://github.com/ethereum/remix/issues" + }, + "homepage": "https://github.com/ethereum/remix#readme", + "nyc": { + "include": [ + "src/**/*.ts" + ], + "extension": [ + ".ts" + ] + }, + "dependencies": { + "@types/tape": "^4.2.33", + "nyc": "^13.3.0", + "tape": "^4.10.1", + "ts-node": "^8.0.3", + "typescript": "^3.4.3" + }, + "devDependencies": { + "tap-spec": "^5.0.0" + } +} diff --git a/remix-astwalker/src/astWalker.ts b/remix-astwalker/src/astWalker.ts new file mode 100644 index 0000000000..a20a03040a --- /dev/null +++ b/remix-astwalker/src/astWalker.ts @@ -0,0 +1,116 @@ +import { EventEmitter } from "events"; +import { AstNodeLegacy, Node, AstNode } from "./index"; + +export declare interface AstWalker { + new(): EventEmitter; +} +/** + * Crawl the given AST through the function walk(ast, callback) + */ +/** + * visit all the AST nodes + * + * @param {Object} ast - AST node + * @return EventEmitter + * event('node', ) will be fired for every node of type . + * event('node', "*") will be fired for all other nodes. + * in each case, if the event emits false it does not descend into children. + * If no event for the current type, children are visited. + */ +export class AstWalker extends EventEmitter { + manageCallback( + node: AstNodeLegacy | AstNode, + callback: Object | Function + ): any { + if (node) { + if ((node).name in callback) { + return callback[(node).name](node); + } else { + return callback["*"](node); + } + } + if (node) { + if ((node).nodeType in callback) { + /* istanbul ignore next */ + return callback[(node).nodeType](node); + } else { + /* istanbul ignore next */ + return callback["*"](node); + } + } + } + walk(ast: AstNodeLegacy | AstNode, callback?: Function | Object) { + if (callback) { + if (callback instanceof Function) { + callback = Object({ "*": callback }); + } + if (!("*" in callback)) { + callback["*"] = function() { + return true; + }; + } + if (ast) { + if ( + this.manageCallback(ast, callback) && + (ast).children && + (ast).children.length > 0 + ) { + for (let k in (ast).children) { + let child = (ast).children[k]; + this.walk(child, callback); + } + } + } + if (ast) { + if ( + this.manageCallback(ast, callback) && + (ast).nodes && + (ast).nodes.length > 0 + ) { + for (let k in (ast).nodes) { + let child = (ast).nodes[k]; + this.walk(child, callback); + } + } + } + } else { + if (ast) { + if ( + (ast).children && + (ast).children.length > 0 + ) { + for (let k in (ast).children) { + let child = (ast).children[k]; + this.emit("node", child); + this.walk(child); + } + } + } + if (ast) { + if ((ast).nodes && (ast).nodes.length > 0) { + for (let k in (ast).nodes) { + let child = (ast).nodes[k]; + this.emit("node", child); + this.walk(child); + } + } + } + } + } + + walkAstList(sourcesList: Node, cb?: Function) { + if (cb) { + if (sourcesList.ast) { + this.walk(sourcesList.ast, cb); + } else { + this.walk(sourcesList.legacyAST, cb); + } + } else { + if (sourcesList.ast) { + this.walk(sourcesList.ast); + } else { + this.walk(sourcesList.legacyAST); + } + } + } +} diff --git a/remix-astwalker/src/index.ts b/remix-astwalker/src/index.ts new file mode 100644 index 0000000000..929bce2d90 --- /dev/null +++ b/remix-astwalker/src/index.ts @@ -0,0 +1,2 @@ +export * from './types' +export * from './astWalker' diff --git a/remix-astwalker/src/types.ts b/remix-astwalker/src/types.ts new file mode 100644 index 0000000000..e36b78c772 --- /dev/null +++ b/remix-astwalker/src/types.ts @@ -0,0 +1,43 @@ +export interface Node { + ast?: AstNode; + legacyAST?: AstNodeLegacy; + source?: string; + id?: number; +} + +export interface AstNode { + absolutePath?: string; + exportedSymbols?: Object; + id: number; + nodeType: string; + nodes?: Array; + src: string; + literals?: Array; + file?: string; + scope?: number; + sourceUnit?: number; + symbolAliases?: Array; + [x: string]: any; +} + +export interface AstNodeLegacy { + id: number; + name: string; + src: string; + children?: Array; + attributes?: AstNodeAtt; +} + +export interface AstNodeAtt { + operator?: string; + string?: null; + type?: string; + value?: string; + constant?: boolean; + name?: string; + public?: boolean; + exportedSymbols?: Object; + argumentTypes?: null; + absolutePath?: string; + [x: string]: any; +} diff --git a/remix-astwalker/tests/LegacyTest.ts b/remix-astwalker/tests/LegacyTest.ts new file mode 100644 index 0000000000..bec2a345dc --- /dev/null +++ b/remix-astwalker/tests/LegacyTest.ts @@ -0,0 +1,101 @@ +import tape from "tape"; +import { AstWalker, AstNodeLegacy } from "../src"; +import node from "./resources/legacyAST"; + + +tape("ASTWalker Legacy", (t: tape.Test) => { + t.test("ASTWalker.walk && .walkAST", (st: tape.Test) => { + st.plan(19); + // New Ast Object + const astWalker = new AstWalker(); + // EventListener + astWalker.on("node", node => { + if (node.name === "ContractDefinition") { + checkContract(st, node); + } + if (node.name === "FunctionDefinition") { + checkSetFunction(st, node); + checkGetFunction(st, node); + } + if (node.name === "VariableDeclaration") { + checkSetFunction(st, node); + checkGetFunction(st, node); + } + }); + + // Callback pattern + astWalker.walk(node.legacyAST, (node: AstNodeLegacy) => { + if (node.name === "ContractDefinition") { + checkContract(st, node); + } + if (node.name === "FunctionDefinition") { + checkSetFunction(st, node); + checkGetFunction(st, node); + } + if (node.name === "VariableDeclaration") { + checkSetFunction(st, node); + checkGetFunction(st, node); + } + }); + + // Callback Object + var callback: any = {}; + callback.FunctionDefinition = function(node: AstNodeLegacy): boolean { + st.equal(node.name, "FunctionDefinition"); + + return true; + }; + // Calling walk function with cb + astWalker.walk(node.legacyAST, callback); + + // Calling walk function without cb + astWalker.walk(node.legacyAST); + + // Calling WALKASTLIST function + astWalker.walkAstList(node); + // Calling walkASTList with new AST format + astWalker.walkAstList(node); + + // Calling WALKASTLIST function with cb + astWalker.walkAstList(node, node => { + return true; + }); + st.end(); + }); +}); + +function checkContract(st: tape.Test, node: AstNodeLegacy) { + st.equal(node.attributes.name, "Greeter"); + st.equal(node.children[1].attributes.name, "greeting"); + st.equal(node.children[1].attributes.type, "string"); + st.equal(node.children[2].name, "FunctionDefinition"); + st.equal(node.children[2].attributes.name, ""); +} + +function checkSetFunction(st: tape.Test, node: AstNodeLegacy) { + if (node.attributes.name === "set") { + st.equal(node.children[0].name, "ParameterList"); + st.equal(node.children[1].name, "ParameterList"); + st.equal(node.children[2].name, "Block"); + st.equal(node.children[2].children[1].name, "ExpressionStatement"); + checkExpressionStatement(st, node.children[2].children[0]); + } +} + +function checkGetFunction(st: tape.Test, node: AstNodeLegacy) { + if (node.attributes.name === "get") { + st.equal(node.children[0].name, "ParameterList"); + st.equal(node.children[1].name, "ParameterList"); + st.equal(node.children[2].name, "Block"); + } +} + +function checkExpressionStatement(st: tape.Test, node: AstNodeLegacy) { + st.equal(node.children[0].name, "Assignment"); + st.equal(node.children[0].attributes.operator, "="); + st.equal(node.children[0].attributes.type, "int256"); + st.equal(node.children[0].children[0].name, "Identifier"); + st.equal(node.children[0].children[0].attributes.value, "x"); + st.equal(node.children[0].children[1].name, "Identifier"); + st.equal(node.children[0].children[1].attributes.value, "_x"); +} diff --git a/remix-astwalker/tests/newTests.ts b/remix-astwalker/tests/newTests.ts new file mode 100644 index 0000000000..56fe6f9ac7 --- /dev/null +++ b/remix-astwalker/tests/newTests.ts @@ -0,0 +1,72 @@ +import tape from "tape"; +import { AstWalker, AstNode } from "../src"; +import node from "./resources/newAST"; + +tape("New ASTWalker", (t: tape.Test) => { + t.test("ASTWalker.walk && .walkAST", (st: tape.Test) => { + st.plan(24); + // New Ast Object + const astWalker = new AstWalker(); + // EventListener + astWalker.on("node", node => { + if (node.nodeType === "ContractDefinition") { + checkContract(st, node); + } + + if (node.nodeType === "PragmaDirective") { + checkProgramDirective(st, node); + } + }); + + // Callback pattern + astWalker.walk(node.ast, (node: AstNode) => { + if (node.nodeType === "ContractDefinition") { + checkContract(st, node); + } + + if (node.nodeType === "PragmaDirective") { + checkProgramDirective(st, node); + } + }); + + // Callback Object + var callback: any = {}; + callback.FunctionDefinition = function(node: AstNode): boolean { + st.equal(node.name, "FunctionDefinition"); + + return true; + }; + // Calling walk function with cb + astWalker.walk(node.ast, callback); + + // Calling walk function without cb + astWalker.walk(node.ast); + + // Calling WALKASTLIST function + astWalker.walkAstList(node); + + // Calling WALKASTLIST function with cb + astWalker.walkAstList(node, node => { + return true; + }); + st.end(); + }); +}); + +function checkProgramDirective(st: tape.Test, node: AstNode) { + st.equal(node.id, 1); + st.equal(node.literals.length, 7); +} + +function checkContract(st: tape.Test, node: AstNode) { + st.equal(node.name, "Greeter"); + st.equal(node.nodes[0].name, "greeting"); + st.equal(node.nodes[0].nodeType, "VariableDeclaration"); + st.equal(node.nodes[0].name, "greeting"); + st.equal(node.nodes[0].typeName.name, "string"); + st.equal(node.nodes[1].nodeType, "FunctionDefinition"); + st.equal(node.nodes[1].name, ""); + st.equal(node.nodes[1].scope, 25); + st.equal(node.nodes[2].nodeType, "FunctionDefinition"); + st.equal(node.nodes[2].name, "greet"); +} diff --git a/remix-astwalker/tests/resources/ast.ts b/remix-astwalker/tests/resources/ast.ts new file mode 100644 index 0000000000..3512fe4bae --- /dev/null +++ b/remix-astwalker/tests/resources/ast.ts @@ -0,0 +1,23 @@ +import { Node } from '../../src/' +const node: Node = { + ast: { "legacyAST": { "children": [{ "attributes": { "fullyImplemented": true, "isLibrary": false, "linearizedBaseContracts": [5640396], "name": "test" }, "children": [{ "attributes": { "name": "x", "type": "int256" }, "children": [{ "attributes": { "name": "int" }, "id": 5657860, "name": "ElementaryTypeName", "src": "21:3:11" }], "id": 5658100, "name": "VariableDeclaration", "src": "21:5:11" }, { "attributes": { "name": "y", "type": "int256" }, "children": [{ "attributes": { "name": "int" }, "id": 5658180, "name": "ElementaryTypeName", "src": "38:3:11" }], "id": 5658268, "name": "VariableDeclaration", "src": "38:5:11" }, { "attributes": { "constant": false, "name": "set", "public": true }, "children": [{ "children": [{ "attributes": { "name": "_x", "type": "int256" }, "children": [{ "attributes": { "name": "int" }, "id": 5658404, "name": "ElementaryTypeName", "src": "68:3:11" }], "id": 5658492, "name": "VariableDeclaration", "src": "68:6:11" }], "id": 5658572, "name": "ParameterList", "src": "67:8:11" }, { "children": [{ "attributes": { "name": "_r", "type": "int256" }, "children": [{ "attributes": { "name": "int" }, "id": 5658628, "name": "ElementaryTypeName", "src": "85:3:11" }], "id": 5658716, "name": "VariableDeclaration", "src": "85:6:11" }], "id": 5658796, "name": "ParameterList", "src": "84:8:11" }, { "children": [{ "children": [{ "attributes": { "operator": "=", "type": "int256" }, "children": [{ "attributes": { "type": "int256", "value": "x" }, "id": 5658900, "name": "Identifier", "src": "108:1:11" }, { "attributes": { "type": "int256", "value": "_x" }, "id": 5658980, "name": "Identifier", "src": "112:2:11" }], "id": 5657492, "name": "Assignment", "src": "108:6:11" }], "id": 5659028, "name": "ExpressionStatement", "src": "108:6:11" }, { "children": [{ "attributes": { "operator": "=", "type": "int256" }, "children": [{ "attributes": { "type": "int256", "value": "y" }, "id": 5659116, "name": "Identifier", "src": "125:1:11" }, { "attributes": { "string": null, "type": "int_const 10", "value": "10" }, "id": 5659196, "name": "Literal", "src": "129:2:11" }], "id": 5659252, "name": "Assignment", "src": "125:6:11" }], "id": 5659316, "name": "ExpressionStatement", "src": "125:6:11" }, { "children": [{ "attributes": { "operator": "=", "type": "int256" }, "children": [{ "attributes": { "type": "int256", "value": "_r" }, "id": 5659428, "name": "Identifier", "src": "141:2:11" }, { "attributes": { "type": "int256", "value": "x" }, "id": 5639308, "name": "Identifier", "src": "146:1:11" }], "id": 5639356, "name": "Assignment", "src": "141:6:11" }], "id": 5639420, "name": "ExpressionStatement", "src": "141:6:11" }], "id": 5639516, "name": "Block", "src": "97:57:11" }], "id": 5639612, "name": "FunctionDefinition", "src": "55:99:11" }, { "attributes": { "constant": false, "name": "get", "public": true }, "children": [{ "children": [], "id": 5639764, "name": "ParameterList", "src": "179:2:11" }, { "children": [{ "attributes": { "name": "x", "type": "uint256" }, "children": [{ "attributes": { "name": "uint" }, "id": 5639820, "name": "ElementaryTypeName", "src": "191:4:11" }], "id": 5639908, "name": "VariableDeclaration", "src": "191:6:11" }, { "attributes": { "name": "y", "type": "uint256" }, "children": [{ "attributes": { "name": "uint" }, "id": 5639988, "name": "ElementaryTypeName", "src": "199:4:11" }], "id": 5640076, "name": "VariableDeclaration", "src": "199:6:11" }], "id": 5640156, "name": "ParameterList", "src": "190:16:11" }, { "children": [], "id": 5640212, "name": "Block", "src": "212:17:11" }], "id": 5640276, "name": "FunctionDefinition", "src": "167:62:11" }], "id": 5640396, "name": "ContractDefinition", "src": "0:231:11" }], "name": "SourceUnit" } }, + source: `contract test { + int x; + + int y; + + function set(int _x) returns (int _r) + { + x = _x; + y = 10; + _r = x; + } + + function get() returns (uint x, uint y) + { + + } + }` +} + +export default node diff --git a/remix-astwalker/tests/resources/legacyAST.ts b/remix-astwalker/tests/resources/legacyAST.ts new file mode 100644 index 0000000000..ca3898f011 --- /dev/null +++ b/remix-astwalker/tests/resources/legacyAST.ts @@ -0,0 +1,24 @@ +import { Node } from '../../src/' +let node: Node; + +node = { "legacyAST": { "children": [{ "attributes": { "literals": ["solidity", ">=", "0.5", ".0", "<", "0.6", ".0"] }, "id": 1, "name": "PragmaDirective", "src": "0:31:0" }, { "attributes": { "SourceUnit": 53, "absolutePath": "mortal.sol", "file": "mortal.sol", "scope": 26, "symbolAliases": [null], "unitAlias": "" }, "id": 2, "name": "ImportDirective", "src": "32:20:0" }, { "attributes": { "contractDependencies": [52], "contractKind": "contract", "documentation": null, "fullyImplemented": true, "linearizedBaseContracts": [25, 52], "name": "Greeter", "scope": 26 }, "children": [{ "attributes": { "arguments": null }, "children": [{ "attributes": { "contractScope": null, "name": "Mortal", "referencedDeclaration": 52, "type": "contract Mortal" }, "id": 3, "name": "UserDefinedTypeName", "src": "74:6:0" }], "id": 4, "name": "InheritanceSpecifier", "src": "74:6:0" }, { "attributes": { "constant": false, "name": "greeting", "scope": 25, "stateVariable": true, "storageLocation": "default", "type": "string", "value": null, "visibility": "internal" }, "children": [{ "attributes": { "name": "string", "type": "string" }, "id": 5, "name": "ElementaryTypeName", "src": "141:6:0" }], "id": 6, "name": "VariableDeclaration", "src": "141:15:0" }, { "attributes": { "documentation": null, "implemented": true, "isConstructor": true, "kind": "constructor", "modifiers": [null], "name": "", "scope": 25, "stateMutability": "nonpayable", "superFunction": null, "visibility": "public" }, "children": [{ "children": [{ "attributes": { "constant": false, "name": "_greeting", "scope": 16, "stateVariable": false, "storageLocation": "memory", "type": "string", "value": null, "visibility": "internal" }, "children": [{ "attributes": { "name": "string", "type": "string" }, "id": 7, "name": "ElementaryTypeName", "src": "225:6:0" }], "id": 8, "name": "VariableDeclaration", "src": "225:23:0" }], "id": 9, "name": "ParameterList", "src": "224:25:0" }, { "attributes": { "parameters": [null] }, "children": [], "id": 10, "name": "ParameterList", "src": "257:0:0" }, { "children": [{ "children": [{ "attributes": { "argumentTypes": null, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "operator": "=", "type": "string storage ref" }, "children": [{ "attributes": { "argumentTypes": null, "overloadedDeclarations": [null], "referencedDeclaration": 6, "type": "string storage ref", "value": "greeting" }, "id": 11, "name": "Identifier", "src": "267:8:0" }, { "attributes": { "argumentTypes": null, "overloadedDeclarations": [null], "referencedDeclaration": 8, "type": "string memory", "value": "_greeting" }, "id": 12, "name": "Identifier", "src": "278:9:0" }], "id": 13, "name": "Assignment", "src": "267:20:0" }], "id": 14, "name": "ExpressionStatement", "src": "267:20:0" }], "id": 15, "name": "Block", "src": "257:37:0" }], "id": 16, "name": "FunctionDefinition", "src": "213:81:0" }, { "attributes": { "documentation": null, "implemented": true, "isConstructor": false, "kind": "function", "modifiers": [null], "name": "greet", "scope": 25, "stateMutability": "view", "superFunction": null, "visibility": "public" }, "children": [{ "attributes": { "parameters": [null] }, "children": [], "id": 17, "name": "ParameterList", "src": "338:2:0" }, { "children": [{ "attributes": { "constant": false, "name": "", "scope": 24, "stateVariable": false, "storageLocation": "memory", "type": "string", "value": null, "visibility": "internal" }, "children": [{ "attributes": { "name": "string", "type": "string" }, "id": 18, "name": "ElementaryTypeName", "src": "362:6:0" }], "id": 19, "name": "VariableDeclaration", "src": "362:13:0" }], "id": 20, "name": "ParameterList", "src": "361:15:0" }, { "children": [{ "attributes": { "functionReturnParameters": 20 }, "children": [{ "attributes": { "argumentTypes": null, "overloadedDeclarations": [null], "referencedDeclaration": 6, "type": "string storage ref", "value": "greeting" }, "id": 21, "name": "Identifier", "src": "394:8:0" }], "id": 22, "name": "Return", "src": "387:15:0" }], "id": 23, "name": "Block", "src": "377:32:0" }], "id": 24, "name": "FunctionDefinition", "src": "324:85:0" }], "id": 25, "name": "ContractDefinition", "src": "54:357:0" }], "name": "SourceUnit", "attributes": { "absolutePath": "greeter.sol", "exportedSymbols": { "Greeter": [25] } }, "id": 26, "src": "0:412:0" } } + +node.source = `contract test { + int x; + + int y; + + function set(int _x) returns (int _r) + { + x = _x; + y = 10; + _r = x; + } + + function get() returns (uint x, uint y) + { + + } +}` + +export default node; diff --git a/remix-astwalker/tests/resources/newAST.ts b/remix-astwalker/tests/resources/newAST.ts new file mode 100644 index 0000000000..328aa4654b --- /dev/null +++ b/remix-astwalker/tests/resources/newAST.ts @@ -0,0 +1,25 @@ +import { Node } from '../../src/' +let node: Node; + +node = { "ast": { "absolutePath": "greeter.sol", "exportedSymbols": { "Greeter": [25] }, "id": 26, "nodeType": "SourceUnit", "nodes": [{ "id": 1, "literals": ["solidity", ">=", "0.5", ".0", "<", "0.6", ".0"], "nodeType": "PragmaDirective", "src": "0:31:0" }, { "absolutePath": "mortal.sol", "file": "mortal.sol", "id": 2, "nodeType": "ImportDirective", "scope": 26, "sourceUnit": 53, "src": "32:20:0", "symbolAliases": [], "unitAlias": "" }, { "baseContracts": [{ "arguments": null, "baseName": { "contractScope": null, "id": 3, "name": "Mortal", "nodeType": "UserDefinedTypeName", "referencedDeclaration": 52, "src": "74:6:0", "typeDescriptions": { "typeIdentifier": "t_contract$_Mortal_$52", "typeString": "contract Mortal" } }, "id": 4, "nodeType": "InheritanceSpecifier", "src": "74:6:0" }], "contractDependencies": [52], "contractKind": "contract", "documentation": null, "fullyImplemented": true, "id": 25, "linearizedBaseContracts": [25, 52], "name": "Greeter", "nodeType": "ContractDefinition", "nodes": [{ "constant": false, "id": 6, "name": "greeting", "nodeType": "VariableDeclaration", "scope": 25, "src": "141:15:0", "stateVariable": true, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_string_storage", "typeString": "string" }, "typeName": { "id": 5, "name": "string", "nodeType": "ElementaryTypeName", "src": "141:6:0", "typeDescriptions": { "typeIdentifier": "t_string_storage_ptr", "typeString": "string" } }, "value": null, "visibility": "internal" }, { "body": { "id": 15, "nodeType": "Block", "src": "257:37:0", "statements": [{ "expression": { "argumentTypes": null, "id": 13, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "leftHandSide": { "argumentTypes": null, "id": 11, "name": "greeting", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 6, "src": "267:8:0", "typeDescriptions": { "typeIdentifier": "t_string_storage", "typeString": "string storage ref" } }, "nodeType": "Assignment", "operator": "=", "rightHandSide": { "argumentTypes": null, "id": 12, "name": "_greeting", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 8, "src": "278:9:0", "typeDescriptions": { "typeIdentifier": "t_string_memory_ptr", "typeString": "string memory" } }, "src": "267:20:0", "typeDescriptions": { "typeIdentifier": "t_string_storage", "typeString": "string storage ref" } }, "id": 14, "nodeType": "ExpressionStatement", "src": "267:20:0" }] }, "documentation": null, "id": 16, "implemented": true, "kind": "constructor", "modifiers": [], "name": "", "nodeType": "FunctionDefinition", "parameters": { "id": 9, "nodeType": "ParameterList", "parameters": [{ "constant": false, "id": 8, "name": "_greeting", "nodeType": "VariableDeclaration", "scope": 16, "src": "225:23:0", "stateVariable": false, "storageLocation": "memory", "typeDescriptions": { "typeIdentifier": "t_string_memory_ptr", "typeString": "string" }, "typeName": { "id": 7, "name": "string", "nodeType": "ElementaryTypeName", "src": "225:6:0", "typeDescriptions": { "typeIdentifier": "t_string_storage_ptr", "typeString": "string" } }, "value": null, "visibility": "internal" }], "src": "224:25:0" }, "returnParameters": { "id": 10, "nodeType": "ParameterList", "parameters": [], "src": "257:0:0" }, "scope": 25, "src": "213:81:0", "stateMutability": "nonpayable", "superFunction": null, "visibility": "public" }, { "body": { "id": 23, "nodeType": "Block", "src": "377:32:0", "statements": [{ "expression": { "argumentTypes": null, "id": 21, "name": "greeting", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 6, "src": "394:8:0", "typeDescriptions": { "typeIdentifier": "t_string_storage", "typeString": "string storage ref" } }, "functionReturnParameters": 20, "id": 22, "nodeType": "Return", "src": "387:15:0" }] }, "documentation": null, "id": 24, "implemented": true, "kind": "function", "modifiers": [], "name": "greet", "nodeType": "FunctionDefinition", "parameters": { "id": 17, "nodeType": "ParameterList", "parameters": [], "src": "338:2:0" }, "returnParameters": { "id": 20, "nodeType": "ParameterList", "parameters": [{ "constant": false, "id": 19, "name": "", "nodeType": "VariableDeclaration", "scope": 24, "src": "362:13:0", "stateVariable": false, "storageLocation": "memory", "typeDescriptions": { "typeIdentifier": "t_string_memory_ptr", "typeString": "string" }, "typeName": { "id": 18, "name": "string", "nodeType": "ElementaryTypeName", "src": "362:6:0", "typeDescriptions": { "typeIdentifier": "t_string_storage_ptr", "typeString": "string" } }, "value": null, "visibility": "internal" }], "src": "361:15:0" }, "scope": 25, "src": "324:85:0", "stateMutability": "view", "superFunction": null, "visibility": "public" }], "scope": 26, "src": "54:357:0" }], "src": "0:412:0" }, "id": 0 } + + +node.source = `contract test { + int x; + + int y; + + function set(int _x) returns (int _r) + { + x = _x; + y = 10; + _r = x; + } + + function get() returns (uint x, uint y) + { + + } +}` + +export default node; diff --git a/remix-astwalker/tsconfig.json b/remix-astwalker/tsconfig.json new file mode 100644 index 0000000000..934d6d2dff --- /dev/null +++ b/remix-astwalker/tsconfig.json @@ -0,0 +1,29 @@ +{ + "include": ["src"], + "compilerOptions": { + /* Basic Options */ + "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": ["dom", "es2018"], /* Specify library files to be included in the compilation. */ + "declaration": true, /* Generates corresponding '.d.ts' file. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ + "outDir": "./dist", /* Redirect output structure to the directory. */ + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ + + /* Module Resolution Options */ + "baseUrl": "./src", /* Base directory to resolve non-absolute module names. */ + "paths": { "remix-tests": ["./"] }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + "typeRoots": ["node_modules/@types"], /* List of folders to include type definitions from. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "types": [ + "node" + ], + /* Experimental Options */ + "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + "allowSyntheticDefaultImports": true, + // Disables strictNullChecks + "strictNullChecks": false + } +}