254 lines
7.1 KiB
Python
254 lines
7.1 KiB
Python
# SPDX-FileCopyrightText: 2026 Art Sea LLC
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from typing import Protocol, Tuple
|
|
|
|
from band_aider.context.class_meta import ClassMeta
|
|
from band_aider.judgement.code_dependency_graph import (
|
|
BindingSite,
|
|
CodeDependencyGraph,
|
|
DeclarationSite,
|
|
DependencySelector,
|
|
DependencyType,
|
|
IndirectReference,
|
|
ParentRelationship,
|
|
ReturnSite,
|
|
)
|
|
|
|
|
|
GraphSignature = Tuple[Tuple[str, ...], Tuple[str, ...]]
|
|
|
|
|
|
class CodeDependencyGraphMaintainer(Protocol):
|
|
"""CodeDependencyGraphMaintainer owns one dependency graph and keeps it current."""
|
|
|
|
@property
|
|
def graph(self) -> CodeDependencyGraph:
|
|
"""Return the maintained dependency graph."""
|
|
|
|
...
|
|
|
|
@property
|
|
def signature(self) -> GraphSignature | None:
|
|
"""Return the last maintained source/test location signature."""
|
|
|
|
...
|
|
|
|
@property
|
|
def is_frozen(self) -> bool:
|
|
"""Return whether graph maintenance mutation is disabled."""
|
|
|
|
...
|
|
|
|
@signature.setter
|
|
def signature(self, value: GraphSignature | None) -> None:
|
|
"""Store the last maintained source/test location signature."""
|
|
|
|
...
|
|
|
|
def build(
|
|
self,
|
|
source_files: list[ClassMeta],
|
|
test_files: list[ClassMeta],
|
|
repo_root: Path,
|
|
src_root: Path,
|
|
test_root: Path,
|
|
) -> CodeDependencyGraph:
|
|
"""Build and store a reusable source/test dependency graph."""
|
|
|
|
...
|
|
|
|
def upsert(
|
|
self,
|
|
class_meta: ClassMeta,
|
|
source_files: list[ClassMeta],
|
|
test_files: list[ClassMeta],
|
|
repo_root: Path,
|
|
src_root: Path,
|
|
test_root: Path,
|
|
) -> CodeDependencyGraph:
|
|
"""Create or update one ClassMeta-owned graph slice and repair its affected evidence."""
|
|
|
|
...
|
|
|
|
def direct_tests_for(self, source_files: list[ClassMeta]) -> list[ClassMeta]:
|
|
"""Return one-hop source-to-test mappings."""
|
|
|
|
...
|
|
|
|
def delete(
|
|
self,
|
|
class_meta: ClassMeta,
|
|
source_files: list[ClassMeta],
|
|
test_files: list[ClassMeta],
|
|
repo_root: Path,
|
|
src_root: Path,
|
|
test_root: Path,
|
|
) -> CodeDependencyGraph:
|
|
"""Delete one ClassMeta-owned graph slice and its connected evidence."""
|
|
|
|
...
|
|
|
|
def freeze(self) -> None:
|
|
"""Freeze the maintained graph and reject future mutation."""
|
|
|
|
...
|
|
|
|
def trace_types_defined_in(self, source_location: str) -> list[DependencyType]:
|
|
"""Return types defined in one source."""
|
|
|
|
...
|
|
|
|
def direct_parent_type_ids_of(self, child_type_id: str) -> set[str]:
|
|
"""Return direct parent type IDs for one child type."""
|
|
|
|
...
|
|
|
|
def direct_child_type_ids_of(self, parent_type_id: str) -> set[str]:
|
|
"""Return direct child type IDs for one parent type."""
|
|
|
|
...
|
|
|
|
def trace_declaration_sites_in(self, source_location: str) -> list[DeclarationSite]:
|
|
"""Return declaration sites owned by one source."""
|
|
|
|
...
|
|
|
|
def trace_declaration_sites_declaring(self, type_id: str) -> list[DeclarationSite]:
|
|
"""Return declaration sites declaring one type."""
|
|
|
|
...
|
|
|
|
def trace_declaration_sites_for_callable(self, callable_id: str) -> list[DeclarationSite]:
|
|
"""Return declaration sites owned by one callable."""
|
|
|
|
...
|
|
|
|
def trace_binding_sites_in(self, source_location: str) -> list[BindingSite]:
|
|
"""Return binding sites owned by one source."""
|
|
|
|
...
|
|
|
|
def trace_binding_sites_for_declaration(self, declaration_site_id: str) -> list[BindingSite]:
|
|
"""Return bindings for one declaration site."""
|
|
|
|
...
|
|
|
|
def trace_binding_sites_supplying(self, type_id: str) -> list[BindingSite]:
|
|
"""Return bindings directly supplying one actual type."""
|
|
|
|
...
|
|
|
|
def binding_sites_returned_by(self, callable_id: str) -> list[BindingSite]:
|
|
"""Return bindings whose value is produced by one callable."""
|
|
|
|
...
|
|
|
|
def trace_return_sites_in(self, source_location: str) -> list[ReturnSite]:
|
|
"""Return return sites owned by one source."""
|
|
|
|
...
|
|
|
|
def trace_return_sites_for_callable(self, callable_id: str) -> list[ReturnSite]:
|
|
"""Return return sites for one callable."""
|
|
|
|
...
|
|
|
|
def trace_return_sites_declaring(self, type_id: str) -> list[ReturnSite]:
|
|
"""Return return sites declaring one return type."""
|
|
|
|
...
|
|
|
|
def trace_return_sites_returning(self, type_id: str) -> list[ReturnSite]:
|
|
"""Return return sites directly returning one actual type."""
|
|
|
|
...
|
|
|
|
def trace_return_sites_calling(self, callable_id: str) -> list[ReturnSite]:
|
|
"""Return return sites whose value comes from one callable."""
|
|
|
|
...
|
|
|
|
def trace_indirect_references_for_declaration(self, declaration_site_id: str) -> list[IndirectReference]:
|
|
"""Return references for one declaration site."""
|
|
|
|
...
|
|
|
|
def trace_indirect_references_through_binding(self, binding_site_id: str) -> list[IndirectReference]:
|
|
"""Return references through one binding site."""
|
|
|
|
...
|
|
|
|
def trace_indirect_references_through_return(self, return_site_id: str) -> list[IndirectReference]:
|
|
"""Return references through one return site."""
|
|
|
|
...
|
|
|
|
def trace_indirect_references_using_actual_type(self, type_id: str) -> list[IndirectReference]:
|
|
"""Return references using one actual type."""
|
|
|
|
...
|
|
|
|
def trace_indirect_references_using_parent_relationship(self, relationship_id: str) -> list[IndirectReference]:
|
|
"""Return references using one parent relationship."""
|
|
|
|
...
|
|
|
|
def trace_dynamic_dependencies_of(self, source_location: str) -> set[str]:
|
|
"""Return one-hop dynamic dependency sources."""
|
|
|
|
...
|
|
|
|
def trace_dynamic_dependents_of(self, source_location: str) -> set[str]:
|
|
"""Return one-hop dynamic dependent sources."""
|
|
|
|
...
|
|
|
|
def source_dependencies_of(
|
|
self,
|
|
source_location: str,
|
|
selector: DependencySelector = DependencySelector.BOTH,
|
|
) -> set[str]:
|
|
"""Return one-hop source dependencies for the selected evidence."""
|
|
|
|
...
|
|
|
|
def source_dependents_of(
|
|
self,
|
|
source_location: str,
|
|
selector: DependencySelector = DependencySelector.BOTH,
|
|
) -> set[str]:
|
|
"""Return one-hop source dependents for the selected evidence."""
|
|
|
|
...
|
|
|
|
def dependency_kind_between(
|
|
self,
|
|
dependent: str,
|
|
dependency: str,
|
|
) -> DependencySelector | None:
|
|
"""Classify static and dynamic evidence for one source pair."""
|
|
|
|
...
|
|
|
|
def upstream_sources_for(
|
|
self,
|
|
source_files: list[ClassMeta],
|
|
selector: DependencySelector = DependencySelector.BOTH,
|
|
) -> list[ClassMeta]:
|
|
"""Return one-hop upstream sources for source or test inputs."""
|
|
|
|
...
|
|
|
|
def downstream_sources_for(
|
|
self,
|
|
source_files: list[ClassMeta],
|
|
selector: DependencySelector = DependencySelector.BOTH,
|
|
) -> list[ClassMeta]:
|
|
"""Return one-hop downstream sources."""
|
|
|
|
...
|