mirror of https://github.com/crytic/slither
parent
d77fcfe6b6
commit
f70e89bf12
@ -1,452 +0,0 @@ |
||||
import os |
||||
import json |
||||
import logging |
||||
from collections import OrderedDict |
||||
|
||||
from slither.core.cfg.node import Node |
||||
from slither.core.declarations import Contract, Function, Enum, Event, Structure, Pragma |
||||
from slither.core.source_mapping.source_mapping import SourceMapping |
||||
from slither.core.variables.variable import Variable |
||||
from slither.exceptions import SlitherError |
||||
from slither.utils.colors import yellow |
||||
|
||||
logger = logging.getLogger("Slither") |
||||
|
||||
|
||||
################################################################################### |
||||
################################################################################### |
||||
# region Output |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def output_json(filename, error, results): |
||||
""" |
||||
|
||||
:param filename: Filename where the json will be written. If None or "-", write to stdout |
||||
:param error: Error to report |
||||
:param results: Results to report |
||||
:param logger: Logger where to log potential info |
||||
:return: |
||||
""" |
||||
# Create our encapsulated JSON result. |
||||
json_result = { |
||||
"success": error is None, |
||||
"error": error, |
||||
"results": results |
||||
} |
||||
|
||||
if filename == "-": |
||||
filename = None |
||||
|
||||
# Determine if we should output to stdout |
||||
if filename is None: |
||||
# Write json to console |
||||
print(json.dumps(json_result)) |
||||
else: |
||||
# Write json to file |
||||
if os.path.isfile(filename): |
||||
logger.info(yellow(f'{filename} exists already, the overwrite is prevented')) |
||||
else: |
||||
with open(filename, 'w', encoding='utf8') as f: |
||||
json.dump(json_result, f, indent=2) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Json generation |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def _convert_to_description(d): |
||||
if isinstance(d, str): |
||||
return d |
||||
|
||||
if not isinstance(d, SourceMapping): |
||||
raise SlitherError(f'{d} does not inherit from SourceMapping, conversion impossible') |
||||
|
||||
if isinstance(d, Node): |
||||
if d.expression: |
||||
return f'{d.expression} ({d.source_mapping_str})' |
||||
else: |
||||
return f'{str(d)} ({d.source_mapping_str})' |
||||
|
||||
if hasattr(d, 'canonical_name'): |
||||
return f'{d.canonical_name} ({d.source_mapping_str})' |
||||
|
||||
if hasattr(d, 'name'): |
||||
return f'{d.name} ({d.source_mapping_str})' |
||||
|
||||
raise SlitherError(f'{type(d)} cannot be converted (no name, or canonical_name') |
||||
|
||||
def _convert_to_markdown(d, markdown_root): |
||||
if isinstance(d, str): |
||||
return d |
||||
|
||||
if not isinstance(d, SourceMapping): |
||||
raise SlitherError(f'{d} does not inherit from SourceMapping, conversion impossible') |
||||
|
||||
if isinstance(d, Node): |
||||
if d.expression: |
||||
return f'[{d.expression}]({d.source_mapping_to_markdown(markdown_root)})' |
||||
else: |
||||
return f'[{str(d)}]({d.source_mapping_to_markdown(markdown_root)})' |
||||
|
||||
if hasattr(d, 'canonical_name'): |
||||
return f'[{d.canonical_name}]({d.source_mapping_to_markdown(markdown_root)})' |
||||
|
||||
if hasattr(d, 'name'): |
||||
return f'[{d.name}]({d.source_mapping_to_markdown(markdown_root)})' |
||||
|
||||
raise SlitherError(f'{type(d)} cannot be converted (no name, or canonical_name') |
||||
|
||||
def generate_json_result(info, additional_fields=None, markdown_root='', standard_format=False): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
d = OrderedDict() |
||||
d['elements'] = [] |
||||
d['description'] = ''.join(_convert_to_description(d) for d in info) |
||||
d['markdown'] = ''.join(_convert_to_markdown(d, markdown_root) for d in info) |
||||
|
||||
if standard_format: |
||||
to_add = [i for i in info if not isinstance(i, str)] |
||||
|
||||
for add in to_add: |
||||
if isinstance(add, Variable): |
||||
add_variable_to_json(add, d) |
||||
elif isinstance(add, Contract): |
||||
add_contract_to_json(add, d) |
||||
elif isinstance(add, Function): |
||||
add_function_to_json(add, d) |
||||
elif isinstance(add, Enum): |
||||
add_enum_to_json(add, d) |
||||
elif isinstance(add, Event): |
||||
add_event_to_json(add, d) |
||||
elif isinstance(add, Structure): |
||||
add_struct_to_json(add, d) |
||||
elif isinstance(add, Pragma): |
||||
add_pragma_to_json(add, d) |
||||
elif isinstance(add, Node): |
||||
add_node_to_json(add, d) |
||||
else: |
||||
raise SlitherError(f'Impossible to add {type(add)} to the json') |
||||
|
||||
if additional_fields: |
||||
d['additional_fields'] = additional_fields |
||||
|
||||
return d |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Internal functions |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def _create_base_element(type, name, source_mapping, type_specific_fields=None, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
if type_specific_fields is None: |
||||
type_specific_fields = {} |
||||
element = {'type': type, |
||||
'name': name, |
||||
'source_mapping': source_mapping} |
||||
if type_specific_fields: |
||||
element['type_specific_fields'] = type_specific_fields |
||||
if additional_fields: |
||||
element['additional_fields'] = additional_fields |
||||
return element |
||||
|
||||
|
||||
def _create_parent_element(element): |
||||
from slither.core.children.child_contract import ChildContract |
||||
from slither.core.children.child_function import ChildFunction |
||||
from slither.core.children.child_inheritance import ChildInheritance |
||||
if isinstance(element, ChildInheritance): |
||||
if element.contract_declarer: |
||||
contract = {'elements': []} |
||||
add_contract_to_json(element.contract_declarer, contract) |
||||
return contract['elements'][0] |
||||
elif isinstance(element, ChildContract): |
||||
if element.contract: |
||||
contract = {'elements': []} |
||||
add_contract_to_json(element.contract, contract) |
||||
return contract['elements'][0] |
||||
elif isinstance(element, ChildFunction): |
||||
if element.function: |
||||
function = {'elements': []} |
||||
add_function_to_json(element.function, function) |
||||
return function['elements'][0] |
||||
return None |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Variables |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_variable_to_json(variable, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(variable) |
||||
} |
||||
element = _create_base_element('variable', |
||||
variable.name, |
||||
variable.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
d['elements'].append(element) |
||||
|
||||
|
||||
def add_variables_to_json(variables, d): |
||||
for variable in sorted(variables, key=lambda x: x.name): |
||||
add_variable_to_json(variable, d) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Contract |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_contract_to_json(contract, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
element = _create_base_element('contract', |
||||
contract.name, |
||||
contract.source_mapping, |
||||
{}, |
||||
additional_fields) |
||||
d['elements'].append(element) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Functions |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_function_to_json(function, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(function), |
||||
'signature': function.full_name |
||||
} |
||||
element = _create_base_element('function', |
||||
function.name, |
||||
function.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
d['elements'].append(element) |
||||
|
||||
|
||||
def add_functions_to_json(functions, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
for function in sorted(functions, key=lambda x: x.name): |
||||
add_function_to_json(function, d, additional_fields) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Enum |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
|
||||
def add_enum_to_json(enum, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(enum) |
||||
} |
||||
element = _create_base_element('enum', |
||||
enum.name, |
||||
enum.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
d['elements'].append(element) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Structures |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_struct_to_json(struct, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(struct) |
||||
} |
||||
element = _create_base_element('struct', |
||||
struct.name, |
||||
struct.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
d['elements'].append(element) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Events |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_event_to_json(event, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(event), |
||||
'signature': event.full_name |
||||
} |
||||
element = _create_base_element('event', |
||||
event.name, |
||||
event.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
|
||||
d['elements'].append(element) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Nodes |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_node_to_json(node, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(node), |
||||
} |
||||
node_name = str(node.expression) if node.expression else "" |
||||
element = _create_base_element('node', |
||||
node_name, |
||||
node.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
d['elements'].append(element) |
||||
|
||||
|
||||
def add_nodes_to_json(nodes, d): |
||||
for node in sorted(nodes, key=lambda x: x.node_id): |
||||
add_node_to_json(node, d) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Pragma |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_pragma_to_json(pragma, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'directive': pragma.directive |
||||
} |
||||
element = _create_base_element('pragma', |
||||
pragma.version, |
||||
pragma.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
d['elements'].append(element) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region File |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
|
||||
def add_file_to_json(filename, content, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'filename': filename, |
||||
'content': content |
||||
} |
||||
element = _create_base_element('file', |
||||
type_specific_fields, |
||||
additional_fields) |
||||
|
||||
d['elements'].append(element) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Pretty Table |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
|
||||
def add_pretty_table_to_json(content, name, d, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'content': content, |
||||
'name': name |
||||
} |
||||
element = _create_base_element('pretty_table', |
||||
type_specific_fields, |
||||
additional_fields) |
||||
|
||||
d['elements'].append(element) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Others |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_other_to_json(name, source_mapping, d, slither, additional_fields=None): |
||||
# If this a tuple with (filename, start, end), convert it to a source mapping. |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
if isinstance(source_mapping, tuple): |
||||
# Parse the source id |
||||
(filename, start, end) = source_mapping |
||||
source_id = next( |
||||
(source_unit_id for (source_unit_id, source_unit_filename) in slither.source_units.items() if |
||||
source_unit_filename == filename), -1) |
||||
|
||||
# Convert to a source mapping string |
||||
source_mapping = f"{start}:{end}:{source_id}" |
||||
|
||||
# If this is a source mapping string, parse it. |
||||
if isinstance(source_mapping, str): |
||||
source_mapping_str = source_mapping |
||||
source_mapping = SourceMapping() |
||||
source_mapping.set_offset(source_mapping_str, slither) |
||||
|
||||
# If this is a source mapping object, get the underlying source mapping dictionary |
||||
if isinstance(source_mapping, SourceMapping): |
||||
source_mapping = source_mapping.source_mapping |
||||
|
||||
# Create the underlying element and add it to our resulting json |
||||
element = _create_base_element('other', |
||||
name, |
||||
source_mapping, |
||||
{}, |
||||
additional_fields) |
||||
d['elements'].append(element) |
@ -0,0 +1,454 @@ |
||||
import os |
||||
import json |
||||
import logging |
||||
from collections import OrderedDict |
||||
|
||||
from slither.core.cfg.node import Node |
||||
from slither.core.declarations import Contract, Function, Enum, Event, Structure, Pragma |
||||
from slither.core.source_mapping.source_mapping import SourceMapping |
||||
from slither.core.variables.variable import Variable |
||||
from slither.exceptions import SlitherError |
||||
from slither.utils.colors import yellow |
||||
|
||||
logger = logging.getLogger("Slither") |
||||
|
||||
|
||||
################################################################################### |
||||
################################################################################### |
||||
# region Output |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def output_to_json(filename, error, results): |
||||
""" |
||||
|
||||
:param filename: Filename where the json will be written. If None or "-", write to stdout |
||||
:param error: Error to report |
||||
:param results: Results to report |
||||
:param logger: Logger where to log potential info |
||||
:return: |
||||
""" |
||||
# Create our encapsulated JSON result. |
||||
json_result = { |
||||
"success": error is None, |
||||
"error": error, |
||||
"results": results |
||||
} |
||||
|
||||
if filename == "-": |
||||
filename = None |
||||
|
||||
# Determine if we should output to stdout |
||||
if filename is None: |
||||
# Write json to console |
||||
print(json.dumps(json_result)) |
||||
else: |
||||
# Write json to file |
||||
if os.path.isfile(filename): |
||||
logger.info(yellow(f'{filename} exists already, the overwrite is prevented')) |
||||
else: |
||||
with open(filename, 'w', encoding='utf8') as f: |
||||
json.dump(json_result, f, indent=2) |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Json generation |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def _convert_to_description(d): |
||||
if isinstance(d, str): |
||||
return d |
||||
|
||||
if not isinstance(d, SourceMapping): |
||||
raise SlitherError(f'{d} does not inherit from SourceMapping, conversion impossible') |
||||
|
||||
if isinstance(d, Node): |
||||
if d.expression: |
||||
return f'{d.expression} ({d.source_mapping_str})' |
||||
else: |
||||
return f'{str(d)} ({d.source_mapping_str})' |
||||
|
||||
if hasattr(d, 'canonical_name'): |
||||
return f'{d.canonical_name} ({d.source_mapping_str})' |
||||
|
||||
if hasattr(d, 'name'): |
||||
return f'{d.name} ({d.source_mapping_str})' |
||||
|
||||
raise SlitherError(f'{type(d)} cannot be converted (no name, or canonical_name') |
||||
|
||||
|
||||
def _convert_to_markdown(d, markdown_root): |
||||
if isinstance(d, str): |
||||
return d |
||||
|
||||
if not isinstance(d, SourceMapping): |
||||
raise SlitherError(f'{d} does not inherit from SourceMapping, conversion impossible') |
||||
|
||||
if isinstance(d, Node): |
||||
if d.expression: |
||||
return f'[{d.expression}]({d.source_mapping_to_markdown(markdown_root)})' |
||||
else: |
||||
return f'[{str(d)}]({d.source_mapping_to_markdown(markdown_root)})' |
||||
|
||||
if hasattr(d, 'canonical_name'): |
||||
return f'[{d.canonical_name}]({d.source_mapping_to_markdown(markdown_root)})' |
||||
|
||||
if hasattr(d, 'name'): |
||||
return f'[{d.name}]({d.source_mapping_to_markdown(markdown_root)})' |
||||
|
||||
raise SlitherError(f'{type(d)} cannot be converted (no name, or canonical_name') |
||||
|
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Internal functions |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def _create_base_element(type, name, source_mapping, type_specific_fields=None, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
if type_specific_fields is None: |
||||
type_specific_fields = {} |
||||
element = {'type': type, |
||||
'name': name, |
||||
'source_mapping': source_mapping} |
||||
if type_specific_fields: |
||||
element['type_specific_fields'] = type_specific_fields |
||||
if additional_fields: |
||||
element['additional_fields'] = additional_fields |
||||
return element |
||||
|
||||
|
||||
def _create_parent_element(element): |
||||
from slither.core.children.child_contract import ChildContract |
||||
from slither.core.children.child_function import ChildFunction |
||||
from slither.core.children.child_inheritance import ChildInheritance |
||||
if isinstance(element, ChildInheritance): |
||||
if element.contract_declarer: |
||||
contract = Output('') |
||||
contract.add_contract(element.contract_declarer) |
||||
return contract.data['elements'][0] |
||||
elif isinstance(element, ChildContract): |
||||
if element.contract: |
||||
contract = Output('') |
||||
contract.add_contract(element.contract) |
||||
return contract.data['elements'][0] |
||||
elif isinstance(element, ChildFunction): |
||||
if element.function: |
||||
function = Output('') |
||||
function.add_function(element.function) |
||||
return function.data['elements'][0] |
||||
return None |
||||
|
||||
|
||||
class Output: |
||||
|
||||
def __init__(self, info, additional_fields=None, markdown_root='', standard_format=True): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
|
||||
# Allow info to be a string to simplify the API |
||||
if isinstance(info, str): |
||||
info = [info] |
||||
|
||||
self._data = OrderedDict() |
||||
self._data['elements'] = [] |
||||
self._data['description'] = ''.join(_convert_to_description(d) for d in info) |
||||
self._data['markdown'] = ''.join(_convert_to_markdown(d, markdown_root) for d in info) |
||||
|
||||
if standard_format: |
||||
to_add = [i for i in info if not isinstance(i, str)] |
||||
|
||||
for add in to_add: |
||||
self.add(add) |
||||
|
||||
if additional_fields: |
||||
self._data['additional_fields'] = additional_fields |
||||
|
||||
|
||||
def add(self, add, additional_fields=None): |
||||
if isinstance(add, Variable): |
||||
self.add_variable(add, additional_fields=additional_fields) |
||||
elif isinstance(add, Contract): |
||||
self.add_contract(add, additional_fields=additional_fields) |
||||
elif isinstance(add, Function): |
||||
self.add_function(add, additional_fields=additional_fields) |
||||
elif isinstance(add, Enum): |
||||
self.add_enum(add, additional_fields=additional_fields) |
||||
elif isinstance(add, Event): |
||||
self.add_event(add, additional_fields=additional_fields) |
||||
elif isinstance(add, Structure): |
||||
self.add_struct(add, additional_fields=additional_fields) |
||||
elif isinstance(add, Pragma): |
||||
self.add_pragma(add, additional_fields=additional_fields) |
||||
elif isinstance(add, Node): |
||||
self.add_node(add, additional_fields=additional_fields) |
||||
else: |
||||
raise SlitherError(f'Impossible to add {type(add)} to the json') |
||||
|
||||
@property |
||||
def data(self): |
||||
return self._data |
||||
|
||||
@property |
||||
def elements(self): |
||||
return self._data['elements'] |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Variables |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_variable(self, variable, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(variable) |
||||
} |
||||
element = _create_base_element('variable', |
||||
variable.name, |
||||
variable.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
self._data['elements'].append(element) |
||||
|
||||
def add_variables_to_output(self, variables): |
||||
for variable in sorted(variables, key=lambda x: x.name): |
||||
self.add_variable(variable) |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Contract |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_contract(self, contract, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
element = _create_base_element('contract', |
||||
contract.name, |
||||
contract.source_mapping, |
||||
{}, |
||||
additional_fields) |
||||
self._data['elements'].append(element) |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Functions |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_function(self, function, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(function), |
||||
'signature': function.full_name |
||||
} |
||||
element = _create_base_element('function', |
||||
function.name, |
||||
function.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
self._data['elements'].append(element) |
||||
|
||||
def add_functions(self, functions, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
for function in sorted(functions, key=lambda x: x.name): |
||||
self.add_function(function, additional_fields) |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Enum |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_enum(self, enum, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(enum) |
||||
} |
||||
element = _create_base_element('enum', |
||||
enum.name, |
||||
enum.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
self._data['elements'].append(element) |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Structures |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_struct(self, struct, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(struct) |
||||
} |
||||
element = _create_base_element('struct', |
||||
struct.name, |
||||
struct.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
self._data['elements'].append(element) |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Events |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_event(self, event, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(event), |
||||
'signature': event.full_name |
||||
} |
||||
element = _create_base_element('event', |
||||
event.name, |
||||
event.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
|
||||
self._data['elements'].append(element) |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Nodes |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_node(self, node, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'parent': _create_parent_element(node), |
||||
} |
||||
node_name = str(node.expression) if node.expression else "" |
||||
element = _create_base_element('node', |
||||
node_name, |
||||
node.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
self._data['elements'].append(element) |
||||
|
||||
def add_nodes(self, nodes): |
||||
for node in sorted(nodes, key=lambda x: x.node_id): |
||||
self.add_node(node) |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Pragma |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_pragma(self, pragma, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'directive': pragma.directive |
||||
} |
||||
element = _create_base_element('pragma', |
||||
pragma.version, |
||||
pragma.source_mapping, |
||||
type_specific_fields, |
||||
additional_fields) |
||||
self._data['elements'].append(element) |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region File |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_file(self, filename, content, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'filename': filename, |
||||
'content': content |
||||
} |
||||
element = _create_base_element('file', |
||||
type_specific_fields, |
||||
additional_fields) |
||||
|
||||
self._data['elements'].append(element) |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Pretty Table |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_pretty_table(self, content, name, additional_fields=None): |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
type_specific_fields = { |
||||
'content': content, |
||||
'name': name |
||||
} |
||||
element = _create_base_element('pretty_table', |
||||
type_specific_fields, |
||||
additional_fields) |
||||
|
||||
self._data['elements'].append(element) |
||||
|
||||
# endregion |
||||
################################################################################### |
||||
################################################################################### |
||||
# region Others |
||||
################################################################################### |
||||
################################################################################### |
||||
|
||||
def add_other(self, name, source_mapping, slither, additional_fields=None): |
||||
# If this a tuple with (filename, start, end), convert it to a source mapping. |
||||
if additional_fields is None: |
||||
additional_fields = {} |
||||
if isinstance(source_mapping, tuple): |
||||
# Parse the source id |
||||
(filename, start, end) = source_mapping |
||||
source_id = next( |
||||
(source_unit_id for (source_unit_id, source_unit_filename) in slither.source_units.items() if |
||||
source_unit_filename == filename), -1) |
||||
|
||||
# Convert to a source mapping string |
||||
source_mapping = f"{start}:{end}:{source_id}" |
||||
|
||||
# If this is a source mapping string, parse it. |
||||
if isinstance(source_mapping, str): |
||||
source_mapping_str = source_mapping |
||||
source_mapping = SourceMapping() |
||||
source_mapping.set_offset(source_mapping_str, slither) |
||||
|
||||
# If this is a source mapping object, get the underlying source mapping dictionary |
||||
if isinstance(source_mapping, SourceMapping): |
||||
source_mapping = source_mapping.source_mapping |
||||
|
||||
# Create the underlying element and add it to our resulting json |
||||
element = _create_base_element('other', |
||||
name, |
||||
source_mapping, |
||||
{}, |
||||
additional_fields) |
||||
self._data['elements'].append(element) |
Loading…
Reference in new issue