MCPcopy Index your code
hub / github.com/tirth8205/code-review-graph / find_dead_code

Function find_dead_code

code_review_graph/refactor.py:240–579  ·  view source on GitHub ↗

Find functions/classes with no callers, no test refs, no importers, and no references. Entry points (functions matching framework decorators or conventional name patterns like ``main``, ``test_*``, ``handle_*``) are excluded. .. note:: **Caveats — dynamic dispatch patterns.**

(
    store: GraphStore,
    kind: Optional[str] = None,
    file_pattern: Optional[str] = None,
    root: Optional[Union[str, Path]] = None,
)

Source from the content-addressed store, hash-verified

238
239
240def find_dead_code(
241 store: GraphStore,
242 kind: Optional[str] = None,
243 file_pattern: Optional[str] = None,
244 root: Optional[Union[str, Path]] = None,
245) -> list[dict[str, Any]]:
246 """Find functions/classes with no callers, no test refs, no importers, and no references.
247
248 Entry points (functions matching framework decorators or conventional name
249 patterns like ``main``, ``test_*``, ``handle_*``) are excluded.
250
251 .. note::
252
253 **Caveats — dynamic dispatch patterns.** Static analysis cannot track
254 all runtime-determined call patterns. Functions registered via fully
255 dynamic keys (``map[computedKey()] = fn``), ``Reflect.apply``, or
256 runtime ``require()`` may still appear as dead code. Treat results as
257 hints, especially for TypeScript projects that use map-based dispatch,
258 plugin registries, or dynamic requires.
259
260 Args:
261 store: The GraphStore instance.
262 kind: Optional filter (e.g. ``"Function"`` or ``"Class"``).
263 file_pattern: Optional file-path substring filter.
264 root: Optional repo root path for computing ``relative_path``.
265
266 Returns:
267 List of dead-code dicts with name, qualified_name, kind, file_path,
268 relative_path, line, and language fields.
269 """
270 # Query candidate nodes.
271 candidates = store.get_nodes_by_kind(
272 kinds=[kind] if kind else ["Function", "Class"],
273 file_pattern=file_pattern,
274 )
275
276 # Build set of class names referenced in function type annotations.
277 type_ref_names = _collect_type_referenced_names(store)
278
279 # Build class hierarchy: class_qualified_name -> [bare_base_names]
280 class_bases: dict[str, list[str]] = {}
281 conn = store._conn
282 for row in conn.execute(
283 "SELECT source_qualified, target_qualified FROM edges WHERE kind = 'INHERITS'"
284 ).fetchall():
285 base = row[1].rsplit("::", 1)[-1] if "::" in row[1] else row[1]
286 class_bases.setdefault(row[0], []).append(base)
287
288 # Build import graph: file_path -> set of file_paths it imports from.
289 # Used to filter bare-name caller matches to plausible callers.
290 importer_files: dict[str, set[str]] = {}
291 for row in conn.execute(
292 "SELECT file_path, target_qualified FROM edges WHERE kind = 'IMPORTS_FROM'"
293 ).fetchall():
294 importer_files.setdefault(row[0], set()).add(row[1])
295
296 # Build set of globally unique names (only one non-test node with that name).
297 # For unique names, any bare-name CALLS edge is reliable — no ambiguity.

Calls 14

_is_entry_pointFunction · 0.85
_has_framework_decoratorFunction · 0.85
_is_plausible_callerFunction · 0.85
_sanitize_nameFunction · 0.85
get_nodes_by_kindMethod · 0.80
searchMethod · 0.80
get_edges_by_sourceMethod · 0.80
getMethod · 0.80
get_nodeMethod · 0.80
get_edges_by_targetMethod · 0.80