Files
q3alique acc1b4f3e7 Initial release of codeflow
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.
2026-06-08 00:55:14 +02:00

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