@@ -113,6 +113,31 @@ def _get_package_name_from_content(content: str, path: Path) -> str:
113113 return path .parent .name
114114
115115
116+ def _resolve_bases (pattern_str : str , parent : Path , repo_root : Path | None ) -> list [Path ]:
117+ base_pattern = pattern_str .split ("*" )[0 ].rstrip ("/" )
118+ candidate_bases = [parent / base_pattern ]
119+ if repo_root :
120+ candidate_bases .append (repo_root / base_pattern )
121+ dirs : list [Path ] = []
122+ for base in candidate_bases :
123+ try :
124+ dirs .append (base .resolve ())
125+ except (OSError , ValueError ):
126+ pass
127+ return dirs
128+
129+
130+ def _any_dir_matches (dirs_to_check : set [Path ], embed_dirs : list [Path ]) -> bool :
131+ for d in dirs_to_check :
132+ try :
133+ resolved = d .resolve ()
134+ if any (resolved == ed or resolved .is_relative_to (ed ) for ed in embed_dirs ):
135+ return True
136+ except (ValueError , OSError ):
137+ continue
138+ return False
139+
140+
116141class GoEdgeBuilder (EdgeBuilder ):
117142 weight = 0.75
118143 import_weight = EDGE_WEIGHTS ["go_import" ].forward
@@ -127,55 +152,55 @@ def discover_related_files(
127152 all_candidate_files : list [Path ],
128153 repo_root : Path | None = None ,
129154 ) -> list [Path ]:
130- go_changed = [f for f in changed_files if _is_go_file (f )]
131155 changed_set = set (changed_files )
132156 discovered : set [Path ] = set ()
157+ candidates = [c for c in all_candidate_files if c not in changed_set and _is_go_file (c )]
133158
159+ go_changed = [f for f in changed_files if _is_go_file (f )]
134160 if go_changed :
135- changed_pkg_dirs = {f .parent for f in go_changed }
136- for candidate in all_candidate_files :
137- if candidate not in changed_set and _is_go_file (candidate ) and candidate .parent in changed_pkg_dirs :
138- discovered .add (candidate )
161+ self ._discover_same_package (go_changed , candidates , discovered )
162+
163+ embed_go_files = self ._discover_embed_files (changed_files , candidates , discovered , repo_root )
164+ self ._discover_package_peers (embed_go_files , candidates , discovered )
165+
166+ return list (discovered )
167+
168+ def _discover_same_package (self , go_changed : list [Path ], candidates : list [Path ], discovered : set [Path ]) -> None :
169+ pkg_dirs = {f .parent for f in go_changed }
170+ for c in candidates :
171+ if c .parent in pkg_dirs :
172+ discovered .add (c )
139173
174+ def _discover_embed_files (
175+ self ,
176+ changed_files : list [Path ],
177+ candidates : list [Path ],
178+ discovered : set [Path ],
179+ repo_root : Path | None ,
180+ ) -> set [Path ]:
140181 changed_dirs = {f .parent for f in changed_files }
141182 embed_go_files : set [Path ] = set ()
142- for candidate in all_candidate_files :
143- if candidate not in changed_set and _is_go_file ( candidate ):
144- if self . _embeds_any_changed_dir ( candidate , changed_dirs , repo_root ):
145- discovered .add (candidate )
146- embed_go_files . add ( candidate )
183+ for c in candidates :
184+ if self . _embeds_any_changed_dir ( c , changed_dirs , repo_root ):
185+ discovered . add ( c )
186+ embed_go_files .add (c )
187+ return embed_go_files
147188
189+ def _discover_package_peers (self , embed_go_files : set [Path ], candidates : list [Path ], discovered : set [Path ]) -> None :
148190 embed_dirs = {f .parent for f in embed_go_files }
149- for candidate in all_candidate_files :
150- if candidate not in changed_set and _is_go_file (candidate ) and candidate not in discovered :
151- if candidate .parent in embed_dirs :
152- discovered .add (candidate )
153-
154- return list (discovered )
191+ for c in candidates :
192+ if c not in discovered and c .parent in embed_dirs :
193+ discovered .add (c )
155194
156195 def _embeds_any_changed_dir (self , go_file : Path , changed_dirs : set [Path ], repo_root : Path | None = None ) -> bool :
157196 try :
158197 content = go_file .read_text (encoding = "utf-8" )
159198 except (OSError , UnicodeDecodeError ):
160199 return False
161200 for match in _GO_EMBED_RE .finditer (content ):
162- embed_pattern = match .group (1 )
163- base_pattern = embed_pattern .split ("*" )[0 ].rstrip ("/" )
164- candidate_bases = [go_file .parent / base_pattern ]
165- if repo_root :
166- candidate_bases .append (repo_root / base_pattern )
167- for base in candidate_bases :
168- try :
169- embed_dir = base .resolve ()
170- except (OSError , ValueError ):
171- continue
172- for changed_dir in changed_dirs :
173- try :
174- resolved = changed_dir .resolve ()
175- if resolved == embed_dir or resolved .is_relative_to (embed_dir ):
176- return True
177- except (ValueError , OSError ):
178- continue
201+ embed_dirs = _resolve_bases (match .group (1 ), go_file .parent , repo_root )
202+ if _any_dir_matches (changed_dirs , embed_dirs ):
203+ return True
179204 return False
180205
181206 def build (self , fragments : list [Fragment ], repo_root : Path | None = None ) -> EdgeDict :
@@ -199,28 +224,26 @@ def _build_embed_edges(
199224 edges : EdgeDict ,
200225 repo_root : Path | None = None ,
201226 ) -> None :
227+ non_go_frags = [f for f in all_frags if not _is_go_file (f .path )]
202228 for gf in go_frags :
203229 for match in _GO_EMBED_RE .finditer (gf .content ):
204- embed_pattern = match .group (1 )
205- base_pattern = embed_pattern .split ("*" )[0 ].rstrip ("/" )
206- candidate_bases = [gf .path .parent / base_pattern ]
207- if repo_root :
208- candidate_bases .append (repo_root / base_pattern )
209- embed_dirs : list [Path ] = []
210- for base in candidate_bases :
211- try :
212- embed_dirs .append (base .resolve ())
213- except (OSError , ValueError ):
214- pass
215- for frag in all_frags :
216- if _is_go_file (frag .path ):
217- continue
218- try :
219- frag_resolved = frag .path .resolve ()
220- if any (frag_resolved .is_relative_to (ed ) for ed in embed_dirs ):
221- self .add_edge (edges , gf .id , frag .id , self .weight * 0.8 )
222- except (ValueError , OSError ):
223- continue
230+ embed_dirs = _resolve_bases (match .group (1 ), gf .path .parent , repo_root )
231+ self ._link_embed_targets (gf , non_go_frags , embed_dirs , edges )
232+
233+ def _link_embed_targets (
234+ self ,
235+ gf : Fragment ,
236+ non_go_frags : list [Fragment ],
237+ embed_dirs : list [Path ],
238+ edges : EdgeDict ,
239+ ) -> None :
240+ for frag in non_go_frags :
241+ try :
242+ frag_resolved = frag .path .resolve ()
243+ if any (frag_resolved .is_relative_to (ed ) for ed in embed_dirs ):
244+ self .add_edge (edges , gf .id , frag .id , self .weight * 0.8 )
245+ except (ValueError , OSError ):
246+ continue
224247
225248 def _build_indices (
226249 self , go_frags : list [Fragment ], repo_root : Path | None
0 commit comments