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