Skip to content

Commit cfe73d9

Browse files
committed
fix: address remaining SonarQube code quality issues
1 parent c499d0b commit cfe73d9

11 files changed

Lines changed: 306 additions & 178 deletions

File tree

src/treemapper/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def _validate_budget(budget: int | None) -> None:
3434

3535

3636
def _validate_alpha(alpha: float) -> None:
37-
if alpha <= 0 or alpha >= 1:
37+
if not (0 < alpha < 1):
3838
_exit_error(f"--alpha must be between 0 and 1 (exclusive), got {alpha}")
3939

4040

src/treemapper/diffctx/edges/config/terraform.py

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,7 @@ def discover_related_files(
120120
for candidate in all_candidate_files:
121121
if candidate in changed_set or not _is_terraform_file(candidate):
122122
continue
123-
if candidate.parent in tf_dirs:
124-
discovered.append(candidate)
125-
elif _is_in_module(candidate, module_sources, tf_dirs):
123+
if candidate.parent in tf_dirs or _is_in_module(candidate, module_sources, tf_dirs):
126124
discovered.append(candidate)
127125

128126
return discovered
@@ -221,24 +219,49 @@ def _build_module_source_edges(
221219
path_to_frags = build_path_to_frags(all_frags, repo_root)
222220

223221
for f in tf_frags:
224-
base_dir = f.path.parent
225-
226-
for match in _TF_SOURCE_RE.finditer(f.content):
227-
source = match.group(1)
228-
229-
if source.startswith("./") or source.startswith("../"):
230-
module_dir = (base_dir / source).resolve()
231-
for p, frag_ids in path_to_frags.items():
232-
try:
233-
if p.is_absolute():
234-
resolved = p.resolve()
235-
elif repo_root:
236-
resolved = (repo_root / p).resolve()
237-
else:
238-
resolved = p
239-
if resolved.parent == module_dir or str(resolved).startswith(str(module_dir)):
240-
for frag_id in frag_ids:
241-
if frag_id != f.id:
242-
self.add_edge(edges, f.id, frag_id, self.weight * 0.8)
243-
except (ValueError, OSError):
244-
continue
222+
self._link_module_sources(f, path_to_frags, edges, repo_root)
223+
224+
def _link_module_sources(
225+
self,
226+
f: Fragment,
227+
path_to_frags: dict[Path, list[FragmentId]],
228+
edges: EdgeDict,
229+
repo_root: Path | None,
230+
) -> None:
231+
base_dir = f.path.parent
232+
233+
for match in _TF_SOURCE_RE.finditer(f.content):
234+
source = match.group(1)
235+
if source.startswith("./") or source.startswith("../"):
236+
module_dir = (base_dir / source).resolve()
237+
self._link_files_in_module_dir(f, module_dir, path_to_frags, edges, repo_root)
238+
239+
def _link_files_in_module_dir(
240+
self,
241+
f: Fragment,
242+
module_dir: Path,
243+
path_to_frags: dict[Path, list[FragmentId]],
244+
edges: EdgeDict,
245+
repo_root: Path | None,
246+
) -> None:
247+
for p, frag_ids in path_to_frags.items():
248+
resolved = self._resolve_path(p, repo_root)
249+
if resolved is None:
250+
continue
251+
if self._is_in_module_dir(resolved, module_dir):
252+
for frag_id in frag_ids:
253+
if frag_id != f.id:
254+
self.add_edge(edges, f.id, frag_id, self.weight * 0.8)
255+
256+
def _resolve_path(self, p: Path, repo_root: Path | None) -> Path | None:
257+
try:
258+
if p.is_absolute():
259+
return p.resolve()
260+
if repo_root:
261+
return (repo_root / p).resolve()
262+
return p
263+
except (ValueError, OSError):
264+
return None
265+
266+
def _is_in_module_dir(self, resolved: Path, module_dir: Path) -> bool:
267+
return resolved.parent == module_dir or str(resolved).startswith(str(module_dir))

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

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -154,44 +154,60 @@ def _link_usings(
154154
edges: EdgeDict,
155155
) -> None:
156156
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)
157+
self._link_single_using(df.id, using, namespace_to_frags, fqn_to_frags, type_to_frags, edges)
161158

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)
159+
def _link_single_using(
160+
self,
161+
df_id: FragmentId,
162+
using: str,
163+
namespace_to_frags: dict[str, list[FragmentId]],
164+
fqn_to_frags: dict[str, list[FragmentId]],
165+
type_to_frags: dict[str, list[FragmentId]],
166+
edges: EdgeDict,
167+
) -> None:
168+
using_lower = using.lower()
169+
self._add_edges_from_index(df_id, namespace_to_frags.get(using_lower, []), self.using_weight, edges)
170+
self._add_edges_from_index(df_id, fqn_to_frags.get(using_lower, []), self.using_weight, edges)
165171

166-
parts = using.split(".")
167-
if parts:
168-
for fid in type_to_frags.get(parts[-1].lower(), []):
169-
if fid != df.id:
170-
self.add_edge(edges, df.id, fid, self.using_weight)
172+
parts = using.split(".")
173+
if parts:
174+
self._add_edges_from_index(df_id, type_to_frags.get(parts[-1].lower(), []), self.using_weight, edges)
175+
176+
def _add_edges_from_index(self, source_id: FragmentId, target_ids: list[FragmentId], weight: float, edges: EdgeDict) -> None:
177+
for fid in target_ids:
178+
if fid != source_id:
179+
self.add_edge(edges, source_id, fid, weight)
171180

172181
def _link_refs(
173182
self,
174183
df: Fragment,
175184
type_to_frags: dict[str, list[FragmentId]],
176185
edges: EdgeDict,
177186
) -> 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)
187+
self._link_inheritance(df.id, df.content, type_to_frags, edges)
188+
self._link_type_refs(df.id, df.content, type_to_frags, edges)
189+
self._link_attributes(df.id, df.content, type_to_frags, edges)
182190

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)
191+
def _link_inheritance(
192+
self, df_id: FragmentId, content: str, type_to_frags: dict[str, list[FragmentId]], edges: EdgeDict
193+
) -> None:
194+
for parent in _extract_inheritance(content):
195+
self._add_edges_from_index(df_id, type_to_frags.get(parent.lower(), []), self.inheritance_weight, edges)
187196

188-
for attr in _extract_attributes(df.content):
197+
def _link_type_refs(
198+
self, df_id: FragmentId, content: str, type_to_frags: dict[str, list[FragmentId]], edges: EdgeDict
199+
) -> None:
200+
for type_ref in _extract_type_refs(content):
201+
self._add_edges_from_index(df_id, type_to_frags.get(type_ref.lower(), []), self.type_weight, edges)
202+
203+
def _link_attributes(
204+
self, df_id: FragmentId, content: str, type_to_frags: dict[str, list[FragmentId]], edges: EdgeDict
205+
) -> None:
206+
for attr in _extract_attributes(content):
189207
attr_lower = attr.lower()
190208
attr_full = attr_lower if attr_lower.endswith("attribute") else attr_lower + "attribute"
191209
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)
210+
self._add_edges_from_index(df_id, type_to_frags.get(lookup, []), self.attribute_weight, edges)
195211

196212
def _link_same_namespace(
197213
self,

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

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,36 @@ def _link_imports(
133133
edges: EdgeDict,
134134
) -> None:
135135
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:
140-
if fid != gf.id:
141-
self.add_edge(edges, gf.id, fid, self.import_weight)
142-
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:
146-
if fid != gf.id:
147-
self.add_edge(edges, gf.id, fid, self.import_weight)
136+
self._link_import_by_package(gf.id, imp, pkg_to_frags, edges)
137+
self._link_import_by_path(gf.id, imp, path_to_frags, edges)
138+
139+
def _link_import_by_package(
140+
self,
141+
gf_id: FragmentId,
142+
imp: str,
143+
pkg_to_frags: dict[str, list[FragmentId]],
144+
edges: EdgeDict,
145+
) -> None:
146+
imp_pkg = imp.split("/")[-1]
147+
for pkg, frag_ids in pkg_to_frags.items():
148+
if pkg == imp_pkg:
149+
self._add_edges_from_ids(gf_id, frag_ids, self.import_weight, edges)
150+
151+
def _link_import_by_path(
152+
self,
153+
gf_id: FragmentId,
154+
imp: str,
155+
path_to_frags: dict[str, list[FragmentId]],
156+
edges: EdgeDict,
157+
) -> None:
158+
for path_str, frag_ids in path_to_frags.items():
159+
if imp in path_str or imp.endswith(path_str):
160+
self._add_edges_from_ids(gf_id, frag_ids, self.import_weight, edges)
161+
162+
def _add_edges_from_ids(self, source_id: FragmentId, target_ids: list[FragmentId], weight: float, edges: EdgeDict) -> None:
163+
for fid in target_ids:
164+
if fid != source_id:
165+
self.add_edge(edges, source_id, fid, weight)
148166

149167
def _link_refs(
150168
self,

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
_JS_SYMBOL_REF_WEIGHT = 0.75
1515
_JS_TYPE_REF_WEIGHT = 0.65
1616

17-
_JS_IMPORT_RE = re.compile(r"""import\s+[^'"]*['"]([^'"]+)['"]|require\s*\(\s*['"]([^'"]+)['"]\s*\)""")
17+
_JS_IMPORT_STATIC_RE = re.compile(r"""import\s+[^'"]*['"]([^'"]+)['"]""")
18+
_JS_REQUIRE_RE = re.compile(r"""require\s*\(\s*['"]([^'"]+)['"]\s*\)""")
1819
_JS_EXPORT_FROM_RE = re.compile(r"""export\s+.*?\s+from\s+['"]([^'"]+)['"]""")
1920

2021

@@ -53,15 +54,17 @@ def _normalize_import(imp: str, source_path: Path) -> set[str]:
5354
def _extract_imports_from_content(content: str, source_path: Path) -> set[str]:
5455
imports: set[str] = set()
5556

56-
for match in _JS_IMPORT_RE.finditer(content):
57-
imp = match.group(1) or match.group(2)
58-
if imp:
59-
imports.update(_normalize_import(imp, source_path))
57+
for match in _JS_IMPORT_STATIC_RE.finditer(content):
58+
if match.group(1):
59+
imports.update(_normalize_import(match.group(1), source_path))
60+
61+
for match in _JS_REQUIRE_RE.finditer(content):
62+
if match.group(1):
63+
imports.update(_normalize_import(match.group(1), source_path))
6064

6165
for match in _JS_EXPORT_FROM_RE.finditer(content):
62-
imp = match.group(1)
63-
if imp:
64-
imports.update(_normalize_import(imp, source_path))
66+
if match.group(1):
67+
imports.update(_normalize_import(match.group(1), source_path))
6568

6669
return imports
6770

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

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -193,16 +193,22 @@ def _add_use_edges(self, pf_id: FragmentId, uses: set[str], idx: _PHPIndex, edge
193193

194194
def _add_require_edges(self, pf_id: FragmentId, requires: set[str], idx: _PHPIndex, edges: EdgeDict) -> None:
195195
for req in requires:
196-
req_name = req.split("/")[-1].replace(".php", "").lower()
197-
for fid in idx.name_to_frags.get(req_name, []):
198-
if fid != pf_id:
199-
self.add_edge(edges, pf_id, fid, self.require_weight)
200-
201-
for path_str, frag_ids in idx.path_to_frags.items():
202-
if req in path_str:
203-
for fid in frag_ids:
204-
if fid != pf_id:
205-
self.add_edge(edges, pf_id, fid, self.require_weight)
196+
self._link_require_by_name(pf_id, req, idx, edges)
197+
self._link_require_by_path(pf_id, req, idx, edges)
198+
199+
def _link_require_by_name(self, pf_id: FragmentId, req: str, idx: _PHPIndex, edges: EdgeDict) -> None:
200+
req_name = req.split("/")[-1].replace(".php", "").lower()
201+
self._add_edges_from_ids(pf_id, idx.name_to_frags.get(req_name, []), self.require_weight, edges)
202+
203+
def _link_require_by_path(self, pf_id: FragmentId, req: str, idx: _PHPIndex, edges: EdgeDict) -> None:
204+
for path_str, frag_ids in idx.path_to_frags.items():
205+
if req in path_str:
206+
self._add_edges_from_ids(pf_id, frag_ids, self.require_weight, edges)
207+
208+
def _add_edges_from_ids(self, source_id: FragmentId, target_ids: list[FragmentId], weight: float, edges: EdgeDict) -> None:
209+
for fid in target_ids:
210+
if fid != source_id:
211+
self.add_edge(edges, source_id, fid, weight)
206212

207213
def _add_inheritance_edges(self, pf_id: FragmentId, inheritance: set[str], idx: _PHPIndex, edges: EdgeDict) -> None:
208214
for parent in inheritance:

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

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ def discover_related_files(
4747
if not py_changed:
4848
return []
4949

50+
changed_modules = self._collect_changed_modules(py_changed, repo_root)
51+
if not changed_modules:
52+
return []
53+
54+
changed_set = set(changed_files)
55+
return self._find_files_importing_modules(all_candidate_files, changed_set, changed_modules)
56+
57+
def _collect_changed_modules(self, py_changed: list[Path], repo_root: Path | None) -> set[str]:
5058
changed_modules: set[str] = set()
5159
for f in py_changed:
5260
module = path_to_module(f, repo_root)
@@ -55,32 +63,27 @@ def discover_related_files(
5563
parts = module.split(".")
5664
for i in range(1, len(parts) + 1):
5765
changed_modules.add(".".join(parts[:i]))
66+
return changed_modules
5867

59-
if not changed_modules:
60-
return []
61-
68+
def _find_files_importing_modules(
69+
self, all_candidate_files: list[Path], changed_set: set[Path], changed_modules: set[str]
70+
) -> list[Path]:
6271
discovered: list[Path] = []
63-
changed_set = set(changed_files)
64-
6572
for candidate in all_candidate_files:
66-
if candidate in changed_set:
67-
continue
68-
if not _is_python_file(candidate):
69-
continue
70-
71-
try:
72-
content = candidate.read_text(encoding="utf-8")
73-
imports = _extract_imports_from_content(content)
74-
75-
for imp in imports:
76-
if imp in changed_modules:
77-
discovered.append(candidate)
78-
break
79-
except (OSError, UnicodeDecodeError):
73+
if candidate in changed_set or not _is_python_file(candidate):
8074
continue
81-
75+
if self._imports_any_module(candidate, changed_modules):
76+
discovered.append(candidate)
8277
return discovered
8378

79+
def _imports_any_module(self, candidate: Path, changed_modules: set[str]) -> bool:
80+
try:
81+
content = candidate.read_text(encoding="utf-8")
82+
imports = _extract_imports_from_content(content)
83+
return any(imp in changed_modules for imp in imports)
84+
except (OSError, UnicodeDecodeError):
85+
return False
86+
8487
def build(self, fragments: list[Fragment], repo_root: Path | None = None) -> EdgeDict:
8588
py_frags = [f for f in fragments if f.path.suffix.lower() == ".py"]
8689
if not py_frags:

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

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -165,16 +165,22 @@ def _add_fragment_edges(self, rf: Fragment, idx: _RubyIndex, edges: EdgeDict, re
165165

166166
def _add_require_edges(self, rf_id: FragmentId, requires: set[str], idx: _RubyIndex, edges: EdgeDict) -> None:
167167
for req in requires:
168-
req_name = req.split("/")[-1].lower()
169-
for fid in idx.name_to_frags.get(req_name, []):
170-
if fid != rf_id:
171-
self.add_edge(edges, rf_id, fid, self.require_weight)
172-
173-
for path_str, frag_ids in idx.path_to_frags.items():
174-
if req in path_str or req.replace("/", "\\") in path_str:
175-
for fid in frag_ids:
176-
if fid != rf_id:
177-
self.add_edge(edges, rf_id, fid, self.require_weight)
168+
self._link_require_by_name(rf_id, req, idx, edges)
169+
self._link_require_by_path(rf_id, req, idx, edges)
170+
171+
def _link_require_by_name(self, rf_id: FragmentId, req: str, idx: _RubyIndex, edges: EdgeDict) -> None:
172+
req_name = req.split("/")[-1].lower()
173+
self._add_edges_from_ids(rf_id, idx.name_to_frags.get(req_name, []), self.require_weight, edges)
174+
175+
def _link_require_by_path(self, rf_id: FragmentId, req: str, idx: _RubyIndex, edges: EdgeDict) -> None:
176+
for path_str, frag_ids in idx.path_to_frags.items():
177+
if req in path_str or req.replace("/", "\\") in path_str:
178+
self._add_edges_from_ids(rf_id, frag_ids, self.require_weight, edges)
179+
180+
def _add_edges_from_ids(self, source_id: FragmentId, target_ids: list[FragmentId], weight: float, edges: EdgeDict) -> None:
181+
for fid in target_ids:
182+
if fid != source_id:
183+
self.add_edge(edges, source_id, fid, weight)
178184

179185
def _add_relative_require_edges(
180186
self,

0 commit comments

Comments
 (0)