Skip to content

Commit

Permalink
bug: address issue #2107 add contract id in inheritance graph printer
Browse files Browse the repository at this point in the history
  • Loading branch information
dokzai committed Oct 7, 2023
1 parent 1eaec64 commit d973133
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 4 deletions.
2 changes: 1 addition & 1 deletion slither/printers/abstract_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class AbstractPrinter(metaclass=abc.ABCMeta):

WIKI = ""

def __init__(self, slither: "Slither", logger: Logger) -> None:
def __init__(self, slither: "Slither", logger: Optional[Logger]) -> None:
self.slither = slither
self.contracts = slither.contracts
self.filename = slither.filename
Expand Down
7 changes: 4 additions & 3 deletions slither/printers/inheritance/inheritance_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,11 @@ def _summary(self, contract):

# Add arrows (number them if there is more than one path so we know order of declaration for inheritance).
if len(contract.immediate_inheritance) == 1:
ret += f"{contract.name} -> {contract.immediate_inheritance[0]};\n"
immediate_inheritance = contract.immediate_inheritance[0]
ret += f"c{contract.id}_{contract.name} -> c{immediate_inheritance.id}_{immediate_inheritance};\n"
else:
for i, immediate_inheritance in enumerate(contract.immediate_inheritance):
ret += f'{contract.name} -> {immediate_inheritance} [ label="{i + 1}" ];\n'
ret += f'c{contract.id}_{contract.name} -> c{immediate_inheritance.id}_{immediate_inheritance} [ label="{i + 1}" ];\n'

# Functions
visibilities = ["public", "external"]
Expand Down Expand Up @@ -151,7 +152,7 @@ def _summary(self, contract):
indirect_shadowing_information = self._get_indirect_shadowing_information(contract)

# Build the node label
ret += f'{contract.name}[shape="box"'
ret += f'c{contract.id}_{contract.name}[shape="box"'
ret += 'label=< <TABLE border="0">'
ret += f'<TR><TD align="center"><B>{contract.name}</B></TD></TR>'
if public_functions:
Expand Down
Empty file added tests/e2e/printers/__init__.py
Empty file.
4 changes: 4 additions & 0 deletions tests/e2e/printers/test_data/test_contract_names/A.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
contract A {
function a_main() public pure {}
}

8 changes: 8 additions & 0 deletions tests/e2e/printers/test_data/test_contract_names/B.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import "./A.sol";

contract B is A {
function b_main() public pure {
a_main();
}
}

7 changes: 7 additions & 0 deletions tests/e2e/printers/test_data/test_contract_names/B2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import "./A.sol";

contract B is A {
function b2_main() public pure {
a_main();
}
}
7 changes: 7 additions & 0 deletions tests/e2e/printers/test_data/test_contract_names/C.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import "./A.sol";

contract C is A {
function c_main() public pure {
a_main();
}
}
45 changes: 45 additions & 0 deletions tests/e2e/printers/test_printers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import re
from collections import Counter
from pathlib import Path

from crytic_compile import CryticCompile
from crytic_compile.platform.solc_standard_json import SolcStandardJson

from slither import Slither
from slither.printers.inheritance.inheritance_graph import PrinterInheritanceGraph


TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data"


def test_inheritance_printer(solc_binary_path) -> None:
solc_path = solc_binary_path("0.8.0")
standard_json = SolcStandardJson()
standard_json.add_source_file(
Path(TEST_DATA_DIR, "test_contract_names", "A.sol").as_posix()
)
standard_json.add_source_file(
Path(TEST_DATA_DIR, "test_contract_names", "B.sol").as_posix()
)
standard_json.add_source_file(
Path(TEST_DATA_DIR, "test_contract_names", "B2.sol").as_posix()
)
standard_json.add_source_file(
Path(TEST_DATA_DIR, "test_contract_names", "C.sol").as_posix()
)
compilation = CryticCompile(standard_json, solc=solc_path)
slither = Slither(compilation)
printer = PrinterInheritanceGraph(slither=slither, logger=None)

content = ""
for contract in slither.contracts:
content += printer._summary(contract)

Check warning on line 36 in tests/e2e/printers/test_printers.py

View workflow job for this annotation

GitHub Actions / Lint Code Base

W0212: Access to a protected member _summary of a client class (protected-access)

pattern = re.compile(r"(?:c\d+_)?(\w+ -> )(?:c\d+_)(\w+)")
matches = re.findall(pattern, content)
relations = ["".join(m) for m in matches]

counter = Counter(relations)

assert counter["B -> A"] == 2
assert counter["C -> A"] == 1

0 comments on commit d973133

Please sign in to comment.