Improve support of top-level structures and enums

pull/522/head
Josselin 4 years ago
parent 64ecdbec9a
commit 2d256ddd93
  1. 22
      slither/core/slither_core.py
  2. 10
      slither/solc_parsing/expressions/expression_parsing.py
  3. 11
      slither/solc_parsing/slitherSolc.py
  4. 4
      slither/solc_parsing/solidity_types/type_parsing.py

@ -11,7 +11,7 @@ from typing import Optional, Dict, List, Set, Union
from crytic_compile import CryticCompile
from slither.core.context.context import Context
from slither.core.declarations import Contract, Pragma, Import, Function, Modifier
from slither.core.declarations import Contract, Pragma, Import, Function, Modifier, Structure, Enum
from slither.core.variables.state_variable import StateVariable
from slither.slithir.operations import InternalCall
from slither.slithir.variables import Constant
@ -136,7 +136,7 @@ class SlitherCore(Context):
"""list(Contract): List of contracts that are derived and not inherited."""
inheritance = (x.inheritance for x in self.contracts)
inheritance = [item for sublist in inheritance for item in sublist]
return [c for c in self._contracts.values() if c not in inheritance]
return [c for c in self._contracts.values() if c not in inheritance and not c.is_top_level]
@property
def contracts_as_dict(self) -> Dict[str, Contract]:
@ -200,6 +200,24 @@ class SlitherCore(Context):
self._all_state_variables = set(state_variables)
return list(self._all_state_variables)
# endregion
###################################################################################
###################################################################################
# region Top level
###################################################################################
###################################################################################
@property
def top_level_structures(self) -> List[Structure]:
top_level_structures = [c.structures for c in self.contracts if c.is_top_level]
return [st for sublist in top_level_structures for st in sublist]
@property
def top_level_enums(self) -> List[Enum]:
top_level_enums = [c.enums for c in self.contracts if c.is_top_level]
return [st for sublist in top_level_enums for st in sublist]
# endregion
###################################################################################
###################################################################################

@ -168,6 +168,11 @@ def find_variable(
if var_name in structures:
return structures[var_name]
structures_top_level = contract.slither.top_level_structures
for st in structures_top_level:
if st.name == var_name:
return st
events = contract.events_as_dict
if var_name in events:
return events[var_name]
@ -176,6 +181,11 @@ def find_variable(
if var_name in enums:
return enums[var_name]
enums_top_level = contract.slither.top_level_enums
for enum in enums_top_level:
if enum.name == var_name:
return enum
# If the enum is refered as its name rather than its canonicalName
enums = {e.name: e for e in contract.enums}
if var_name in enums:

@ -163,15 +163,16 @@ class SlitherSolc:
assert self._is_compact_ast # Do not support top level definition for legacy AST
fake_contract_data = {
"name": f"SlitherInternalTopLevelContract{self._top_level_contracts_counter}",
"id": -1000, # TODO: determine if collission possible
"id": -1000 + self._top_level_contracts_counter, # TODO: determine if collission possible
"linearizedBaseContracts": [],
"fullyImplemented": True,
"contractKind": "SLitherInternal",
}
self._top_level_contracts_counter += 1
top_level_contract = ContractSolc(self, fake_contract_data)
top_level_contract.is_top_level = True
top_level_contract.set_offset(contract_data["src"], self)
contract = Contract()
top_level_contract = ContractSolc(self, contract, fake_contract_data)
contract.is_top_level = True
contract.set_offset(contract_data["src"], self._core)
if contract_data[self.get_key()] == "StructDefinition":
top_level_contract._structuresNotParsed.append(
@ -182,7 +183,7 @@ class SlitherSolc:
contract_data
) # Todo add proper setters
self._contractsNotParsed.append(top_level_contract)
self._underlying_contract_to_parser[contract] = top_level_contract
def _parse_source_unit(self, data: Dict, filename: str):
if data[self.get_key()] != "SourceUnit":

@ -167,8 +167,8 @@ def parse_type(t: Union[Dict, UnknownType], caller_context):
else:
key = "name"
structures = contract.structures
enums = contract.enums
structures = contract.structures + contract.slither.top_level_structures
enums = contract.enums + contract.slither.top_level_enums
contracts = contract.slither.contracts
if isinstance(t, UnknownType):

Loading…
Cancel
Save