diff --git a/clang-tools-extra/clangd/indexer/IndexerMain.cpp b/clang-tools-extra/clangd/indexer/IndexerMain.cpp --- a/clang-tools-extra/clangd/indexer/IndexerMain.cpp +++ b/clang-tools-extra/clangd/indexer/IndexerMain.cpp @@ -20,7 +20,9 @@ #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Execution.h" #include "clang/Tooling/Tooling.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Signals.h" namespace clang { @@ -35,9 +37,36 @@ "binary RIFF format")), llvm::cl::init(IndexFileFormat::RIFF)); +static llvm::cl::opt + ProjectRoot("project-root", + llvm::cl::desc("Filter out all symbols outside of this " + "directory. This is useful for remote index."), + llvm::cl::Hidden); + +bool filterURI(llvm::StringRef URI, llvm::StringRef IndexRoot) { + auto Parsed = URI::parse(URI); + return !Parsed || !Parsed->body().startswith(IndexRoot); +} + +/// Returns true if \p Sym should be excluded from index. +bool filterSymbol(const Symbol &Sym, llvm::StringRef IndexRoot) { + if (*Sym.CanonicalDeclaration.FileURI) + if (filterURI(Sym.CanonicalDeclaration.FileURI, IndexRoot)) + return true; + if (*Sym.Definition.FileURI) + if (filterURI(Sym.Definition.FileURI, IndexRoot)) + return true; + for (const auto &Header : Sym.IncludeHeaders) + if (!isLiteralInclude(Header.IncludeHeader)) + if (filterURI(Header.IncludeHeader, IndexRoot)) + return true; + return false; +} + class IndexActionFactory : public tooling::FrontendActionFactory { public: - IndexActionFactory(IndexFileIn &Result) : Result(Result) {} + IndexActionFactory(IndexFileIn &Result, llvm::StringRef IndexRoot) + : Result(Result), IndexRoot(IndexRoot) {} std::unique_ptr create() override { SymbolCollector::Options Opts; @@ -56,10 +85,10 @@ }, [&](RefSlab S) { std::lock_guard Lock(SymbolsMu); - for (const auto &Sym : S) { + for (const auto &SymbolAndRefs : S) { // Deduplication happens during insertion. - for (const auto &Ref : Sym.second) - Refs.insert(Sym.first, Ref); + for (const auto &Ref : SymbolAndRefs.second) + Refs.insert(SymbolAndRefs.first, Ref); } }, [&](RelationSlab S) { @@ -77,6 +106,38 @@ Result.Symbols = std::move(Symbols).build(); Result.Refs = std::move(Refs).build(); Result.Relations = std::move(Relations).build(); + + // Post-filtering. + if (!IndexRoot.empty()) { + llvm::DenseSet ExcludeIDs; + for (const auto &Sym : *Result.Symbols) + if (filterSymbol(Sym, IndexRoot)) + ExcludeIDs.insert(Sym.ID); + + llvm::errs() << "Total symbols collected: " << Result.Symbols->size() + << ". Filtering out " << ExcludeIDs.size() << " of them.\n"; + + if (!ExcludeIDs.empty()) { + SymbolSlab::Builder FilteredSymbols; + RefSlab::Builder FilteredRefs; + RelationSlab::Builder FilteredRelations; + for (const auto &Sym : *Result.Symbols) + if (ExcludeIDs.find(Sym.ID) == ExcludeIDs.end()) + FilteredSymbols.insert(Sym); + for (const auto &SymbolAndRefs : *Result.Refs) + if (ExcludeIDs.find(SymbolAndRefs.first) == ExcludeIDs.end()) + for (const auto &Ref : SymbolAndRefs.second) + FilteredRefs.insert(SymbolAndRefs.first, Ref); + for (const auto &Rel : *Result.Relations) + if ((ExcludeIDs.find(Rel.Object) == ExcludeIDs.end()) && + (ExcludeIDs.find(Rel.Subject) == ExcludeIDs.end())) + FilteredRelations.insert(Rel); + + Result.Symbols = std::move(FilteredSymbols).build(); + Result.Refs = std::move(FilteredRefs).build(); + Result.Relations = std::move(FilteredRelations).build(); + } + } } private: @@ -85,6 +146,7 @@ SymbolSlab::Builder Symbols; RefSlab::Builder Refs; RelationSlab::Builder Relations; + std::string IndexRoot; }; } // namespace @@ -119,7 +181,9 @@ // Collect symbols found in each translation unit, merging as we go. clang::clangd::IndexFileIn Data; auto Err = Executor->get()->execute( - std::make_unique(Data), + std::make_unique( + Data, llvm::sys::path::convert_to_slash( + clang::clangd::ProjectRoot, llvm::sys::path::Style::posix)), clang::tooling::getStripPluginsAdjuster()); if (Err) { llvm::errs() << llvm::toString(std::move(Err)) << "\n";