@@ -119,6 +119,32 @@ auto collect_facts(const extract::ProjectModel& model,
119119 return facts;
120120}
121121
122+ template <typename ... Groups>
123+ auto collect_merged_facts (const extract::ProjectModel& model,
124+ std::uint32_t max_count,
125+ const std::string& project_root,
126+ const Groups&... groups) -> std::vector<SymbolFact> {
127+ std::vector<SymbolFact> facts;
128+ std::unordered_set<extract::SymbolID> seen;
129+
130+ auto append_group = [&](const auto & ids) {
131+ for (const auto & id : ids) {
132+ if (facts.size () >= max_count) {
133+ return ;
134+ }
135+ if (!seen.insert (id).second ) {
136+ continue ;
137+ }
138+ if (auto * sym = lookup (model, id)) {
139+ facts.push_back (to_symbol_fact (*sym, project_root));
140+ }
141+ }
142+ };
143+
144+ (append_group (groups), ...);
145+ return facts;
146+ }
147+
122148auto collect_summaries (const PageSummaryCache& cache,
123149 const std::vector<std::string>& keys,
124150 std::uint32_t max_count) -> std::vector<std::string> {
@@ -403,9 +429,11 @@ auto build_evidence_for_function_declaration_summary(
403429 pack.target_facts .push_back (to_symbol_fact (target, root));
404430
405431 // Callers — how this function is used
406- pack.reverse_usage_context = collect_facts (model, target.called_by , rules.max_callers , root);
407- auto refs = collect_facts (model, target.referenced_by , rules.max_callers , root);
408- for (auto & f : refs) pack.reverse_usage_context .push_back (std::move (f));
432+ pack.reverse_usage_context = collect_merged_facts (model,
433+ rules.max_callers ,
434+ root,
435+ target.called_by ,
436+ target.referenced_by );
409437
410438 // Callees — what it delegates to (helps understand contract)
411439 pack.dependency_context = collect_facts (model, target.calls , rules.max_callees , root);
@@ -489,14 +517,15 @@ auto build_evidence_for_type_declaration_summary(
489517 pack.target_facts .push_back (to_symbol_fact (target, root));
490518
491519 // Callers / references — how this type is used
492- pack.reverse_usage_context = collect_facts (model, target.called_by , rules.max_callers , root);
493- auto refs = collect_facts (model, target.referenced_by , rules.max_callers , root);
494- for (auto & f : refs) pack.reverse_usage_context .push_back (std::move (f));
520+ pack.reverse_usage_context = collect_merged_facts (model,
521+ rules.max_callers ,
522+ root,
523+ target.called_by ,
524+ target.referenced_by ,
525+ target.derived );
495526
496527 // Base types and derived types
497528 pack.dependency_context = collect_facts (model, target.bases , rules.max_callees , root);
498- auto derived = collect_facts (model, target.derived , rules.max_callers , root);
499- for (auto & f : derived) pack.reverse_usage_context .push_back (std::move (f));
500529
501530 // Sibling types as local context
502531 if (!target.enclosing_namespace .empty ()) {
0 commit comments