slither.utils.loc
1from dataclasses import dataclass, field 2from pathlib import Path 3from typing import List, Tuple 4 5from slither import Slither 6from slither.utils.myprettytable import MyPrettyTable 7from slither.utils.tests_pattern import is_test_file 8 9 10@dataclass 11class LoCInfo: 12 loc: int = 0 13 sloc: int = 0 14 cloc: int = 0 15 16 def total(self) -> int: 17 return self.loc + self.sloc + self.cloc 18 19 20@dataclass 21class LoC: 22 src: LoCInfo = field(default_factory=LoCInfo) 23 dep: LoCInfo = field(default_factory=LoCInfo) 24 test: LoCInfo = field(default_factory=LoCInfo) 25 26 def to_pretty_table(self) -> MyPrettyTable: 27 table = MyPrettyTable(["", "src", "dep", "test"]) 28 29 table.add_row(["loc", str(self.src.loc), str(self.dep.loc), str(self.test.loc)]) 30 table.add_row(["sloc", str(self.src.sloc), str(self.dep.sloc), str(self.test.sloc)]) 31 table.add_row(["cloc", str(self.src.cloc), str(self.dep.cloc), str(self.test.cloc)]) 32 table.add_row( 33 ["Total", str(self.src.total()), str(self.dep.total()), str(self.test.total())] 34 ) 35 return table 36 37 38def count_lines(contract_lines: List[str]) -> Tuple[int, int, int]: 39 """Function to count and classify the lines of code in a contract. 40 Args: 41 contract_lines: list(str) representing the lines of a contract. 42 Returns: 43 tuple(int, int, int) representing (cloc, sloc, loc) 44 """ 45 multiline_comment = False 46 cloc = 0 47 sloc = 0 48 loc = 0 49 50 for line in contract_lines: 51 loc += 1 52 stripped_line = line.strip() 53 if not multiline_comment: 54 if stripped_line.startswith("//"): 55 cloc += 1 56 elif "/*" in stripped_line: 57 # Account for case where /* is followed by */ on the same line. 58 # If it is, then multiline_comment does not need to be set to True 59 start_idx = stripped_line.find("/*") 60 end_idx = stripped_line.find("*/", start_idx + 2) 61 if end_idx == -1: 62 multiline_comment = True 63 cloc += 1 64 elif stripped_line: 65 sloc += 1 66 else: 67 cloc += 1 68 if "*/" in stripped_line: 69 multiline_comment = False 70 71 return cloc, sloc, loc 72 73 74def _update_lines(loc_info: LoCInfo, lines: list) -> None: 75 """An internal function used to update (mutate in place) the loc_info. 76 77 Args: 78 loc_info: LoCInfo to be updated 79 lines: list(str) representing the lines of a contract. 80 """ 81 cloc, sloc, loc = count_lines(lines) 82 loc_info.loc += loc 83 loc_info.cloc += cloc 84 loc_info.sloc += sloc 85 86 87def compute_loc_metrics(slither: Slither) -> LoC: 88 """Used to compute the lines of code metrics for a Slither object. 89 90 Args: 91 slither: A Slither object 92 Returns: 93 A LoC object 94 """ 95 96 loc = LoC() 97 98 for filename, source_code in slither.source_code.items(): 99 current_lines = source_code.splitlines() 100 is_dep = False 101 if slither.crytic_compile: 102 is_dep = slither.crytic_compile.is_dependency(filename) 103 loc_type = loc.dep if is_dep else loc.test if is_test_file(Path(filename)) else loc.src 104 _update_lines(loc_type, current_lines) 105 return loc
class
LoCInfo:
class
LoC:
22class LoC: 23 src: LoCInfo = field(default_factory=LoCInfo) 24 dep: LoCInfo = field(default_factory=LoCInfo) 25 test: LoCInfo = field(default_factory=LoCInfo) 26 27 def to_pretty_table(self) -> MyPrettyTable: 28 table = MyPrettyTable(["", "src", "dep", "test"]) 29 30 table.add_row(["loc", str(self.src.loc), str(self.dep.loc), str(self.test.loc)]) 31 table.add_row(["sloc", str(self.src.sloc), str(self.dep.sloc), str(self.test.sloc)]) 32 table.add_row(["cloc", str(self.src.cloc), str(self.dep.cloc), str(self.test.cloc)]) 33 table.add_row( 34 ["Total", str(self.src.total()), str(self.dep.total()), str(self.test.total())] 35 ) 36 return table
src: LoCInfo
dep: LoCInfo
test: LoCInfo
27 def to_pretty_table(self) -> MyPrettyTable: 28 table = MyPrettyTable(["", "src", "dep", "test"]) 29 30 table.add_row(["loc", str(self.src.loc), str(self.dep.loc), str(self.test.loc)]) 31 table.add_row(["sloc", str(self.src.sloc), str(self.dep.sloc), str(self.test.sloc)]) 32 table.add_row(["cloc", str(self.src.cloc), str(self.dep.cloc), str(self.test.cloc)]) 33 table.add_row( 34 ["Total", str(self.src.total()), str(self.dep.total()), str(self.test.total())] 35 ) 36 return table
def
count_lines(contract_lines: List[str]) -> Tuple[int, int, int]:
39def count_lines(contract_lines: List[str]) -> Tuple[int, int, int]: 40 """Function to count and classify the lines of code in a contract. 41 Args: 42 contract_lines: list(str) representing the lines of a contract. 43 Returns: 44 tuple(int, int, int) representing (cloc, sloc, loc) 45 """ 46 multiline_comment = False 47 cloc = 0 48 sloc = 0 49 loc = 0 50 51 for line in contract_lines: 52 loc += 1 53 stripped_line = line.strip() 54 if not multiline_comment: 55 if stripped_line.startswith("//"): 56 cloc += 1 57 elif "/*" in stripped_line: 58 # Account for case where /* is followed by */ on the same line. 59 # If it is, then multiline_comment does not need to be set to True 60 start_idx = stripped_line.find("/*") 61 end_idx = stripped_line.find("*/", start_idx + 2) 62 if end_idx == -1: 63 multiline_comment = True 64 cloc += 1 65 elif stripped_line: 66 sloc += 1 67 else: 68 cloc += 1 69 if "*/" in stripped_line: 70 multiline_comment = False 71 72 return cloc, sloc, loc
Function to count and classify the lines of code in a contract. Args: contract_lines: list(str) representing the lines of a contract. Returns: tuple(int, int, int) representing (cloc, sloc, loc)
88def compute_loc_metrics(slither: Slither) -> LoC: 89 """Used to compute the lines of code metrics for a Slither object. 90 91 Args: 92 slither: A Slither object 93 Returns: 94 A LoC object 95 """ 96 97 loc = LoC() 98 99 for filename, source_code in slither.source_code.items(): 100 current_lines = source_code.splitlines() 101 is_dep = False 102 if slither.crytic_compile: 103 is_dep = slither.crytic_compile.is_dependency(filename) 104 loc_type = loc.dep if is_dep else loc.test if is_test_file(Path(filename)) else loc.src 105 _update_lines(loc_type, current_lines) 106 return loc
Used to compute the lines of code metrics for a Slither object.
Args: slither: A Slither object Returns: A LoC object