From ecf8c3df348466b812b57cb75dc70ec6dd027ed1 Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 26 Mar 2024 13:51:12 +0100 Subject: [PATCH] Make using-for utils --- slither/core/declarations/contract.py | 25 +++++-------------- .../core/declarations/function_top_level.py | 22 ++++------------ .../core/declarations/using_for_top_level.py | 4 +-- slither/slithir/convert.py | 8 +++--- slither/solc_parsing/declarations/contract.py | 3 ++- slither/utils/using_for.py | 17 +++++++++++++ 6 files changed, 36 insertions(+), 43 deletions(-) create mode 100644 slither/utils/using_for.py diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 7224859c63..4400bc265d 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -9,9 +9,8 @@ from crytic_compile.platform import Type as PlatformType from slither.core.cfg.scope import Scope -from slither.core.solidity_types.type import Type from slither.core.source_mapping.source_mapping import SourceMapping - +from slither.utils.using_for import USING_FOR, _merge_using_for from slither.core.declarations.function import Function, FunctionType, FunctionLanguage from slither.utils.erc import ( ERC20_signatures, @@ -50,9 +49,6 @@ LOGGER = logging.getLogger("Contract") -USING_FOR_KEY = Union[str, Type] -USING_FOR_ITEM = List[Union[Type, Function]] - class Contract(SourceMapping): # pylint: disable=too-many-public-methods """ @@ -87,8 +83,8 @@ def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope self._type_aliases: Dict[str, "TypeAliasContract"] = {} # The only str is "*" - self._using_for: Dict[USING_FOR_KEY, USING_FOR_ITEM] = {} - self._using_for_complete: Optional[Dict[USING_FOR_KEY, USING_FOR_ITEM]] = None + self._using_for: USING_FOR = {} + self._using_for_complete: Optional[USING_FOR] = None self._kind: Optional[str] = None self._is_interface: bool = False self._is_library: bool = False @@ -310,24 +306,15 @@ def events_as_dict(self) -> Dict[str, "EventContract"]: ################################################################################### @property - def using_for(self) -> Dict[USING_FOR_KEY, USING_FOR_ITEM]: + def using_for(self) -> USING_FOR: return self._using_for @property - def using_for_complete(self) -> Dict[USING_FOR_KEY, USING_FOR_ITEM]: + def using_for_complete(self) -> USING_FOR: """ - Dict[Union[str, Type], List[Type]]: Dict of merged local using for directive with top level directive + USING_FOR: Dict of merged local using for directive with top level directive """ - def _merge_using_for( - uf1: Dict[USING_FOR_KEY, USING_FOR_ITEM], uf2: Dict[USING_FOR_KEY, USING_FOR_ITEM] - ) -> Dict[USING_FOR_KEY, USING_FOR_ITEM]: - result = {**uf1, **uf2} - for key, value in result.items(): - if key in uf1 and key in uf2: - result[key] = value + uf1[key] - return result - if self._using_for_complete is None: result = self.using_for top_level_using_for = self.file_scope.using_for_directives diff --git a/slither/core/declarations/function_top_level.py b/slither/core/declarations/function_top_level.py index 03785fe209..e0dcd25579 100644 --- a/slither/core/declarations/function_top_level.py +++ b/slither/core/declarations/function_top_level.py @@ -1,46 +1,34 @@ """ Function module """ -from typing import Dict, List, Tuple, TYPE_CHECKING, Union, Optional +from typing import Dict, List, Tuple, TYPE_CHECKING, Optional from slither.core.declarations import Function from slither.core.declarations.top_level import TopLevel -from slither.core.solidity_types.type import Type +from slither.utils.using_for import USING_FOR, _merge_using_for if TYPE_CHECKING: from slither.core.compilation_unit import SlitherCompilationUnit from slither.core.scope.scope import FileScope from slither.slithir.variables.state_variable import StateIRVariable -USING_FOR_KEY = Union[str, Type] -USING_FOR_ITEM = List[Union[Type, Function]] - class FunctionTopLevel(Function, TopLevel): def __init__(self, compilation_unit: "SlitherCompilationUnit", scope: "FileScope") -> None: super().__init__(compilation_unit) self._scope: "FileScope" = scope - self._using_for_complete: Optional[Dict[USING_FOR_KEY, USING_FOR_ITEM]] = None + self._using_for_complete: Optional[USING_FOR] = None @property def file_scope(self) -> "FileScope": return self._scope @property - def using_for_complete(self) -> Dict[USING_FOR_KEY, USING_FOR_ITEM]: + def using_for_complete(self) -> USING_FOR: """ - Dict[Union[str, Type], List[Type]]: Dict of top level directive + USING_FOR: Dict of top level directive """ - def _merge_using_for( - uf1: Dict[USING_FOR_KEY, USING_FOR_ITEM], uf2: Dict[USING_FOR_KEY, USING_FOR_ITEM] - ) -> Dict[USING_FOR_KEY, USING_FOR_ITEM]: - result = {**uf1, **uf2} - for key, value in result.items(): - if key in uf1 and key in uf2: - result[key] = value + uf1[key] - return result - if self._using_for_complete is None: result = {} for uftl in self.file_scope.using_for_directives: diff --git a/slither/core/declarations/using_for_top_level.py b/slither/core/declarations/using_for_top_level.py index edf846a5b1..ca73777e55 100644 --- a/slither/core/declarations/using_for_top_level.py +++ b/slither/core/declarations/using_for_top_level.py @@ -1,8 +1,8 @@ from typing import TYPE_CHECKING, List, Dict, Union -from slither.core.declarations.contract import USING_FOR_KEY, USING_FOR_ITEM from slither.core.solidity_types.type import Type from slither.core.declarations.top_level import TopLevel +from slither.utils.using_for import USING_FOR if TYPE_CHECKING: from slither.core.scope.scope import FileScope @@ -15,5 +15,5 @@ def __init__(self, scope: "FileScope") -> None: self.file_scope: "FileScope" = scope @property - def using_for(self) -> Dict[USING_FOR_KEY, USING_FOR_ITEM]: + def using_for(self) -> USING_FOR: return self._using_for diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 59c5f81be3..c3161a507d 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -1,6 +1,6 @@ import logging from pathlib import Path -from typing import Any, List, TYPE_CHECKING, Union, Optional, Dict +from typing import Any, List, TYPE_CHECKING, Union, Optional # pylint: disable= too-many-lines,import-outside-toplevel,too-many-branches,too-many-statements,too-many-nested-blocks from slither.core.declarations import ( @@ -13,7 +13,6 @@ SolidityVariableComposed, Structure, ) -from slither.core.declarations.contract import USING_FOR_KEY, USING_FOR_ITEM from slither.core.declarations.custom_error import CustomError from slither.core.declarations.function_contract import FunctionContract from slither.core.declarations.function_top_level import FunctionTopLevel @@ -84,6 +83,7 @@ from slither.slithir.variables import TupleVariable from slither.utils.function import get_function_id from slither.utils.type import export_nested_types_from_variable +from slither.utils.using_for import USING_FOR from slither.visitors.slithir.expression_to_slithir import ExpressionToSlithIR if TYPE_CHECKING: @@ -595,7 +595,7 @@ def propagate_types(ir: Operation, node: "Node"): # pylint: disable=too-many-lo # propagate the type node_function = node.function - using_for: Dict[USING_FOR_KEY, USING_FOR_ITEM] = {} + using_for: USING_FOR = {} if isinstance(node_function, FunctionContract): using_for = node_function.contract.using_for_complete elif isinstance(node_function, FunctionTopLevel): @@ -1211,7 +1211,7 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]) -> Union[Call, internalcall.set_expression(ins.expression) return internalcall - raise Exception(f"Not extracted {type(ins.called)} {ins}") # pylint: disable=bad-option-value + raise Exception(f"Not extracted {type(ins.called)} {ins}") # pylint: disable=bad-option-value # endregion diff --git a/slither/solc_parsing/declarations/contract.py b/slither/solc_parsing/declarations/contract.py index b27cce7988..dd7f0342b7 100644 --- a/slither/solc_parsing/declarations/contract.py +++ b/slither/solc_parsing/declarations/contract.py @@ -9,7 +9,7 @@ StructureContract, Function, ) -from slither.core.declarations.contract import Contract, USING_FOR_KEY +from slither.core.declarations.contract import Contract from slither.core.declarations.custom_error_contract import CustomErrorContract from slither.core.declarations.function_contract import FunctionContract from slither.core.solidity_types import ElementaryType, TypeAliasContract @@ -23,6 +23,7 @@ from slither.solc_parsing.exceptions import ParsingError, VariableNotFound from slither.solc_parsing.solidity_types.type_parsing import parse_type from slither.solc_parsing.variables.state_variable import StateVariableSolc +from slither.utils.using_for import USING_FOR_KEY LOGGER = logging.getLogger("ContractSolcParsing") diff --git a/slither/utils/using_for.py b/slither/utils/using_for.py new file mode 100644 index 0000000000..d8e6481ebf --- /dev/null +++ b/slither/utils/using_for.py @@ -0,0 +1,17 @@ +from typing import Dict, List, TYPE_CHECKING, Union +from slither.core.solidity_types.type import Type + +if TYPE_CHECKING: + from slither.core.declarations import Function + +USING_FOR_KEY = Union[str, Type] +USING_FOR_ITEM = List[Union[Type, "Function"]] +USING_FOR = Dict[USING_FOR_KEY, USING_FOR_ITEM] + + +def _merge_using_for(uf1: USING_FOR, uf2: USING_FOR) -> USING_FOR: + result = {**uf1, **uf2} + for key, value in result.items(): + if key in uf1 and key in uf2: + result[key] = value + uf1[key] + return result