Simplify. Also try to address yann300's concerns

pull/5370/head
rocky 6 years ago
parent 6ddc8d11ee
commit 13b96ada6c
  1. 47
      remix-astwalker/src/astWalker.ts
  2. 38
      remix-astwalker/src/sourceMappings.ts
  3. 6
      remix-astwalker/src/types.ts
  4. 292
      remix-astwalker/tests/resources/newAST.ts

@ -22,6 +22,10 @@ export class AstWalker extends EventEmitter {
node: AstNodeLegacy | AstNode,
callback: Object | Function
): any {
// FIXME: we shouldn't be doing this callback determination type on each AST node,
// since the callback function is set once per walk.
// Better would be to store the right one as a variable and
// return that.
if (<AstNodeLegacy>node) {
if ((<AstNodeLegacy>node).name in callback) {
return callback[(<AstNodeLegacy>node).name](node);
@ -98,22 +102,26 @@ export class AstWalker extends EventEmitter {
}
}
walkFullInternal(ast: AstNode, callback?: Function | Object) {
function isObject(obj: any): boolean {
return obj != null && obj.constructor.name === "Object"
}
function isAstNode(node: Object): boolean {
return (
isObject(node) &&
'id' in node &&
'nodeType' in node &&
'src' in node
);
}
isObject(obj: any): boolean {
return obj != null && obj.constructor.name === "Object"
}
isAstNode(node: Object): boolean {
return (
this.isObject(node) &&
'id' in node &&
'nodeType' in node &&
'src' in node
)
}
walkFullInternal(ast: AstNode, callback: Function) {
if (isAstNode(ast) && this.manageCallback(ast, callback)) {
if (this.isAstNode(ast)) {
// console.log(`XXX id ${ast.id}, nodeType: ${ast.nodeType}, src: ${ast.src}`);
callback(ast);
for (let k of Object.keys(ast)) {
if (k in ['id', 'src', 'nodeType']) continue;
const astItem = ast[k];
if (Array.isArray(astItem)) {
for (let child of astItem) {
@ -129,17 +137,8 @@ export class AstWalker extends EventEmitter {
}
// Normalizes parameter callback and calls walkFullInternal
walkFull(ast: AstNode, callback?: Function | Object) {
if (callback) {
if (callback instanceof Function) {
callback = Object({ "*": callback });
}
if (!("*" in callback)) {
callback["*"] = function() {
return true;
};
}
}
walkFull(ast: AstNode, callback: any) {
if (!this.isAstNode(ast)) throw new TypeError("first argument should an ast");
return this.walkFullInternal(ast, callback);
}

@ -30,52 +30,42 @@ export class SourceMappings {
constructor(source: string) {
this.source = source;
this.lineBreaks = this.getLinebreakPositions();
// Create a list of line offsets which will be used to map between
// character offset and line/column positions.
let lineBreaks: Array<number> = [];
for (var pos = source.indexOf('\n'); pos >= 0; pos = source.indexOf('\n', pos + 1)) {
lineBreaks.push(pos)
}
this.lineBreaks = lineBreaks;
};
/**
* get a list of nodes that are at the given @arg offset
* get a list of nodes that are at the given @arg position
*
* @param {String} astNodeType - type of node to return or null
* @param {Int} position - character offset
* @return {Object} ast object given by the compiler
*/
nodesAtPosition(astNodeType: string | null, position: number, ast: AstNode): Array<AstNode> {
nodesAtPosition(astNodeType: string | null, position: Location, ast: AstNode): Array<AstNode> {
const astWalker = new AstWalker()
const callback = {}
let found: Array<AstNode> = [];
/* FIXME: Looking at AST walker code,
I don't understand a need to return a boolean. */
callback['*'] = function(node: AstNode): boolean {
const callback = function(node: AstNode): boolean {
let nodeLocation = sourceLocationFromAstNode(node);
if (nodeLocation &&
nodeLocation.start <= position &&
nodeLocation.start + nodeLocation.length >= position) {
nodeLocation.start == position.start &&
nodeLocation.length == position.length) {
if (!astNodeType || astNodeType === node.name) {
found.push(node)
}
}
return true;
}
astWalker.walk(ast, callback);
astWalker.walkFull(ast, callback);
return found;
}
/**
* Retrieve line/column position of each source char
*
* @param {String} source - contract source code
* @return {Array} returns an array containing offset of line breaks
*/
getLinebreakPositions(source: string = this.source): Array<number> {
let ret: Array<number> = [];
for (var pos = source.indexOf('\n'); pos >= 0; pos = source.indexOf('\n', pos + 1)) {
ret.push(pos)
}
return ret;
}
findNodeAtSourceLocation(astNodeType: string, sourceLocation: Location, ast: AstNode | null) {
const astWalker = new AstWalker()
const callback = {};

@ -30,10 +30,10 @@ export interface AstNode {
}
export interface AstNodeLegacy {
id: number;
name: string; // This corresponds to nodeType in current AST
id: number; // This is unique across all nodes in an AST tree
name: string; // This corresponds to "nodeType" in ASTNode
src: string;
children?: Array<AstNodeLegacy>; // This corresponds to nodes in current AST
children?: Array<AstNodeLegacy>; // This corresponds to "nodes" in ASTNode
attributes?: AstNodeAtt;
}

@ -1,7 +1,297 @@
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 = {
"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"
}
}
node.source = `contract test {

Loading…
Cancel
Save