Skip to content

Commit c150638

Browse files
committed
refactor: reduce cognitive complexity in edge builders and graph.py
1 parent b661481 commit c150638

6 files changed

Lines changed: 478 additions & 291 deletions

File tree

src/treemapper/diffctx/edges/semantic/dotnet.py

Lines changed: 100 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -103,87 +103,116 @@ def build(self, fragments: list[Fragment], repo_root: Path | None = None) -> Edg
103103
return {}
104104

105105
edges: EdgeDict = {}
106+
indices = self._build_indices(dotnet_frags)
106107

108+
for df in dotnet_frags:
109+
self._link_fragment(df, indices, edges)
110+
111+
return edges
112+
113+
def _build_indices(
114+
self, dotnet_frags: list[Fragment]
115+
) -> tuple[dict[str, list[FragmentId]], dict[str, list[FragmentId]], dict[str, list[FragmentId]]]:
107116
namespace_to_frags: dict[str, list[FragmentId]] = defaultdict(list)
108117
type_to_frags: dict[str, list[FragmentId]] = defaultdict(list)
109118
fqn_to_frags: dict[str, list[FragmentId]] = defaultdict(list)
110119

111120
for f in dotnet_frags:
112121
ns = _extract_namespace(f.content, f.path)
113122
if ns:
114-
namespace_to_frags[ns.lower()].append(f.id)
115-
for i in range(len(ns.split("."))):
116-
partial_ns = ".".join(ns.split(".")[: i + 1])
123+
ns_parts = ns.split(".")
124+
for i in range(len(ns_parts)):
125+
partial_ns = ".".join(ns_parts[: i + 1])
117126
namespace_to_frags[partial_ns.lower()].append(f.id)
118127

119-
types = _extract_types(f.content, f.path)
120-
for t in types:
128+
for t in _extract_types(f.content, f.path):
121129
type_to_frags[t.lower()].append(f.id)
122130
if ns:
123-
fqn = f"{ns}.{t}"
124-
fqn_to_frags[fqn.lower()].append(f.id)
125-
126-
for df in dotnet_frags:
127-
usings = _extract_usings(df.content, df.path)
128-
inheritance = _extract_inheritance(df.content)
129-
type_refs = _extract_type_refs(df.content)
130-
attributes = _extract_attributes(df.content)
131-
current_ns = _extract_namespace(df.content, df.path)
132-
current_types = _extract_types(df.content, df.path)
133-
134-
for using in usings:
135-
using_lower = using.lower()
136-
if using_lower in namespace_to_frags:
137-
for fid in namespace_to_frags[using_lower]:
138-
if fid != df.id:
139-
self.add_edge(edges, df.id, fid, self.using_weight)
140-
141-
if using_lower in fqn_to_frags:
142-
for fid in fqn_to_frags[using_lower]:
143-
if fid != df.id:
144-
self.add_edge(edges, df.id, fid, self.using_weight)
145-
146-
parts = using.split(".")
147-
if parts:
148-
type_name = parts[-1].lower()
149-
if type_name in type_to_frags:
150-
for fid in type_to_frags[type_name]:
151-
if fid != df.id:
152-
self.add_edge(edges, df.id, fid, self.using_weight)
153-
154-
for parent in inheritance:
155-
parent_lower = parent.lower()
156-
if parent_lower in type_to_frags:
157-
for fid in type_to_frags[parent_lower]:
158-
if fid != df.id:
159-
self.add_edge(edges, df.id, fid, self.inheritance_weight)
160-
161-
for type_ref in type_refs:
162-
ref_lower = type_ref.lower()
163-
if ref_lower in type_to_frags:
164-
for fid in type_to_frags[ref_lower]:
165-
if fid != df.id:
166-
self.add_edge(edges, df.id, fid, self.type_weight)
167-
168-
for attr in attributes:
169-
attr_lower = attr.lower()
170-
attr_full = (attr_lower + "attribute") if not attr_lower.endswith("attribute") else attr_lower
171-
for lookup in [attr_lower, attr_full]:
172-
if lookup in type_to_frags:
173-
for fid in type_to_frags[lookup]:
174-
if fid != df.id:
175-
self.add_edge(edges, df.id, fid, self.attribute_weight)
176-
177-
if current_ns and current_ns.lower() in namespace_to_frags:
178-
for fid in namespace_to_frags[current_ns.lower()]:
131+
fqn_to_frags[f"{ns}.{t}".lower()].append(f.id)
132+
133+
return namespace_to_frags, type_to_frags, fqn_to_frags
134+
135+
def _link_fragment(
136+
self,
137+
df: Fragment,
138+
indices: tuple[dict[str, list[FragmentId]], dict[str, list[FragmentId]], dict[str, list[FragmentId]]],
139+
edges: EdgeDict,
140+
) -> None:
141+
namespace_to_frags, type_to_frags, fqn_to_frags = indices
142+
143+
self._link_usings(df, namespace_to_frags, fqn_to_frags, type_to_frags, edges)
144+
self._link_refs(df, type_to_frags, edges)
145+
self._link_same_namespace(df, namespace_to_frags, edges)
146+
self._link_partial_classes(df, type_to_frags, edges)
147+
148+
def _link_usings(
149+
self,
150+
df: Fragment,
151+
namespace_to_frags: dict[str, list[FragmentId]],
152+
fqn_to_frags: dict[str, list[FragmentId]],
153+
type_to_frags: dict[str, list[FragmentId]],
154+
edges: EdgeDict,
155+
) -> None:
156+
for using in _extract_usings(df.content, df.path):
157+
using_lower = using.lower()
158+
for fid in namespace_to_frags.get(using_lower, []):
159+
if fid != df.id:
160+
self.add_edge(edges, df.id, fid, self.using_weight)
161+
162+
for fid in fqn_to_frags.get(using_lower, []):
163+
if fid != df.id:
164+
self.add_edge(edges, df.id, fid, self.using_weight)
165+
166+
parts = using.split(".")
167+
if parts:
168+
for fid in type_to_frags.get(parts[-1].lower(), []):
179169
if fid != df.id:
180-
self.add_edge(edges, df.id, fid, self.same_namespace_weight)
181-
182-
for current_type in current_types:
183-
ct_lower = current_type.lower()
184-
if ct_lower in type_to_frags:
185-
for fid in type_to_frags[ct_lower]:
186-
if fid != df.id:
187-
self.add_edge(edges, df.id, fid, self.partial_class_weight)
188-
189-
return edges
170+
self.add_edge(edges, df.id, fid, self.using_weight)
171+
172+
def _link_refs(
173+
self,
174+
df: Fragment,
175+
type_to_frags: dict[str, list[FragmentId]],
176+
edges: EdgeDict,
177+
) -> None:
178+
for parent in _extract_inheritance(df.content):
179+
for fid in type_to_frags.get(parent.lower(), []):
180+
if fid != df.id:
181+
self.add_edge(edges, df.id, fid, self.inheritance_weight)
182+
183+
for type_ref in _extract_type_refs(df.content):
184+
for fid in type_to_frags.get(type_ref.lower(), []):
185+
if fid != df.id:
186+
self.add_edge(edges, df.id, fid, self.type_weight)
187+
188+
for attr in _extract_attributes(df.content):
189+
attr_lower = attr.lower()
190+
attr_full = attr_lower if attr_lower.endswith("attribute") else attr_lower + "attribute"
191+
for lookup in [attr_lower, attr_full]:
192+
for fid in type_to_frags.get(lookup, []):
193+
if fid != df.id:
194+
self.add_edge(edges, df.id, fid, self.attribute_weight)
195+
196+
def _link_same_namespace(
197+
self,
198+
df: Fragment,
199+
namespace_to_frags: dict[str, list[FragmentId]],
200+
edges: EdgeDict,
201+
) -> None:
202+
current_ns = _extract_namespace(df.content, df.path)
203+
if not current_ns:
204+
return
205+
for fid in namespace_to_frags.get(current_ns.lower(), []):
206+
if fid != df.id:
207+
self.add_edge(edges, df.id, fid, self.same_namespace_weight)
208+
209+
def _link_partial_classes(
210+
self,
211+
df: Fragment,
212+
type_to_frags: dict[str, list[FragmentId]],
213+
edges: EdgeDict,
214+
) -> None:
215+
for current_type in _extract_types(df.content, df.path):
216+
for fid in type_to_frags.get(current_type.lower(), []):
217+
if fid != df.id:
218+
self.add_edge(edges, df.id, fid, self.partial_class_weight)

src/treemapper/diffctx/edges/semantic/go.py

Lines changed: 85 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,18 @@ def build(self, fragments: list[Fragment], repo_root: Path | None = None) -> Edg
7070
return {}
7171

7272
edges: EdgeDict = {}
73+
indices = self._build_indices(go_frags, repo_root)
7374

75+
for gf in go_frags:
76+
self._link_fragment(gf, indices, edges)
77+
78+
return edges
79+
80+
def _build_indices(
81+
self, go_frags: list[Fragment], repo_root: Path | None
82+
) -> tuple[
83+
dict[str, list[FragmentId]], dict[str, list[FragmentId]], dict[str, list[FragmentId]], dict[str, list[FragmentId]]
84+
]:
7485
pkg_to_frags: dict[str, list[FragmentId]] = defaultdict(list)
7586
path_to_frags: dict[str, list[FragmentId]] = defaultdict(list)
7687
type_defs: dict[str, list[FragmentId]] = defaultdict(list)
@@ -83,8 +94,7 @@ def build(self, fragments: list[Fragment], repo_root: Path | None = None) -> Edg
8394
if repo_root:
8495
try:
8596
rel = f.path.relative_to(repo_root)
86-
pkg_path = str(rel.parent)
87-
path_to_frags[pkg_path].append(f.id)
97+
path_to_frags[str(rel.parent)].append(f.id)
8898
except ValueError:
8999
pass
90100

@@ -94,45 +104,80 @@ def build(self, fragments: list[Fragment], repo_root: Path | None = None) -> Edg
94104
for fn in funcs:
95105
func_defs[fn.lower()].append(f.id)
96106

97-
for gf in go_frags:
98-
imports = _extract_imports(gf.content)
99-
func_calls, type_refs, pkg_calls = _extract_references(gf.content)
100-
101-
for imp in imports:
102-
imp_pkg = imp.split("/")[-1]
103-
for pkg, frag_ids in pkg_to_frags.items():
104-
if pkg == imp_pkg:
105-
for fid in frag_ids:
106-
if fid != gf.id:
107-
self.add_edge(edges, gf.id, fid, self.import_weight)
108-
109-
for path_str, frag_ids in path_to_frags.items():
110-
if imp in path_str or imp.endswith(path_str):
111-
for fid in frag_ids:
112-
if fid != gf.id:
113-
self.add_edge(edges, gf.id, fid, self.import_weight)
114-
115-
for type_ref in type_refs:
116-
if type_ref.lower() in type_defs:
117-
for fid in type_defs[type_ref.lower()]:
107+
return pkg_to_frags, path_to_frags, type_defs, func_defs
108+
109+
def _link_fragment(
110+
self,
111+
gf: Fragment,
112+
indices: tuple[
113+
dict[str, list[FragmentId]], dict[str, list[FragmentId]], dict[str, list[FragmentId]], dict[str, list[FragmentId]]
114+
],
115+
edges: EdgeDict,
116+
) -> None:
117+
pkg_to_frags, path_to_frags, type_defs, func_defs = indices
118+
imports = _extract_imports(gf.content)
119+
func_calls, type_refs, pkg_calls = _extract_references(gf.content)
120+
121+
self._link_imports(gf, imports, pkg_to_frags, path_to_frags, edges)
122+
self._link_refs(gf, type_refs, type_defs, self.type_weight, edges)
123+
self._link_refs(gf, func_calls, func_defs, self.func_weight, edges)
124+
self._link_pkg_calls(gf, pkg_calls, pkg_to_frags, edges)
125+
self._link_same_package(gf, pkg_to_frags, edges)
126+
127+
def _link_imports(
128+
self,
129+
gf: Fragment,
130+
imports: set[str],
131+
pkg_to_frags: dict[str, list[FragmentId]],
132+
path_to_frags: dict[str, list[FragmentId]],
133+
edges: EdgeDict,
134+
) -> None:
135+
for imp in imports:
136+
imp_pkg = imp.split("/")[-1]
137+
for pkg, frag_ids in pkg_to_frags.items():
138+
if pkg == imp_pkg:
139+
for fid in frag_ids:
118140
if fid != gf.id:
119-
self.add_edge(edges, gf.id, fid, self.type_weight)
141+
self.add_edge(edges, gf.id, fid, self.import_weight)
120142

121-
for func_call in func_calls:
122-
if func_call.lower() in func_defs:
123-
for fid in func_defs[func_call.lower()]:
143+
for path_str, frag_ids in path_to_frags.items():
144+
if imp in path_str or imp.endswith(path_str):
145+
for fid in frag_ids:
124146
if fid != gf.id:
125-
self.add_edge(edges, gf.id, fid, self.func_weight)
126-
127-
for pkg_name, symbol in pkg_calls:
128-
if pkg_name.lower() in pkg_to_frags:
129-
for fid in pkg_to_frags[pkg_name.lower()]:
130-
if fid != gf.id:
131-
self.add_edge(edges, gf.id, fid, self.func_weight)
132-
133-
current_pkg = _get_package_name(gf.path)
134-
for fid in pkg_to_frags[current_pkg]:
147+
self.add_edge(edges, gf.id, fid, self.import_weight)
148+
149+
def _link_refs(
150+
self,
151+
gf: Fragment,
152+
refs: set[str],
153+
defs: dict[str, list[FragmentId]],
154+
weight: float,
155+
edges: EdgeDict,
156+
) -> None:
157+
for ref in refs:
158+
for fid in defs.get(ref.lower(), []):
135159
if fid != gf.id:
136-
self.add_edge(edges, gf.id, fid, self.same_package_weight)
137-
138-
return edges
160+
self.add_edge(edges, gf.id, fid, weight)
161+
162+
def _link_pkg_calls(
163+
self,
164+
gf: Fragment,
165+
pkg_calls: set[tuple[str, str]],
166+
pkg_to_frags: dict[str, list[FragmentId]],
167+
edges: EdgeDict,
168+
) -> None:
169+
for pkg_name, _symbol in pkg_calls:
170+
for fid in pkg_to_frags.get(pkg_name.lower(), []):
171+
if fid != gf.id:
172+
self.add_edge(edges, gf.id, fid, self.func_weight)
173+
174+
def _link_same_package(
175+
self,
176+
gf: Fragment,
177+
pkg_to_frags: dict[str, list[FragmentId]],
178+
edges: EdgeDict,
179+
) -> None:
180+
current_pkg = _get_package_name(gf.path)
181+
for fid in pkg_to_frags.get(current_pkg, []):
182+
if fid != gf.id:
183+
self.add_edge(edges, gf.id, fid, self.same_package_weight)

0 commit comments

Comments
 (0)