diff options
4 files changed, 63 insertions, 3 deletions
diff --git a/clang-tools-extra/include-fixer/SymbolIndexManager.cpp b/clang-tools-extra/include-fixer/SymbolIndexManager.cpp index 2a0547a473a..1800fab4199 100644 --- a/clang-tools-extra/include-fixer/SymbolIndexManager.cpp +++ b/clang-tools-extra/include-fixer/SymbolIndexManager.cpp @@ -17,6 +17,37 @@ namespace clang { namespace include_fixer { +using clang::find_all_symbols::SymbolInfo; + +/// Sorts and uniques SymbolInfos based on the popularity info in SymbolInfo. +static void rankByPopularity(std::vector<SymbolInfo> &Symbols) { + // First collect occurrences per header file. + std::map<llvm::StringRef, unsigned> HeaderPopularity; + for (const SymbolInfo &Symbol : Symbols) { + unsigned &Popularity = HeaderPopularity[Symbol.getFilePath()]; + Popularity = std::max(Popularity, Symbol.getNumOccurrences()); + } + + // Sort by the gathered popularities. Use file name as a tie breaker so we can + // deduplicate. + std::sort(Symbols.begin(), Symbols.end(), + [&](const SymbolInfo &A, const SymbolInfo &B) { + auto APop = HeaderPopularity[A.getFilePath()]; + auto BPop = HeaderPopularity[B.getFilePath()]; + if (APop != BPop) + return APop > BPop; + return A.getFilePath() < B.getFilePath(); + }); + + // Deduplicate based on the file name. They will have the same popularity and + // we don't want to suggest the same header twice. + Symbols.erase(std::unique(Symbols.begin(), Symbols.end(), + [](const SymbolInfo &A, const SymbolInfo &B) { + return A.getFilePath() == B.getFilePath(); + }), + Symbols.end()); +} + std::vector<std::string> SymbolIndexManager::search(llvm::StringRef Identifier) const { // The identifier may be fully qualified, so split it and get all the context @@ -45,6 +76,8 @@ SymbolIndexManager::search(llvm::StringRef Identifier) const { DEBUG(llvm::dbgs() << "Searching " << Names.back() << "... got " << Symbols.size() << " results...\n"); + rankByPopularity(Symbols); + for (const auto &Symbol : Symbols) { // Match the identifier name without qualifier. if (Symbol.getName() == Names.back()) { diff --git a/clang-tools-extra/include-fixer/tool/ClangIncludeFixer.cpp b/clang-tools-extra/include-fixer/tool/ClangIncludeFixer.cpp index 7b5c9f9359c..6e385fe617f 100644 --- a/clang-tools-extra/include-fixer/tool/ClangIncludeFixer.cpp +++ b/clang-tools-extra/include-fixer/tool/ClangIncludeFixer.cpp @@ -98,11 +98,11 @@ createSymbolIndexManager(StringRef FilePath) { std::vector<std::string> Headers; SmallVector<StringRef, 4> CommaSplits; Split.second.split(CommaSplits, ","); - for (StringRef Header : CommaSplits) + for (size_t I = 0, E = CommaSplits.size(); I != E; ++I) Symbols.push_back(find_all_symbols::SymbolInfo( Split.first.trim(), - find_all_symbols::SymbolInfo::SymbolKind::Unknown, Header.trim(), 1, - {})); + find_all_symbols::SymbolInfo::SymbolKind::Unknown, + CommaSplits[I].trim(), 1, {}, /*NumOccurrences=*/E - I)); } SymbolIndexMgr->addSymbolIndex( llvm::make_unique<include_fixer::InMemorySymbolIndex>(Symbols)); diff --git a/clang-tools-extra/test/include-fixer/Inputs/fake_yaml_db.yaml b/clang-tools-extra/test/include-fixer/Inputs/fake_yaml_db.yaml index 7e60fc2e9ae..4d9c219150a 100644 --- a/clang-tools-extra/test/include-fixer/Inputs/fake_yaml_db.yaml +++ b/clang-tools-extra/test/include-fixer/Inputs/fake_yaml_db.yaml @@ -22,3 +22,24 @@ LineNumber: 1 Type: Class NumOccurrences: 1 ... +Name: bar +Contexts: + - ContextType: Namespace + ContextName: a + - ContextType: Namespace + ContextName: b +FilePath: ../include/bar.h +LineNumber: 2 +Type: Class +NumOccurrences: 3 +... +Name: bar +Contexts: + - ContextType: Namespace + ContextName: a + - ContextType: Namespace + ContextName: b +FilePath: ../include/zbar.h +LineNumber: 1 +Type: Class +NumOccurrences: 3 diff --git a/clang-tools-extra/test/include-fixer/ranking.cpp b/clang-tools-extra/test/include-fixer/ranking.cpp new file mode 100644 index 00000000000..13cd7890282 --- /dev/null +++ b/clang-tools-extra/test/include-fixer/ranking.cpp @@ -0,0 +1,6 @@ +// RUN: clang-include-fixer -db=yaml -input=%S/Inputs/fake_yaml_db.yaml -output-headers %s -- | FileCheck %s -implicit-check-not=.h + +// CHECK: "../include/bar.h" +// CHECK-NEXT: "../include/zbar.h" + +bar b; |

