@@ -616,24 +616,32 @@ using FileIdsToBeIndexedSet =
616
616
// / In the future, for cross-repo, a directory layout<->project mapping
617
617
// / may be supplied or inferred, which would provide canonical relative
618
618
// / paths for more files.
619
- class CanonicalPathMap final {
619
+ class StableFileIdMap final {
620
+ std::vector<RootRelativePath> storage;
621
+
622
+ struct ExternalFileEntry {
623
+ AbsolutePathRef absPath;
624
+ // Points to storage
625
+ RootRelativePathRef fakeRelativePath;
626
+ };
627
+
620
628
absl::flat_hash_map<llvm_ext::AbslHashAdapter<clang::FileID>,
621
- std::variant<RootRelativePathRef, AbsolutePathRef >>
629
+ std::variant<RootRelativePathRef, ExternalFileEntry >>
622
630
map;
623
631
624
632
const RootPath &projectRootPath;
625
633
626
634
const RootPath &buildRootPath;
627
635
628
636
public:
629
- CanonicalPathMap () = delete ;
630
- CanonicalPathMap (const RootPath &projectRootPath,
631
- const RootPath &buildRootPath)
637
+ StableFileIdMap () = delete ;
638
+ StableFileIdMap (const RootPath &projectRootPath,
639
+ const RootPath &buildRootPath)
632
640
: map(), projectRootPath(projectRootPath), buildRootPath(buildRootPath) {}
633
- CanonicalPathMap (CanonicalPathMap &&other) = default ;
634
- CanonicalPathMap &operator =(CanonicalPathMap &&) = delete ;
635
- CanonicalPathMap (const CanonicalPathMap &) = delete ;
636
- CanonicalPathMap &operator =(const CanonicalPathMap &) = delete ;
641
+ StableFileIdMap (StableFileIdMap &&other) = default ;
642
+ StableFileIdMap &operator =(StableFileIdMap &&) = delete ;
643
+ StableFileIdMap (const StableFileIdMap &) = delete ;
644
+ StableFileIdMap &operator =(const StableFileIdMap &) = delete ;
637
645
638
646
void populate (const ClangIdLookupMap &clangIdLookupMap) {
639
647
this ->map .reserve (clangIdLookupMap.size ());
@@ -683,28 +691,40 @@ class CanonicalPathMap final {
683
691
this ->projectRootPath .tryMakeRelative (absPathRef)) {
684
692
return insertRelPath (optProjectRootRelPath.value ());
685
693
}
686
- return this ->map .insert ({{fileId}, absPathRef}).second ;
694
+ auto optFileName = absPathRef.fileName ();
695
+ ENFORCE (optFileName.has_value (),
696
+ " Clang returned file path {} without a file name" ,
697
+ absPathRef.asStringView ());
698
+ this ->storage .emplace_back (
699
+ fmt::format (" <external>/{}/{}" ,
700
+ HashValue::forText (absPathRef.asStringView ()),
701
+ *optFileName),
702
+ RootKind::Build); // fake value to satisfy the RootRelativePathRef API
703
+ return this ->map
704
+ .insert ({{fileId},
705
+ ExternalFileEntry{absPathRef, this ->storage .back ().asRef ()}})
706
+ .second ;
687
707
}
688
708
689
709
bool contains (clang::FileID fileId) const {
690
710
return this ->map .contains ({fileId});
691
711
}
692
712
693
- // / See the doc comment on \c CanonicalPathMap
694
- std::optional<RootRelativePathRef>
695
- tryGetCanonicalPath (clang::FileID fileId) const {
713
+ // / See the doc comment on \c StableFileIdMap
714
+ std::optional<StableFileId> getStableFileId (clang::FileID fileId) const {
696
715
auto it = this ->map .find ({fileId});
697
- // TODO: Some headers like <built-in> and those in the Xcode SDK
698
- // are not getting populated here. That's fine, because they are
699
- // out-of-project anyways, but it seems weird that the populate(...)
700
- // call isn't adding them.
701
716
if (it == this ->map .end ()) {
702
717
return {};
703
718
}
704
719
if (std::holds_alternative<RootRelativePathRef>(it->second )) {
705
- return std::get<RootRelativePathRef>(it->second );
720
+ return StableFileId{.path = std::get<RootRelativePathRef>(it->second ),
721
+ .isInProject = true ,
722
+ .isSynthetic = false };
706
723
}
707
- return {};
724
+ return StableFileId{
725
+ .path = std::get<ExternalFileEntry>(it->second ).fakeRelativePath ,
726
+ .isInProject = false ,
727
+ .isSynthetic = true };
708
728
}
709
729
};
710
730
@@ -726,17 +746,17 @@ struct PartialScipIndex {
726
746
class IndexerAstVisitor : public clang ::RecursiveASTVisitor<IndexerAstVisitor> {
727
747
using Base = RecursiveASTVisitor;
728
748
729
- const CanonicalPathMap &pathMap ;
749
+ const StableFileIdMap &stableFileIdMap ;
730
750
FileIdsToBeIndexedSet toBeIndexed;
731
751
bool deterministic;
732
752
733
753
TuIndexer &tuIndexer;
734
754
735
755
public:
736
- IndexerAstVisitor (const CanonicalPathMap &pathMap,
737
- FileIdsToBeIndexedSet &&map , bool deterministic,
756
+ IndexerAstVisitor (const StableFileIdMap &pathMap,
757
+ FileIdsToBeIndexedSet &&toBeIndexed , bool deterministic,
738
758
TuIndexer &tuIndexer)
739
- : pathMap (pathMap), toBeIndexed(std::move(map )),
759
+ : stableFileIdMap (pathMap), toBeIndexed(std::move(toBeIndexed )),
740
760
deterministic (deterministic), tuIndexer(tuIndexer) {}
741
761
742
762
// See clang/include/clang/Basic/DeclNodes.td for list of declarations.
@@ -807,13 +827,15 @@ class IndexerAstVisitor : public clang::RecursiveASTVisitor<IndexerAstVisitor> {
807
827
808
828
void writeIndex (SymbolFormatter &&symbolFormatter, MacroIndexer &¯oIndex,
809
829
scip::Index &scipIndex) {
810
- std::vector<std::pair<RootRelativePathRef, clang::FileID>> relativePaths;
811
- for (auto wrappedFileId : toBeIndexed) {
812
- // We may have been asked to index files outside the project,
813
- // which lack canonical paths.
814
- if (auto optRelPathRef =
815
- pathMap.tryGetCanonicalPath (wrappedFileId.data )) {
816
- relativePaths.push_back ({optRelPathRef.value (), wrappedFileId.data });
830
+ std::vector<std::pair<RootRelativePathRef, clang::FileID>>
831
+ indexedProjectFiles;
832
+ for (auto wrappedFileId : this ->toBeIndexed ) {
833
+ if (auto optStableFileId =
834
+ this ->stableFileIdMap .getStableFileId (wrappedFileId.data )) {
835
+ if (optStableFileId->isInProject ) {
836
+ indexedProjectFiles.emplace_back (optStableFileId->path ,
837
+ wrappedFileId.data );
838
+ }
817
839
}
818
840
}
819
841
if (this ->deterministic ) {
@@ -824,10 +846,10 @@ class IndexerAstVisitor : public clang::RecursiveASTVisitor<IndexerAstVisitor> {
824
846
p1.first .asStringView ());
825
847
return cmp == std::strong_ordering::less;
826
848
};
827
- absl::c_sort (relativePaths , comparePaths);
849
+ absl::c_sort (indexedProjectFiles , comparePaths);
828
850
}
829
851
830
- for (auto [relPathRef, fileId] : relativePaths ) {
852
+ for (auto [relPathRef, fileId] : indexedProjectFiles ) {
831
853
scip::Document document;
832
854
auto relPath = relPathRef.asStringView ();
833
855
document.set_relative_path (relPath.data (), relPath.size ());
@@ -898,22 +920,22 @@ class IndexerAstConsumer : public clang::SemaConsumer {
898
920
return ;
899
921
}
900
922
901
- CanonicalPathMap canonicalPathMap {this ->options .projectRootPath ,
902
- this ->options .buildRootPath };
923
+ StableFileIdMap stableFileIdMap {this ->options .projectRootPath ,
924
+ this ->options .buildRootPath };
903
925
FileIdsToBeIndexedSet toBeIndexed{};
904
926
this ->computeFileIdsToBeIndexed (astContext, emitIndexDetails,
905
- clangIdLookupMap, canonicalPathMap ,
927
+ clangIdLookupMap, stableFileIdMap ,
906
928
toBeIndexed);
907
929
908
- auto getRelativePath =
909
- [&](clang::FileID fileId) -> std::optional<RootRelativePathRef > {
910
- return canonicalPathMap. tryGetCanonicalPath (fileId);
930
+ auto getStableFileId =
931
+ [&](clang::FileID fileId) -> std::optional<StableFileId > {
932
+ return stableFileIdMap. getStableFileId (fileId);
911
933
};
912
- SymbolFormatter symbolFormatter{sourceManager, getRelativePath };
934
+ SymbolFormatter symbolFormatter{sourceManager, getStableFileId };
913
935
TuIndexer tuIndexer{sourceManager, this ->sema ->getLangOpts (),
914
936
this ->sema ->getASTContext (), symbolFormatter};
915
937
916
- IndexerAstVisitor visitor{canonicalPathMap , std::move (toBeIndexed),
938
+ IndexerAstVisitor visitor{stableFileIdMap , std::move (toBeIndexed),
917
939
this ->options .deterministic , tuIndexer};
918
940
visitor.TraverseAST (astContext);
919
941
@@ -933,16 +955,16 @@ class IndexerAstConsumer : public clang::SemaConsumer {
933
955
void computeFileIdsToBeIndexed (const clang::ASTContext &astContext,
934
956
const EmitIndexJobDetails &emitIndexDetails,
935
957
const ClangIdLookupMap &clangIdLookupMap,
936
- CanonicalPathMap &canonicalPathMap ,
958
+ StableFileIdMap &stableFileIdMap ,
937
959
FileIdsToBeIndexedSet &toBeIndexed) {
938
960
auto &sourceManager = astContext.getSourceManager ();
939
961
auto mainFileId = sourceManager.getMainFileID ();
940
962
941
- canonicalPathMap .populate (clangIdLookupMap);
963
+ stableFileIdMap .populate (clangIdLookupMap);
942
964
if (auto *mainFileEntry = sourceManager.getFileEntryForID (mainFileId)) {
943
965
if (auto optMainFileAbsPath =
944
966
AbsolutePathRef::tryFrom (mainFileEntry->tryGetRealPathName ())) {
945
- canonicalPathMap .insert (mainFileId, optMainFileAbsPath.value ());
967
+ stableFileIdMap .insert (mainFileId, optMainFileAbsPath.value ());
946
968
toBeIndexed.insert ({mainFileId});
947
969
} else {
948
970
spdlog::debug (
@@ -971,7 +993,7 @@ class IndexerAstConsumer : public clang::SemaConsumer {
971
993
std::string message;
972
994
auto check = [&](auto wrappedFileId) -> bool {
973
995
auto fileId = wrappedFileId.data ;
974
- if (canonicalPathMap .contains (fileId)) {
996
+ if (stableFileIdMap .contains (fileId)) {
975
997
return true ;
976
998
}
977
999
message = fmt::format (" missing fileId {} for path: {}" ,
0 commit comments