mirror of https://github.com/crytic/slither
Merge pull request #877 from crytic/dev-source-mapping-refactor
Refactor source mapping + add new source code APIspull/1343/head
commit
e34fcfab99
@ -0,0 +1,57 @@ |
||||
from slither.printers.abstract_printer import AbstractPrinter |
||||
from slither.utils.source_mapping import get_definition, get_implementation, get_references |
||||
|
||||
|
||||
class Declaration(AbstractPrinter): |
||||
ARGUMENT = "declaration" |
||||
HELP = "Prototype showing the source code declaration, implementation and references of the contracts objects" |
||||
|
||||
WIKI = "TODO" |
||||
|
||||
def output(self, _filename): |
||||
""" |
||||
_filename is not used |
||||
Args: |
||||
_filename(string) |
||||
""" |
||||
|
||||
txt = "" |
||||
for compilation_unit in self.slither.compilation_units: |
||||
txt += "\n# Contracts\n" |
||||
for contract in compilation_unit.contracts: |
||||
txt += f"# {contract.name}\n" |
||||
txt += f"\t- Declaration: {get_definition(contract, compilation_unit.core.crytic_compile).to_detailled_str()}\n" |
||||
txt += f"\t- Implementation: {get_implementation(contract).to_detailled_str()}\n" |
||||
txt += ( |
||||
f"\t- References: {[x.to_detailled_str() for x in get_references(contract)]}\n" |
||||
) |
||||
|
||||
txt += "\n\t## Function\n" |
||||
|
||||
for func in contract.functions: |
||||
txt += f"\t\t- {func.canonical_name}\n" |
||||
txt += f"\t\t\t- Declaration: {get_definition(func, compilation_unit.core.crytic_compile).to_detailled_str()}\n" |
||||
txt += ( |
||||
f"\t\t\t- Implementation: {get_implementation(func).to_detailled_str()}\n" |
||||
) |
||||
txt += f"\t\t\t- References: {[x.to_detailled_str() for x in get_references(func)]}\n" |
||||
|
||||
txt += "\n\t## State variables\n" |
||||
|
||||
for var in contract.state_variables: |
||||
txt += f"\t\t- {var.name}\n" |
||||
txt += f"\t\t\t- Declaration: {get_definition(var, compilation_unit.core.crytic_compile).to_detailled_str()}\n" |
||||
txt += f"\t\t\t- Implementation: {get_implementation(var).to_detailled_str()}\n" |
||||
txt += f"\t\t\t- References: {[x.to_detailled_str() for x in get_references(var)]}\n" |
||||
|
||||
txt += "\n\t## Structures\n" |
||||
|
||||
for st in contract.structures: |
||||
txt += f"\t\t- {st.name}\n" |
||||
txt += f"\t\t\t- Declaration: {get_definition(st, compilation_unit.core.crytic_compile).to_detailled_str()}\n" |
||||
txt += f"\t\t\t- Implementation: {get_implementation(st).to_detailled_str()}\n" |
||||
txt += f"\t\t\t- References: {[x.to_detailled_str() for x in get_references(st)]}\n" |
||||
|
||||
self.info(txt) |
||||
res = self.generate_output(txt) |
||||
return res |
@ -0,0 +1,57 @@ |
||||
from typing import List |
||||
from crytic_compile import CryticCompile |
||||
from slither.core.declarations import Contract, Function, Enum, Event, Import, Pragma, Structure |
||||
from slither.core.solidity_types.type import Type |
||||
from slither.core.source_mapping.source_mapping import Source, SourceMapping |
||||
from slither.core.variables.variable import Variable |
||||
from slither.exceptions import SlitherError |
||||
|
||||
|
||||
def get_definition(target: SourceMapping, crytic_compile: CryticCompile) -> Source: |
||||
if isinstance(target, (Contract, Function, Enum, Event, Structure, Variable)): |
||||
# Add " " to look after the first solidity keyword |
||||
pattern = " " + target.name |
||||
elif isinstance(target, Import): |
||||
pattern = "import" |
||||
elif isinstance(target, Pragma): |
||||
pattern = "pragma" # todo maybe return with the while pragma statement |
||||
elif isinstance(target, Type): |
||||
raise SlitherError("get_definition_generic not implemented for types") |
||||
else: |
||||
raise SlitherError(f"get_definition_generic not implemented for {type(target)}") |
||||
|
||||
file_content = crytic_compile.src_content_for_file(target.source_mapping.filename.absolute) |
||||
txt = file_content[ |
||||
target.source_mapping.start : target.source_mapping.start + target.source_mapping.length |
||||
] |
||||
|
||||
start_offset = txt.find(pattern) + 1 # remove the space |
||||
|
||||
starting_line, starting_column = crytic_compile.get_line_from_offset( |
||||
target.source_mapping.filename, target.source_mapping.start + start_offset |
||||
) |
||||
|
||||
ending_line, ending_column = crytic_compile.get_line_from_offset( |
||||
target.source_mapping.filename, target.source_mapping.start + start_offset + len(pattern) |
||||
) |
||||
|
||||
s = Source() |
||||
s.start = target.source_mapping.start + start_offset |
||||
s.length = len(pattern) |
||||
s.filename = target.source_mapping.filename |
||||
s.is_dependency = target.source_mapping.is_dependency |
||||
s.lines = list(range(starting_line, ending_line + 1)) |
||||
s.starting_column = starting_column |
||||
s.ending_column = ending_column |
||||
s.end = s.start + s.length |
||||
s.compilation_unit = target.compilation_unit |
||||
|
||||
return s |
||||
|
||||
|
||||
def get_implementation(target: SourceMapping) -> Source: |
||||
return target.source_mapping |
||||
|
||||
|
||||
def get_references(target: SourceMapping) -> List[Source]: |
||||
return target.references |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue