mirror of
https://github.com/q3alique/codeflow
synced 2026-06-21 14:06:02 +00:00
acc1b4f3e7
Static taint-analysis and visualization tool for source-code security review. Supports deep analysis for Python, JavaScript/TypeScript, Java, Go, and C#, with structural support for all other languages via the generic extractor. Outputs: interactive HTML report, LLM-ready Markdown review document, and optional Burp Suite JSON export. Self-bootstrapping launcher (run.py) requires no virtual environment.
78 lines
2.4 KiB
Python
78 lines
2.4 KiB
Python
from __future__ import annotations
|
|
import networkx as nx
|
|
from codeflow.models.node import Node, NodeType
|
|
from codeflow.models.edge import Edge, EdgeType
|
|
from typing import Any
|
|
|
|
|
|
class CodeGraph:
|
|
def __init__(self):
|
|
self._graph: nx.DiGraph = nx.DiGraph()
|
|
|
|
@property
|
|
def graph(self) -> nx.DiGraph:
|
|
return self._graph
|
|
|
|
def add_node(self, node: Node):
|
|
self._graph.add_node(node.id, data=node)
|
|
|
|
def get_node(self, node_id: str) -> Node | None:
|
|
data = self._graph.nodes.get(node_id)
|
|
if data is None:
|
|
return None
|
|
return data.get("data")
|
|
|
|
def has_node(self, node_id: str) -> bool:
|
|
return self._graph.has_node(node_id)
|
|
|
|
def remove_node(self, node_id: str):
|
|
if self._graph.has_node(node_id):
|
|
self._graph.remove_node(node_id)
|
|
|
|
def add_edge(self, edge: Edge):
|
|
if self._graph.has_node(edge.source_id) and self._graph.has_node(edge.target_id):
|
|
self._graph.add_edge(edge.source_id, edge.target_id, data=edge)
|
|
|
|
def get_edge(self, source_id: str, target_id: str) -> Edge | None:
|
|
edges = self._graph.get_edge_data(source_id, target_id)
|
|
if edges is None:
|
|
return None
|
|
return edges.get("data")
|
|
|
|
def has_edge(self, source_id: str, target_id: str) -> bool:
|
|
return self._graph.has_edge(source_id, target_id)
|
|
|
|
def nodes(self) -> list[str]:
|
|
return list(self._graph.nodes())
|
|
|
|
def edges(self) -> list[tuple[str, str, Edge]]:
|
|
result = []
|
|
for u, v, d in self._graph.edges(data=True):
|
|
edge_data = d.get("data")
|
|
if edge_data is not None:
|
|
result.append((u, v, edge_data))
|
|
return result
|
|
|
|
def successors(self, node_id: str) -> list[str]:
|
|
return list(self._graph.successors(node_id))
|
|
|
|
def predecessors(self, node_id: str) -> list[str]:
|
|
return list(self._graph.predecessors(node_id))
|
|
|
|
def node_count(self) -> int:
|
|
return self._graph.number_of_nodes()
|
|
|
|
def edge_count(self) -> int:
|
|
return self._graph.number_of_edges()
|
|
|
|
def nodes_by_type(self, node_type: NodeType) -> list[Node]:
|
|
result = []
|
|
for nid in self._graph.nodes():
|
|
data = self._graph.nodes[nid].get("data")
|
|
if data and data.node_type == node_type:
|
|
result.append(data)
|
|
return result
|
|
|
|
def nx_graph(self) -> nx.DiGraph:
|
|
return self._graph
|