diff --git a/remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts b/remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts index 5cc15b5099..d3f4540de0 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts +++ b/remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts @@ -1,9 +1,9 @@ -import { isContractDefinition, getStateVariableDeclarationsFormContractNode, isInheritanceSpecifier, - getInheritsFromName, isModifierDefinition, isModifierInvocation, getContractName, - getFunctionOrModifierDefinitionParameterPart, getType, getDeclaredVariableName, isVariableDeclaration, +import { getStateVariableDeclarationsFormContractNode, + getInheritsFromName, getContractName, + getFunctionOrModifierDefinitionParameterPart, getType, getDeclaredVariableName, getFunctionDefinitionReturnParameterPart } from './staticAnalysisCommon' import { AstWalker } from 'remix-astwalker' -import { CommonAstNode } from 'types' +import { CommonAstNode, FunctionDefinitionAstNode, ParameterListAstNode } from 'types' export default class abstractAstView { contracts = [] @@ -49,7 +49,7 @@ export default class abstractAstView { */ build_visit (relevantNodeFilter) { var that = this - return function (node: CommonAstNode) { + return function (node: any) { if (node.nodeType === "ContractDefinition") { that.setCurrentContract(that, { node: node, @@ -59,7 +59,7 @@ export default class abstractAstView { inheritsFrom: [], stateVariables: getStateVariableDeclarationsFormContractNode(node) }) - } else if (isInheritanceSpecifier(node)) { + } else if (node.nodeType === "InheritanceSpecifier") { const currentContract = that.getCurrentContract(that) const inheritsFromName = getInheritsFromName(node) currentContract.inheritsFrom.push(inheritsFromName) @@ -78,14 +78,14 @@ export default class abstractAstView { that.getCurrentFunction(that).relevantNodes.push(item.node) } }) - } else if (isModifierDefinition(node)) { + } else if (node.nodeType === "ModifierDefinition") { that.setCurrentModifier(that, { node: node, relevantNodes: [], localVariables: that.getLocalVariables(node), parameters: that.getLocalParameters(node) }) - } else if (isModifierInvocation(node)) { + } else if (node.nodeType === "ModifierInvocation") { if (!that.isFunctionNotModifier) throw new Error('abstractAstView.js: Found modifier invocation outside of function scope.') that.getCurrentFunction(that).modifierInvocations.push(node) } else if (relevantNodeFilter(node)) { @@ -160,7 +160,7 @@ export default class abstractAstView { } private getLocalParameters (funcNode) { - return this.getLocalVariables(getFunctionOrModifierDefinitionParameterPart(funcNode)).map(getType) + return getFunctionOrModifierDefinitionParameterPart(funcNode).parameters.map(getType) } private getReturnParameters (funcNode) { @@ -172,10 +172,10 @@ export default class abstractAstView { }) } - private getLocalVariables (funcNode) { + private getLocalVariables (funcNode: ParameterListAstNode) { const locals: any[] = [] new AstWalker().walk(funcNode, {'*': function (node) { - if (isVariableDeclaration(node)) locals.push(node) + if (node.nodeType === "VariableDeclaration") locals.push(node) return true }}) return locals diff --git a/remix-analyzer/src/solidity-analyzer/modules/constantFunctions.ts b/remix-analyzer/src/solidity-analyzer/modules/constantFunctions.ts index e176495927..b55d40a925 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/constantFunctions.ts +++ b/remix-analyzer/src/solidity-analyzer/modules/constantFunctions.ts @@ -1,12 +1,12 @@ import { default as category } from './categories' -import { isLowLevelCall, isTransfer, isExternalDirectCall, isEffect, isLocalCallGraphRelevantNode, - isInlineAssembly, isNewExpression, isSelfdestructCall, isDeleteUnaryOperation, isPayableFunction, +import { isLowLevelCall, isTransfer, isExternalDirectCall, isEffect, isLocalCallGraphRelevantNode, + isSelfdestructCall, isDeleteUnaryOperation, isPayableFunction, isConstructor, getFullQuallyfiedFuncDefinitionIdent, hasFunctionBody, isConstantFunction, isWriteOnStateVariable, isStorageVariableDeclaration, isCallToNonConstLocalFunction, getFullQualifiedFunctionCallIdent} from './staticAnalysisCommon' import { default as algorithm } from './algorithmCategories' import { buildGlobalFuncCallGraph, resolveCallGraphSymbol, analyseCallGraph } from './functionCallGraph' import AbstractAst from './abstractAstView' -import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types' +import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, CommonAstNode} from './../../types' export default class constantFunctions implements AnalyzerModule { name: string = 'Constant functions: ' @@ -17,13 +17,13 @@ export default class constantFunctions implements AnalyzerModule { abstractAst: AbstractAst = new AbstractAst() visit = this.abstractAst.build_visit( - (node: AstNodeLegacy) => isLowLevelCall(node) || + (node: CommonAstNode) => isLowLevelCall(node) || isTransfer(node) || isExternalDirectCall(node) || isEffect(node) || isLocalCallGraphRelevantNode(node) || - isInlineAssembly(node) || - isNewExpression(node) || + node.nodeType === "InlineAssembly" || + node.nodeType === "NewExpression" || isSelfdestructCall(node) || isDeleteUnaryOperation(node) ) @@ -98,8 +98,8 @@ export default class constantFunctions implements AnalyzerModule { isTransfer(node) || this.isCallOnNonConstExternalInterfaceFunction(node, context) || isCallToNonConstLocalFunction(node) || - isInlineAssembly(node) || - isNewExpression(node) || + node.nodeType === "InlineAssembly" || + node.nodeType === "NewExpression" || isSelfdestructCall(node) || isDeleteUnaryOperation(node) } diff --git a/remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.ts b/remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.ts index bf15be2c5f..43d8558718 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.ts +++ b/remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.ts @@ -1,35 +1,26 @@ import { default as category } from './categories' import { default as algorithm } from './algorithmCategories' -import { isLoop, isBlock, getLoopBlockStartIndex, isExpressionStatement, isTransfer } from './staticAnalysisCommon' -import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types' +import { getLoopBlockStartIndex, isTransfer } from './staticAnalysisCommon' +import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, ForStatementAstNode, WhileStatementAstNode, CommonAstNode, ExpressionStatementAstNode} from './../../types' export default class etherTransferInLoop implements AnalyzerModule { - relevantNodes: AstNodeLegacy[] = [] + relevantNodes: CommonAstNode[] = [] name: string = 'Ether transfer in a loop: ' description: string = 'Avoid transferring Ether to multiple addresses in a loop' category: ModuleCategory = category.GAS algorithm: ModuleAlgorithm = algorithm.EXACT - visit (node: AstNodeLegacy): void { - if (isLoop(node)) { - let transferNodes: AstNodeLegacy[] = [] - const loopBlockStartIndex: number | undefined = getLoopBlockStartIndex(node) - if (loopBlockStartIndex && node.children && isBlock(node.children[loopBlockStartIndex])) { - const childrenNodes: AstNodeLegacy[] | undefined = node.children[loopBlockStartIndex].children - if(childrenNodes) - transferNodes = childrenNodes.filter(child => ( - isExpressionStatement(child) && - child.children && - child.children[0].name === 'FunctionCall' && - child.children[0].children && - isTransfer(child.children[0].children[0]) - ) - ) - if (transferNodes.length > 0) { - this.relevantNodes.push(...transferNodes) - } + visit (node: ForStatementAstNode | WhileStatementAstNode): void { + let transferNodes: CommonAstNode[] = [] + transferNodes = node.body.statements.filter(child => ( + child.nodeType === 'ExpressionStatement' && + child.expression.nodeType === 'FunctionCall' && + isTransfer(child.expression.expression) + ) + ) + if (transferNodes.length > 0) { + this.relevantNodes.push(...transferNodes) } - } } report (compilationResults: CompilationResult): ReportObj[] { diff --git a/remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.ts b/remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.ts index f33fd05eaf..4192ca31d5 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.ts +++ b/remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.ts @@ -1,17 +1,17 @@ import { default as category } from './categories' import { default as algorithm } from './algorithmCategories' import { isForLoop, isDynamicArrayLengthAccess, isBinaryOperation } from './staticAnalysisCommon' -import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types' +import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, CommonAstNode} from './../../types' export default class forLoopIteratesOverDynamicArray implements AnalyzerModule { - relevantNodes: AstNodeLegacy[] = [] + relevantNodes: CommonAstNode[] = [] name: string = 'For loop iterates over dynamic array: ' description: string = 'The number of \'for\' loop iterations depends on dynamic array\'s size' category: ModuleCategory = category.GAS algorithm: ModuleAlgorithm = algorithm.EXACT - visit (node: AstNodeLegacy): void { - if (isForLoop(node) && node.children) { + visit (node: CommonAstNode): void { + if (node.nodeType === "Forstatement" && node.children) { let conditionChildrenNode: AstNodeLegacy | null = null // Access 'condition' node of 'for' loop statement const forLoopConditionNode: AstNodeLegacy = node.children[1] diff --git a/remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts b/remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts index df7e253fa4..d9b7991506 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts +++ b/remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts @@ -1,17 +1,16 @@ import { default as category } from './categories' -import { isInlineAssembly } from './staticAnalysisCommon' import { default as algorithm } from './algorithmCategories' -import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types' +import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, InlineAssemblyAstNode} from './../../types' export default class inlineAssembly implements AnalyzerModule { - inlineAssNodes: AstNodeLegacy[] = [] + inlineAssNodes: InlineAssemblyAstNode[] = [] name: string = 'Inline assembly: ' description: string = 'Use of Inline Assembly' category: ModuleCategory = category.SECURITY algorithm: ModuleAlgorithm = algorithm.EXACT - visit (node: AstNodeLegacy): void { - if (isInlineAssembly(node)) this.inlineAssNodes.push(node) + visit (node: InlineAssemblyAstNode): void { + this.inlineAssNodes.push(node) } report (compilationResults: CompilationResult): ReportObj[] { diff --git a/remix-analyzer/src/solidity-analyzer/modules/noReturn.ts b/remix-analyzer/src/solidity-analyzer/modules/noReturn.ts index eaa747f0a7..a1368a4d30 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/noReturn.ts +++ b/remix-analyzer/src/solidity-analyzer/modules/noReturn.ts @@ -1,8 +1,8 @@ import { default as category } from './categories' -import { isReturn, isAssignment, hasFunctionBody, getFullQuallyfiedFuncDefinitionIdent, getEffectedVariableName } from './staticAnalysisCommon' +import { hasFunctionBody, getFullQuallyfiedFuncDefinitionIdent, getEffectedVariableName } from './staticAnalysisCommon' import { default as algorithm } from './algorithmCategories' import AbstractAst from './abstractAstView' -import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types' +import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, CommonAstNode, FunctionDefinitionAstNode} from './../../types' export default class noReturn implements AnalyzerModule { name: string = 'no return: ' @@ -13,7 +13,7 @@ export default class noReturn implements AnalyzerModule { abstractAst: AbstractAst = new AbstractAst() visit = this.abstractAst.build_visit( - (node: AstNodeLegacy) => isReturn(node) || isAssignment(node) + (node: CommonAstNode) => node.nodeType === "Return" || node.nodeType === "Assignment" ) report = this.abstractAst.build_report(this._report.bind(this)) @@ -44,13 +44,13 @@ export default class noReturn implements AnalyzerModule { return func.returns.length > 0 } - private hasReturnStatement (func): boolean { - return func.relevantNodes.filter(isReturn).length > 0 + private hasReturnStatement (func: CommonAstNode): boolean { + return func.relevantNodes.filter(n => n.nodeType === "Return").length > 0 } private hasAssignToAllNamedReturns (func): boolean { const namedReturns = func.returns.filter((n) => n.name.length > 0).map((n) => n.name) - const assignedVars = func.relevantNodes.filter(isAssignment).map(getEffectedVariableName) + const assignedVars = func.relevantNodes.filter(n => n.nodeType === "Assignment").map(getEffectedVariableName) const diff = namedReturns.filter(e => !assignedVars.includes(e)) return diff.length === 0 } diff --git a/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts b/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts index 416b5d569e..5df07b50d7 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts +++ b/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts @@ -1,6 +1,6 @@ 'use strict' -import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode } from "types" +import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, CommonAstNode, ForStatementAstNode, WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode, MemberAccessAstNode } from "types" const remixLib = require('remix-lib') const util = remixLib.util @@ -125,8 +125,8 @@ const abiNamespace = { // #################### Trivial Getters -function getType (node) { - return node.attributes.type +function getType (node: CommonAstNode) { + return node.nodeType } // #################### Complex Getters @@ -149,7 +149,7 @@ function getFunctionCallType (func) { * @return {string} variable name written to */ function getEffectedVariableName (effectNode) { - if (!isEffect(effectNode) || isInlineAssembly(effectNode)) throw new Error('staticAnalysisCommon.js: not an effect Node or inline assembly') + if (!isEffect(effectNode) || effectNode.nodeType === "InlineAssembly") throw new Error('staticAnalysisCommon.js: not an effect Node or inline assembly') return findFirstSubNodeLTR(effectNode, exactMatch(nodeTypes.IDENTIFIER)).attributes.value } @@ -234,9 +234,8 @@ function getExternalDirectCallMemberName (extDirectCall) { * @contract {ASTNode} Contract Definition node * @return {string} name of a contract defined */ -function getContractName (contract) { - if (!isContractDefinition(contract)) throw new Error('staticAnalysisCommon.js: not an contractDefinition Node') - return contract.attributes.name +function getContractName (contract: ContractDefinitionAstNode) { + return contract.name } /** @@ -258,9 +257,8 @@ function getFunctionDefinitionName (funcDef: FunctionDefinitionAstNode): string * @func {ASTNode} Inheritance specifier * @return {string} name of contract inherited from */ -function getInheritsFromName (inheritsNode) { - if (!isInheritanceSpecifier(inheritsNode)) throw new Error('staticAnalysisCommon.js: not an InheritanceSpecifier Node') - return inheritsNode.children[0].attributes.name +function getInheritsFromName (inheritsNode: InheritanceSpecifierAstNode) { + return inheritsNode.baseName } /** @@ -270,9 +268,8 @@ function getInheritsFromName (inheritsNode) { * @varDeclNode {ASTNode} Variable declaration node * @return {string} variable name */ -function getDeclaredVariableName (varDeclNode) { - if (!isVariableDeclaration(varDeclNode)) throw new Error('staticAnalysisCommon.js: not a variable declaration') - return varDeclNode.attributes.name +function getDeclaredVariableName (varDeclNode: VariableDeclarationAstNode) { + return varDeclNode.name } /** @@ -282,9 +279,8 @@ function getDeclaredVariableName (varDeclNode) { * @varDeclNode {ASTNode} Variable declaration node * @return {string} variable type */ -function getDeclaredVariableType (varDeclNode) { - if (!isVariableDeclaration(varDeclNode)) throw new Error('staticAnalysisCommon.js: not a variable declaration') - return varDeclNode.attributes.type +function getDeclaredVariableType (varDeclNode: VariableDeclarationAstNode) { + return varDeclNode.typeName } /** @@ -297,10 +293,8 @@ function getDeclaredVariableType (varDeclNode) { * @contractNode {ASTNode} Contract Definition node * @return {list variable declaration} state variable node list */ -function getStateVariableDeclarationsFormContractNode (contractNode) { - if (!isContractDefinition(contractNode)) throw new Error('staticAnalysisCommon.js: not a contract definition declaration') - if (!contractNode.children) return [] - return contractNode.children.filter((el) => isVariableDeclaration(el)) +function getStateVariableDeclarationsFormContractNode (contractNode: ContractDefinitionAstNode): CommonAstNode[] { + return contractNode.nodes.filter(el => el.nodeType === "VariableDeclaration") } /** @@ -380,7 +374,7 @@ function getLibraryCallContractName (funcCall) { * @return {string} name of function called on the library */ function getLibraryCallMemberName (funcCall) { - if (!isLibraryCall(funcCall)) throw new Error('staticAnalysisCommon.js: not an library call Node') + // if (!isLibraryCall(funcCall)) throw new Error('staticAnalysisCommon.js: not an library call Node') return funcCall.attributes.member_name } @@ -413,73 +407,14 @@ function getUnAssignedTopLevelBinOps (subScope) { return subScope.children.filter(isBinaryOpInExpression) } -function getLoopBlockStartIndex (node) { - if (isLoop(node)) { - if (nodeType(node, exactMatch(nodeTypes.FORSTATEMENT))) { - return 3 // For 'for' loop - } else { - return 1 // For 'while' and 'do-while' loop - } - } +function getLoopBlockStartIndex (node: ForStatementAstNode | WhileStatementAstNode): 3|1 { + return node.nodeType === "ForStatement" ? 3 : 1 } // #################### Trivial Node Identification -// function isFunctionDefinition (node) { -// return nodeType(node, exactMatch(nodeTypes.FUNCTIONDEFINITION)) -// } - -function isStatement (node) { - return nodeType(node, 'Statement$') || isBlock(node) || isReturn(node) -} - -function isBlock (node) { - return nodeType(node, exactMatch(nodeTypes.BLOCK)) -} - -function isModifierDefinition (node) { - return nodeType(node, exactMatch(nodeTypes.MODIFIERDEFINITION)) -} - -function isModifierInvocation (node) { - return nodeType(node, exactMatch(nodeTypes.MODIFIERINVOCATION)) -} - -function isVariableDeclaration (node) { - return nodeType(node, exactMatch(nodeTypes.VARIABLEDECLARATION)) -} - -function isReturn (node) { - return nodeType(node, exactMatch(nodeTypes.RETURN)) -} - -function isInheritanceSpecifier (node) { - return nodeType(node, exactMatch(nodeTypes.INHERITANCESPECIFIER)) -} - -function isAssignment (node) { - return nodeType(node, exactMatch(nodeTypes.ASSIGNMENT)) -} - -function isContractDefinition (node) { - return nodeType(node, exactMatch(nodeTypes.CONTRACTDEFINITION)) -} - -function isInlineAssembly (node) { - return nodeType(node, exactMatch(nodeTypes.INLINEASSEMBLY)) -} - -function isNewExpression (node) { - return nodeType(node, exactMatch(nodeTypes.NEWEXPRESSION)) -} - -/** - * True if is Expression - * @node {ASTNode} some AstNode - * @return {bool} - */ -function isExpressionStatement (node) { - return nodeType(node, exactMatch(nodeTypes.EXPRESSIONSTATEMENT)) +function isStatement (node: CommonAstNode) { + return nodeType(node, 'Statement$') || node.nodeType === "Block" || node.nodeType === "Return" } /** @@ -618,8 +553,8 @@ function isRequireCall (node) { * @node {ASTNode} some AstNode * @return {bool} */ -function isStorageVariableDeclaration (node) { - return isVariableDeclaration(node) && expressionType(node, basicRegex.REFTYPE) +function isStorageVariableDeclaration (node: VariableDeclarationAstNode): boolean { + return expressionType(node, basicRegex.REFTYPE) } /** @@ -637,7 +572,7 @@ function isInteraction (node) { * @return {bool} */ function isEffect (node) { - return isAssignment(node) || isPlusPlusUnaryOperation(node) || isMinusMinusUnaryOperation(node) || isInlineAssembly(node) + return node.nodeType === "Assignment" || isPlusPlusUnaryOperation(node) || isMinusMinusUnaryOperation(node) || node.nodeType === "InlineAssembly" } /** @@ -647,7 +582,7 @@ function isEffect (node) { * @return {bool} */ function isWriteOnStateVariable (effectNode, stateVariables) { - return isInlineAssembly(effectNode) || (isEffect(effectNode) && isStateVariable(getEffectedVariableName(effectNode), stateVariables)) + return effectNode.nodeType === "InlineAssembly" || (isEffect(effectNode) && isStateVariable(getEffectedVariableName(effectNode), stateVariables)) } /** @@ -720,7 +655,7 @@ function isSubScopeStatement (node) { * @return {bool} */ function isBinaryOpInExpression (node) { - return isExpressionStatement(node) && nrOfChildren(node, 1) && isBinaryOperation(node.children[0]) + return node.nodeType === "ExpressionStatement" && nrOfChildren(node, 1) && isBinaryOperation(node.children[0]) } /** @@ -978,16 +913,17 @@ function isBytesLengthCheck (node) { * @node {ASTNode} some AstNode * @return {bool} */ -function isLoop (node) { - return nodeType(node, exactMatch(nodeTypes.FORSTATEMENT)) || - nodeType(node, exactMatch(nodeTypes.WHILESTATEMENT)) || - nodeType(node, exactMatch(nodeTypes.DOWHILESTATEMENT)) -} +// function isLoop (node) { +// return nodeType(node, exactMatch(nodeTypes.FORSTATEMENT)) || +// nodeType(node, exactMatch(nodeTypes.WHILESTATEMENT)) || +// nodeType(node, exactMatch(nodeTypes.DOWHILESTATEMENT)) +// } /** * True if it is a 'for' loop * @node {ASTNode} some AstNode * @return {bool} + * TODO: This should be removed once for loop iterates Over dynamic array fixed */ function isForLoop (node) { return nodeType(node, exactMatch(nodeTypes.FORSTATEMENT)) @@ -995,13 +931,13 @@ function isForLoop (node) { // #################### Complex Node Identification - Private -function isMemberAccess (node, retType, accessor, accessorType, memberName) { +function isMemberAccess (node: MemberAccessAstNode, retType, accessor, accessorType, memberName) { return nodeType(node, exactMatch(nodeTypes.MEMBERACCESS)) && expressionType(node, retType) && memName(node, memberName) && nrOfChildren(node, 1) && - memName(node.children[0], accessor) && - expressionType(node.children[0], accessorType) + memName(node.expression, accessor) && + expressionType(node.expression, accessorType) } function isSpecialVariableAccess (node, varType) { @@ -1168,28 +1104,27 @@ export { isIntDivision, isStringToBytesConversion, isBytesLengthCheck, - isLoop, isForLoop, // #################### Trivial Node Identification isDeleteUnaryOperation, // isFunctionDefinition, - isModifierDefinition, - isInheritanceSpecifier, - isModifierInvocation, - isVariableDeclaration, + // isModifierDefinition, + // isInheritanceSpecifier, + // isModifierInvocation, + // isVariableDeclaration, isStorageVariableDeclaration, - isAssignment, - isContractDefinition, + // isAssignment, + // isContractDefinition, isConstantFunction, isPayableFunction, isConstructor, - isInlineAssembly, - isNewExpression, - isReturn, + // isInlineAssembly, + // isNewExpression, + // isReturn, isStatement, - isExpressionStatement, - isBlock, + // isExpressionStatement, + // isBlock, isBinaryOperation, // #################### Constants diff --git a/remix-analyzer/src/types.ts b/remix-analyzer/src/types.ts index f21a8ae6da..e2027bf7c5 100644 --- a/remix-analyzer/src/types.ts +++ b/remix-analyzer/src/types.ts @@ -95,7 +95,7 @@ export interface ContractDefinitionAstNode { linearizedBaseContracts: Array baseContracts: Array contractDependencies: Array - nodes: Array + nodes: Array scope: number } @@ -298,7 +298,7 @@ export interface BlockAstNode { id: number nodeType: 'Block' src: string - statements: Array + statements: Array } export interface PlaceholderStatementAstNode { diff --git a/remix-analyzer/test/analysis/staticAnalysisCommon-test.ts b/remix-analyzer/test/analysis/staticAnalysisCommon-test.ts index 3dc629ac05..8dcfa00f22 100644 --- a/remix-analyzer/test/analysis/staticAnalysisCommon-test.ts +++ b/remix-analyzer/test/analysis/staticAnalysisCommon-test.ts @@ -317,89 +317,89 @@ test('staticAnalysisCommon.getLoopBlockStartIndex', function (t) { // t.notOk(common.isFunctionDefinition(node3), 'substring should not work') // }) -test('staticAnalysisCommon.isModifierDefinition', function (t) { - t.plan(3) - const node1 = { name: 'ModifierDefinition' } - const node2 = { name: 'MemberAccess' } - const node3 = { name: 'ModifierDefinitionBLABLA' } +// test('staticAnalysisCommon.isModifierDefinition', function (t) { +// t.plan(3) +// const node1 = { name: 'ModifierDefinition' } +// const node2 = { name: 'MemberAccess' } +// const node3 = { name: 'ModifierDefinitionBLABLA' } - t.ok(common.isModifierDefinition(node1), 'is exact match should work') - t.notOk(common.isModifierDefinition(node2), 'different node should not work') - t.notOk(common.isModifierDefinition(node3), 'substring should not work') -}) +// t.ok(common.isModifierDefinition(node1), 'is exact match should work') +// t.notOk(common.isModifierDefinition(node2), 'different node should not work') +// t.notOk(common.isModifierDefinition(node3), 'substring should not work') +// }) -test('staticAnalysisCommon.isModifierInvocation', function (t) { - t.plan(3) - const node1 = { name: 'ModifierInvocation' } - const node2 = { name: 'MemberAccess' } - const node3 = { name: 'ModifierInvocationBLABLA' } +// test('staticAnalysisCommon.isModifierInvocation', function (t) { +// t.plan(3) +// const node1 = { name: 'ModifierInvocation' } +// const node2 = { name: 'MemberAccess' } +// const node3 = { name: 'ModifierInvocationBLABLA' } - t.ok(common.isModifierInvocation(node1), 'is exact match should work') - t.notOk(common.isModifierInvocation(node2), 'different node should not work') - t.notOk(common.isModifierInvocation(node3), 'substring should not work') -}) +// t.ok(common.isModifierInvocation(node1), 'is exact match should work') +// t.notOk(common.isModifierInvocation(node2), 'different node should not work') +// t.notOk(common.isModifierInvocation(node3), 'substring should not work') +// }) -test('staticAnalysisCommon.isVariableDeclaration', function (t) { - t.plan(3) - const node1 = { name: 'VariableDeclaration' } - const node2 = { name: 'MemberAccess' } - const node3 = { name: 'VariableDeclarationBLABLA' } +// test('staticAnalysisCommon.isVariableDeclaration', function (t) { +// t.plan(3) +// const node1 = { name: 'VariableDeclaration' } +// const node2 = { name: 'MemberAccess' } +// const node3 = { name: 'VariableDeclarationBLABLA' } - t.ok(common.isVariableDeclaration(node1), 'is exact match should work') - t.notOk(common.isVariableDeclaration(node2), 'different node should not work') - t.notOk(common.isVariableDeclaration(node3), 'substring should not work') -}) +// t.ok(common.isVariableDeclaration(node1), 'is exact match should work') +// t.notOk(common.isVariableDeclaration(node2), 'different node should not work') +// t.notOk(common.isVariableDeclaration(node3), 'substring should not work') +// }) -test('staticAnalysisCommon.isInheritanceSpecifier', function (t) { - t.plan(3) - const node1 = { name: 'InheritanceSpecifier' } - const node2 = { name: 'MemberAccess' } - const node3 = { name: 'InheritanceSpecifierBLABLA' } +// test('staticAnalysisCommon.isInheritanceSpecifier', function (t) { +// t.plan(3) +// const node1 = { name: 'InheritanceSpecifier' } +// const node2 = { name: 'MemberAccess' } +// const node3 = { name: 'InheritanceSpecifierBLABLA' } - t.ok(common.isInheritanceSpecifier(node1), 'is exact match should work') - t.notOk(common.isInheritanceSpecifier(node2), 'different node should not work') - t.notOk(common.isInheritanceSpecifier(node3), 'substring should not work') -}) +// t.ok(common.isInheritanceSpecifier(node1), 'is exact match should work') +// t.notOk(common.isInheritanceSpecifier(node2), 'different node should not work') +// t.notOk(common.isInheritanceSpecifier(node3), 'substring should not work') +// }) -test('staticAnalysisCommon.isAssignment', function (t) { - t.plan(3) - const node1 = { name: 'Assignment' } - const node2 = { name: 'MemberAccess' } - const node3 = { name: 'AssignmentBLABLA' } +// test('staticAnalysisCommon.isAssignment', function (t) { +// t.plan(3) +// const node1 = { name: 'Assignment' } +// const node2 = { name: 'MemberAccess' } +// const node3 = { name: 'AssignmentBLABLA' } - t.ok(common.isAssignment(node1), 'is exact match should work') - t.notOk(common.isAssignment(node2), 'different node should not work') - t.notOk(common.isAssignment(node3), 'substring should not work') -}) +// t.ok(common.isAssignment(node1), 'is exact match should work') +// t.notOk(common.isAssignment(node2), 'different node should not work') +// t.notOk(common.isAssignment(node3), 'substring should not work') +// }) -test('staticAnalysisCommon.isContractDefinition', function (t) { - t.plan(3) - const node1 = { name: 'ContractDefinition' } - const node2 = { name: 'MemberAccess' } - const node3 = { name: 'ContractDefinitionBLABLA' } +// test('staticAnalysisCommon.isContractDefinition', function (t) { +// t.plan(3) +// const node1 = { name: 'ContractDefinition' } +// const node2 = { name: 'MemberAccess' } +// const node3 = { name: 'ContractDefinitionBLABLA' } - t.ok(common.isContractDefinition(node1), 'is exact match should work') - t.notOk(common.isContractDefinition(node2), 'different node should not work') - t.notOk(common.isContractDefinition(node3), 'substring should not work') -}) +// t.ok(common.isContractDefinition(node1), 'is exact match should work') +// t.notOk(common.isContractDefinition(node2), 'different node should not work') +// t.notOk(common.isContractDefinition(node3), 'substring should not work') +// }) -test('staticAnalysisCommon.isInlineAssembly', function (t) { - t.plan(3) - const node1 = { name: 'InlineAssembly' } - const node2 = { name: 'MemberAccess' } - const node3 = { name: 'InlineAssemblyBLABLA' } +// test('staticAnalysisCommon.isInlineAssembly', function (t) { +// t.plan(3) +// const node1 = { name: 'InlineAssembly' } +// const node2 = { name: 'MemberAccess' } +// const node3 = { name: 'InlineAssemblyBLABLA' } - t.ok(common.isInlineAssembly(node1), 'is exact match should work') - t.notOk(common.isInlineAssembly(node2), 'different node should not work') - t.notOk(common.isInlineAssembly(node3), 'substring should not work') -}) +// t.ok(common.isInlineAssembly(node1), 'is exact match should work') +// t.notOk(common.isInlineAssembly(node2), 'different node should not work') +// t.notOk(common.isInlineAssembly(node3), 'substring should not work') +// }) -test('staticAnalysisCommon.isLoop', function (t) { - t.plan(3) - t.equal(common.isLoop(forLoopNode), true) - t.equal(common.isLoop(doWhileLoopNode), true) - t.equal(common.isLoop(whileLoopNode), true) -}) +// test('staticAnalysisCommon.isLoop', function (t) { +// t.plan(3) +// t.equal(common.isLoop(forLoopNode), true) +// t.equal(common.isLoop(doWhileLoopNode), true) +// t.equal(common.isLoop(whileLoopNode), true) +// }) // #################### Complex Node Identification