1pub mod extractor;
15pub mod hits;
16pub mod inverted;
17mod macro_lexical;
18pub mod namespace_alias;
19pub mod resolver;
20pub mod syntax;
21
22use crate::graph_support::CppSource;
23use brokk_bifrost_core::analyzer::capabilities::{TypeAliasProvider, TypeHierarchyProvider};
24use brokk_bifrost_core::analyzer::fq_name::FqName;
25use brokk_bifrost_core::analyzer::model::{CppFieldLinkage, SignatureMetadata};
26use brokk_bifrost_core::analyzer::query_token::QueryToken;
27use brokk_bifrost_core::analyzer::{CodeUnit, CodeUnitIndex, ProjectFile, Range};
28use std::collections::BTreeSet;
29
30pub(super) fn cpp_namespace_path_is_ordered_subsequence(
31 namespace: &[String],
32 owner_scope: &[String],
33) -> bool {
34 let mut owner_components = owner_scope.iter();
35 namespace
36 .iter()
37 .all(|component| owner_components.any(|candidate| candidate == component))
38}
39
40pub trait CppWorkspaceSource {
48 fn import_statements(&self, file: &ProjectFile) -> Vec<String>;
50
51 fn definitions_by_name(&self, token: QueryToken<'_>, name: &FqName) -> Vec<CodeUnit>;
55
56 fn definitions_by_identifier(&self, token: QueryToken<'_>, name: &FqName) -> Vec<CodeUnit>;
59}
60
61#[derive(Clone, Copy)]
68pub struct CppWorkspaceDefinitions<'a>(&'a dyn CppWorkspaceSource, QueryToken<'a>);
69
70impl<'a> CppWorkspaceDefinitions<'a> {
71 pub fn exact(&self, name: &FqName) -> Vec<CodeUnit> {
72 self.0.definitions_by_name(self.1, name)
73 }
74
75 pub fn identifier(&self, name: &FqName) -> Vec<CodeUnit> {
76 self.0.definitions_by_identifier(self.1, name)
77 }
78}
79
80#[derive(Clone, Copy)]
91pub struct CppGraphSource<'a> {
92 pub index: &'a dyn CodeUnitIndex,
93 pub cpp: Option<&'a dyn CppSource>,
94 pub aliases: Option<&'a dyn TypeAliasProvider>,
95 pub hierarchy: Option<&'a dyn TypeHierarchyProvider>,
96 pub workspace: &'a dyn CppWorkspaceSource,
97 pub token: QueryToken<'a>,
102}
103
104impl<'a> CppGraphSource<'a> {
105 pub fn from_source(source: &'a dyn CppSource, token: QueryToken<'a>) -> Self {
112 Self {
113 index: source,
114 cpp: Some(source),
115 aliases: Some(source),
116 hierarchy: Some(source),
117 workspace: source,
118 token,
119 }
120 }
121
122 pub fn type_alias_provider(&self) -> Option<&'a dyn TypeAliasProvider> {
123 self.aliases
124 }
125
126 pub fn type_hierarchy_provider(&self) -> Option<&'a dyn TypeHierarchyProvider> {
127 self.hierarchy
128 }
129
130 pub fn import_statements(&self, file: &ProjectFile) -> Vec<String> {
131 self.workspace.import_statements(file)
132 }
133
134 pub fn canonical_include_paths(&self, file: &ProjectFile) -> Option<Vec<String>> {
137 self.cpp?.canonical_include_paths(self.token, file)
138 }
139
140 pub fn workspace_definitions(&self) -> CppWorkspaceDefinitions<'a> {
141 CppWorkspaceDefinitions(self.workspace, self.token)
142 }
143
144 pub fn parent_of(&self, code_unit: &CodeUnit) -> Option<CodeUnit> {
145 self.index.parent_of(code_unit)
146 }
147
148 pub fn ranges(&self, code_unit: &CodeUnit) -> Vec<Range> {
149 self.index.ranges(code_unit)
150 }
151
152 pub fn enclosing_code_unit(&self, file: &ProjectFile, range: &Range) -> Option<CodeUnit> {
153 self.index.enclosing_code_unit(file, range)
154 }
155
156 pub fn declaration_source_occurrences(
157 &self,
158 unit: &CodeUnit,
159 ) -> Option<Vec<crate::source_facts::CppDeclarationOccurrence>> {
160 self.cpp?.declaration_source_occurrences(self.token, unit)
161 }
162
163 pub fn declaration_source_properties(
164 &self,
165 unit: &CodeUnit,
166 ) -> Option<Vec<brokk_bifrost_core::analyzer::cpp_facts::CppDeclarationSourceFact>> {
167 self.cpp?.declaration_source_properties(self.token, unit)
168 }
169
170 pub fn signature_metadata(&self, code_unit: &CodeUnit) -> Vec<SignatureMetadata> {
171 self.index.signature_metadata(code_unit)
172 }
173
174 pub fn cpp_field_linkage(&self, code_unit: &CodeUnit) -> Option<CppFieldLinkage> {
175 self.cpp?.cpp_field_linkage(code_unit)
176 }
177
178 pub fn signatures(&self, code_unit: &CodeUnit) -> Vec<String> {
179 self.index.signatures(code_unit)
180 }
181
182 pub fn get_source(&self, code_unit: &CodeUnit, include_comments: bool) -> Option<String> {
183 self.index.get_source(code_unit, include_comments)
184 }
185
186 pub fn indexed_source(&self, file: &ProjectFile) -> Option<String> {
187 self.index.indexed_source(file)
188 }
189
190 pub fn declarations(&self, file: &ProjectFile) -> BTreeSet<CodeUnit> {
191 self.index.declarations(file)
192 }
193
194 pub fn reference_uses_c_semantics(&self, file: &ProjectFile) -> bool {
200 match self.cpp {
201 Some(cpp) => resolver::reference_uses_c_semantics(cpp, file),
202 None => resolver::is_c_source_file(file),
203 }
204 }
205
206 pub fn declarations_in_reading(
209 &self,
210 file: &ProjectFile,
211 c_semantics: bool,
212 ) -> BTreeSet<CodeUnit> {
213 match self.cpp {
214 Some(cpp) if c_semantics => cpp.declarations_in_reading(file, true),
215 _ => self.index.declarations(file),
216 }
217 }
218
219 pub fn site_equivalent_units(&self, code_unit: &CodeUnit) -> Vec<CodeUnit> {
222 match self.cpp {
223 Some(cpp) => cpp.site_equivalent_units(code_unit),
224 None => Vec::new(),
225 }
226 }
227
228 pub fn direct_children(&self, code_unit: &CodeUnit) -> Vec<CodeUnit> {
229 self.index.direct_children(code_unit)
230 }
231
232 pub fn definitions(&self, fq_name: &str) -> Box<dyn Iterator<Item = CodeUnit> + '_> {
233 self.index.definitions(fq_name)
234 }
235}
236
237pub fn callable_definitions_share_identity_evidence(
246 analyzer: &CppGraphSource<'_>,
247 left: &CodeUnit,
248 right: &CodeUnit,
249) -> bool {
250 crate::identity::cpp_callable_definitions_share_identity_evidence(
251 analyzer.index,
252 left,
253 right,
254 |left_source, right_source| {
255 let Some(cpp) = analyzer.cpp else {
256 return false;
257 };
258 crate::identity::cpp_header_body_files_are_related(
259 cpp,
260 analyzer.token,
261 left_source,
262 right_source,
263 )
264 },
265 )
266}
267
268pub fn callable_definitions_share_identity_evidence_with_visibility(
274 analyzer: &CppGraphSource<'_>,
275 visibility: &resolver::VisibilityIndex<'_>,
276 left: &CodeUnit,
277 right: &CodeUnit,
278) -> bool {
279 crate::identity::cpp_callable_definitions_share_identity_evidence_with_visibility(
280 analyzer,
281 visibility,
282 left,
283 right,
284 |left_source, right_source| {
285 let Some(cpp) = analyzer.cpp else {
286 return false;
287 };
288 crate::identity::cpp_header_body_files_are_related(
289 cpp,
290 analyzer.token,
291 left_source,
292 right_source,
293 )
294 },
295 )
296}