slither.utils.source_mapping

 1from typing import List, Set
 2from crytic_compile import CryticCompile
 3from slither.core.declarations import (
 4    Contract,
 5    Function,
 6    Enum,
 7    Event,
 8    Import,
 9    Pragma,
10    Structure,
11    CustomError,
12    FunctionContract,
13)
14from slither.core.solidity_types import Type, TypeAlias
15from slither.core.source_mapping.source_mapping import Source, SourceMapping
16from slither.core.variables.variable import Variable
17from slither.exceptions import SlitherError
18
19
20def get_definition(target: SourceMapping, crytic_compile: CryticCompile) -> Source:
21    if isinstance(target, (Contract, Function, Enum, Event, Structure, Variable)):
22        # Add " " to look after the first solidity keyword
23        pattern = " " + target.name
24    elif isinstance(target, Import):
25        pattern = "import"
26    elif isinstance(target, Pragma):
27        pattern = "pragma"  # todo maybe return with the while pragma statement
28    elif isinstance(target, CustomError):
29        pattern = "error"
30    elif isinstance(target, TypeAlias):
31        pattern = "type"
32    elif isinstance(target, Type):
33        raise SlitherError("get_definition_generic not implemented for types")
34    else:
35        raise SlitherError(f"get_definition_generic not implemented for {type(target)}")
36
37    file_content = crytic_compile.src_content_for_file(target.source_mapping.filename.absolute)
38    txt = file_content[
39        target.source_mapping.start : target.source_mapping.start + target.source_mapping.length
40    ]
41
42    start_offset = txt.find(pattern) + 1  # remove the space
43
44    starting_line, starting_column = crytic_compile.get_line_from_offset(
45        target.source_mapping.filename, target.source_mapping.start + start_offset
46    )
47
48    ending_line, ending_column = crytic_compile.get_line_from_offset(
49        target.source_mapping.filename, target.source_mapping.start + start_offset + len(pattern)
50    )
51
52    s = Source(target.source_mapping.compilation_unit)
53    s.start = target.source_mapping.start + start_offset
54    s.length = len(pattern)
55    s.filename = target.source_mapping.filename
56    s.is_dependency = target.source_mapping.is_dependency
57    s.lines = list(range(starting_line, ending_line + 1))
58    s.starting_column = starting_column
59    s.ending_column = ending_column
60    s.end = s.start + s.length
61    s.txt = txt
62    return s
63
64
65def get_implementation(target: SourceMapping) -> Source:
66    return target.source_mapping
67
68
69def get_all_implementations(target: SourceMapping, contracts: List[Contract]) -> Set[Source]:
70    """
71    Get all implementations of a contract or function, accounting for inheritance and overrides
72    """
73    implementations = set()
74    # Abstract contracts and interfaces are implemented by their children
75    if isinstance(target, Contract):
76        is_interface = target.is_interface
77        is_implicitly_abstract = not target.is_fully_implemented
78        is_explicitly_abstract = target.is_abstract
79        if is_interface or is_implicitly_abstract or is_explicitly_abstract:
80            for contract in contracts:
81                if target in contract.immediate_inheritance:
82                    implementations.add(contract.source_mapping)
83
84    # Parent's virtual functions may be overridden by children
85    elif isinstance(target, FunctionContract):
86        for over in target.overridden_by:
87            implementations.add(over.source_mapping)
88        # Only show implemented virtual functions
89        if not target.is_virtual or target.is_implemented:
90            implementations.add(get_implementation(target))
91
92    else:
93        implementations.add(get_implementation(target))
94
95    return implementations
96
97
98def get_references(target: SourceMapping) -> List[Source]:
99    return target.references
def get_definition( target: slither.core.source_mapping.source_mapping.SourceMapping, crytic_compile: crytic_compile.crytic_compile.CryticCompile) -> slither.core.source_mapping.source_mapping.Source:
21def get_definition(target: SourceMapping, crytic_compile: CryticCompile) -> Source:
22    if isinstance(target, (Contract, Function, Enum, Event, Structure, Variable)):
23        # Add " " to look after the first solidity keyword
24        pattern = " " + target.name
25    elif isinstance(target, Import):
26        pattern = "import"
27    elif isinstance(target, Pragma):
28        pattern = "pragma"  # todo maybe return with the while pragma statement
29    elif isinstance(target, CustomError):
30        pattern = "error"
31    elif isinstance(target, TypeAlias):
32        pattern = "type"
33    elif isinstance(target, Type):
34        raise SlitherError("get_definition_generic not implemented for types")
35    else:
36        raise SlitherError(f"get_definition_generic not implemented for {type(target)}")
37
38    file_content = crytic_compile.src_content_for_file(target.source_mapping.filename.absolute)
39    txt = file_content[
40        target.source_mapping.start : target.source_mapping.start + target.source_mapping.length
41    ]
42
43    start_offset = txt.find(pattern) + 1  # remove the space
44
45    starting_line, starting_column = crytic_compile.get_line_from_offset(
46        target.source_mapping.filename, target.source_mapping.start + start_offset
47    )
48
49    ending_line, ending_column = crytic_compile.get_line_from_offset(
50        target.source_mapping.filename, target.source_mapping.start + start_offset + len(pattern)
51    )
52
53    s = Source(target.source_mapping.compilation_unit)
54    s.start = target.source_mapping.start + start_offset
55    s.length = len(pattern)
56    s.filename = target.source_mapping.filename
57    s.is_dependency = target.source_mapping.is_dependency
58    s.lines = list(range(starting_line, ending_line + 1))
59    s.starting_column = starting_column
60    s.ending_column = ending_column
61    s.end = s.start + s.length
62    s.txt = txt
63    return s
66def get_implementation(target: SourceMapping) -> Source:
67    return target.source_mapping
70def get_all_implementations(target: SourceMapping, contracts: List[Contract]) -> Set[Source]:
71    """
72    Get all implementations of a contract or function, accounting for inheritance and overrides
73    """
74    implementations = set()
75    # Abstract contracts and interfaces are implemented by their children
76    if isinstance(target, Contract):
77        is_interface = target.is_interface
78        is_implicitly_abstract = not target.is_fully_implemented
79        is_explicitly_abstract = target.is_abstract
80        if is_interface or is_implicitly_abstract or is_explicitly_abstract:
81            for contract in contracts:
82                if target in contract.immediate_inheritance:
83                    implementations.add(contract.source_mapping)
84
85    # Parent's virtual functions may be overridden by children
86    elif isinstance(target, FunctionContract):
87        for over in target.overridden_by:
88            implementations.add(over.source_mapping)
89        # Only show implemented virtual functions
90        if not target.is_virtual or target.is_implemented:
91            implementations.add(get_implementation(target))
92
93    else:
94        implementations.add(get_implementation(target))
95
96    return implementations

Get all implementations of a contract or function, accounting for inheritance and overrides

 99def get_references(target: SourceMapping) -> List[Source]:
100    return target.references