@@ -38,6 +38,28 @@ struct DenseMapInfo<clice::index::Occurrence> {
3838 }
3939};
4040
41+ template <>
42+ struct DenseMapInfo <clice::index::IncludeDefinition> {
43+ using R = clice::LocalSourceRange;
44+ using V = clice::index::IncludeDefinition;
45+
46+ inline static V getEmptyKey () {
47+ return V (R (-1 , 0 ), 0 );
48+ }
49+
50+ inline static V getTombstoneKey () {
51+ return V (R (-2 , 0 ), 0 );
52+ }
53+
54+ static auto getHashValue (const V& v) {
55+ return dense_hash (v.range .begin , v.range .end , v.target_path );
56+ }
57+
58+ static bool isEqual (const V& lhs, const V& rhs) {
59+ return lhs.range == rhs.range && lhs.target_path == rhs.target_path ;
60+ }
61+ };
62+
4163template <>
4264struct DenseMapInfo <clice::index::Relation> {
4365 using R = clice::index::Relation;
@@ -134,12 +156,18 @@ struct MergedIndex::Impl {
134156 // / All merged symbol occurrences.
135157 llvm::DenseMap<Occurrence, roaring::Roaring> occurrences;
136158
159+ // / All merged include definitions.
160+ llvm::DenseMap<IncludeDefinition, roaring::Roaring> include_definitions;
161+
137162 // / All merged symbol relations.
138163 llvm::DenseMap<SymbolHash, llvm::DenseMap<Relation, roaring::Roaring>> relations;
139164
140165 // / Sorted occurrences cache for fast lookup.
141166 std::vector<Occurrence> occurrences_cache;
142167
168+ // / Sorted include definitions cache for fast lookup.
169+ std::vector<IncludeDefinition> include_definitions_cache;
170+
143171 void merge (this Impl& self, std::uint32_t path_id, FileIndex& index, auto && add_context) {
144172 auto hash = index.hash ();
145173 auto hash_key = llvm::StringRef (reinterpret_cast <char *>(hash.data ()), hash.size ());
@@ -158,6 +186,10 @@ struct MergedIndex::Impl {
158186 self.occurrences [occurrence].add (canonical_id);
159187 }
160188
189+ for (auto & include: index.include_definitions ) {
190+ self.include_definitions [include].add (canonical_id);
191+ }
192+
161193 for (auto & [symbol_id, relations]: index.relations ) {
162194 auto & target = self.relations [symbol_id];
163195 for (auto & relation: relations) {
@@ -245,6 +277,14 @@ void MergedIndex::load_in_memory(this Self& self) {
245277 read_bitmap (entry->context ()));
246278 }
247279
280+ if (root->include_definitions ()) {
281+ for (auto entry: *root->include_definitions ()) {
282+ index.include_definitions .try_emplace (
283+ *safe_cast<IncludeDefinition>(entry->include_definition ()),
284+ read_bitmap (entry->context ()));
285+ }
286+ }
287+
248288 for (auto entry: *root->relations ()) {
249289 auto & relations = index.relations [entry->symbol ()];
250290 for (auto relation_entry: *entry->relations ()) {
@@ -329,6 +369,27 @@ void MergedIndex::serialize(this const Self& self, llvm::raw_ostream& out) {
329369 std::tuple (ro.range .begin , ro.range .end , ro.target );
330370 });
331371
372+ llvm::SmallVector<const IncludeDefinition*> include_definition_keys;
373+ include_definition_keys.reserve (index->include_definitions .size ());
374+ auto include_definitions = transform (index->include_definitions , [&](auto && value) {
375+ auto && [include, bitmap] = value;
376+ buffer.clear ();
377+ buffer.resize_for_overwrite (bitmap.getSizeInBytes (false ));
378+ bitmap.write (buffer.data (), false );
379+ include_definition_keys.emplace_back (&include);
380+ return binary::CreateIncludeDefinitionEntry (
381+ builder,
382+ safe_cast<binary::IncludeDefinition>(&include),
383+ CreateVector (builder, buffer));
384+ });
385+ std::ranges::sort (std::views::zip (include_definition_keys, include_definitions),
386+ [](auto lhs, auto rhs) {
387+ const auto & lo = *std::get<0 >(lhs);
388+ const auto & ro = *std::get<0 >(rhs);
389+ return std::tuple (lo.range .begin , lo.range .end , lo.target_path ) <
390+ std::tuple (ro.range .begin , ro.range .end , ro.target_path );
391+ });
392+
332393 llvm::SmallVector<std::uint64_t > relation_keys;
333394 relation_keys.reserve (index->relations .size ());
334395 auto relations = transform (index->relations , [&](auto && value) {
@@ -369,7 +430,8 @@ void MergedIndex::serialize(this const Self& self, llvm::raw_ostream& out) {
369430 CreateVector (builder, occurrences),
370431 CreateVector (builder, relations),
371432 removed,
372- content_offset);
433+ content_offset,
434+ CreateVector (builder, include_definitions));
373435 builder.Finish (merged_index);
374436
375437 out.write (safe_cast<char >(builder.GetBufferPointer ()), builder.GetSize ());
@@ -443,6 +505,81 @@ void MergedIndex::lookup(this const Self& self,
443505 }
444506}
445507
508+ void MergedIndex::lookup_include_definition (
509+ this const Self& self,
510+ std::uint32_t offset,
511+ llvm::function_ref<bool (const IncludeDefinition&)> callback) {
512+ if (self.impl ) {
513+ auto & index = *self.impl ;
514+ auto & includes = index.include_definitions_cache ;
515+ if (includes.empty ()) {
516+ for (auto & [include, _]: index.include_definitions ) {
517+ includes.emplace_back (include);
518+ }
519+ std::ranges::sort (includes,
520+ [](const IncludeDefinition& lhs, const IncludeDefinition& rhs) {
521+ return std::tuple (lhs.range .begin ,
522+ lhs.range .end ,
523+ lhs.target_path ) < std::tuple (rhs.range .begin ,
524+ rhs.range .end ,
525+ rhs.target_path );
526+ });
527+ }
528+
529+ auto it = std::ranges::lower_bound (includes, offset, {}, [](const IncludeDefinition& i) {
530+ return i.range .end ;
531+ });
532+
533+ while (it != includes.end ()) {
534+ if (it->range .contains (offset)) {
535+ if (!index.removed .isEmpty ()) {
536+ auto bitmap_it = index.include_definitions .find (*it);
537+ if (bitmap_it != index.include_definitions .end ()) {
538+ auto remaining = bitmap_it->second - index.removed ;
539+ if (remaining.isEmpty ()) {
540+ it++;
541+ continue ;
542+ }
543+ }
544+ }
545+
546+ if (!callback (*it)) {
547+ break ;
548+ }
549+
550+ it++;
551+ continue ;
552+ }
553+
554+ break ;
555+ }
556+ } else if (self.buffer ) {
557+ auto index = fbs::GetRoot<binary::MergedIndex>(self.buffer ->getBufferStart ());
558+ auto include_definitions = index->include_definitions ();
559+ if (!include_definitions) {
560+ return ;
561+ }
562+
563+ auto it = std::ranges::lower_bound (*include_definitions, offset, {}, [](auto i) {
564+ return i->include_definition ()->range ().end ();
565+ });
566+
567+ while (it != include_definitions->end ()) {
568+ auto include = safe_cast<IncludeDefinition>((*it)->include_definition ());
569+ if (include->range .contains (offset)) {
570+ if (!callback (*include)) {
571+ break ;
572+ }
573+
574+ it++;
575+ continue ;
576+ }
577+
578+ break ;
579+ }
580+ }
581+ }
582+
446583void MergedIndex::lookup (this const Self& self,
447584 SymbolHash symbol,
448585 RelationKind kind,
@@ -577,6 +714,7 @@ void MergedIndex::remove(this Self& self, std::uint32_t path_id) {
577714
578715 // Invalidate cached occurrences.
579716 index.occurrences_cache .clear ();
717+ index.include_definitions_cache .clear ();
580718}
581719
582720void MergedIndex::merge (this Self& self,
@@ -594,6 +732,7 @@ void MergedIndex::merge(this Self& self,
594732 context.include_locations = std::move (include_locations);
595733 });
596734 self.impl ->occurrences_cache .clear ();
735+ self.impl ->include_definitions_cache .clear ();
597736}
598737
599738void MergedIndex::merge (this Self& self,
@@ -610,6 +749,7 @@ void MergedIndex::merge(this Self& self,
610749 context.includes .emplace_back (include_id, canonical_id);
611750 });
612751 self.impl ->occurrences_cache .clear ();
752+ self.impl ->include_definitions_cache .clear ();
613753}
614754
615755llvm::StringRef MergedIndex::content (this const Self& self) {
0 commit comments