Index: clang-tools-extra/trunk/include-fixer/SymbolIndexManager.cpp =================================================================== --- clang-tools-extra/trunk/include-fixer/SymbolIndexManager.cpp +++ clang-tools-extra/trunk/include-fixer/SymbolIndexManager.cpp @@ -24,53 +24,61 @@ llvm::SmallVector Names; Identifier.split(Names, "::"); - std::vector Symbols; - for (const auto &DB : SymbolIndices) { - auto Res = DB->search(Names.back().str()); - Symbols.insert(Symbols.end(), Res.begin(), Res.end()); - } + // As long as we don't find a result keep stripping name parts from the end. + // This is to support nested classes which aren't recorded in the database. + // Eventually we will either hit a class (namespaces aren't in the database + // either) and can report that result. + std::vector Results; + while (Results.empty() && !Names.empty()) { + std::vector Symbols; + for (const auto &DB : SymbolIndices) { + auto Res = DB->search(Names.back().str()); + Symbols.insert(Symbols.end(), Res.begin(), Res.end()); + } - DEBUG(llvm::dbgs() << "Searching " << Names.back() << "... got " - << Symbols.size() << " results...\n"); + DEBUG(llvm::dbgs() << "Searching " << Names.back() << "... got " + << Symbols.size() << " results...\n"); - std::vector Results; - for (const auto &Symbol : Symbols) { - // Match the identifier name without qualifier. - if (Symbol.getName() == Names.back()) { - bool IsMatched = true; - auto SymbolContext = Symbol.getContexts().begin(); - auto IdentiferContext = Names.rbegin() + 1; // Skip identifier name; - // Match the remaining context names. - while (IdentiferContext != Names.rend() && - SymbolContext != Symbol.getContexts().end()) { - if (SymbolContext->second == *IdentiferContext) { - ++IdentiferContext; - ++SymbolContext; - } else if (SymbolContext->first == - find_all_symbols::SymbolInfo::ContextType::EnumDecl) { - // Skip non-scoped enum context. - ++SymbolContext; - } else { - IsMatched = false; - break; + for (const auto &Symbol : Symbols) { + // Match the identifier name without qualifier. + if (Symbol.getName() == Names.back()) { + bool IsMatched = true; + auto SymbolContext = Symbol.getContexts().begin(); + auto IdentiferContext = Names.rbegin() + 1; // Skip identifier name. + // Match the remaining context names. + while (IdentiferContext != Names.rend() && + SymbolContext != Symbol.getContexts().end()) { + if (SymbolContext->second == *IdentiferContext) { + ++IdentiferContext; + ++SymbolContext; + } else if (SymbolContext->first == + find_all_symbols::SymbolInfo::ContextType::EnumDecl) { + // Skip non-scoped enum context. + ++SymbolContext; + } else { + IsMatched = false; + break; + } } - } - // FIXME: Support full match. At this point, we only find symbols in - // database which end with the same contexts with the identifier. - if (IsMatched && IdentiferContext == Names.rend()) { - // FIXME: file path should never be in the form of <...> or "...", but - // the unit test with fixed database use <...> file path, which might - // need to be changed. - // FIXME: if the file path is a system header name, we want to use angle - // brackets. - std::string FilePath = Symbol.getFilePath().str(); - Results.push_back((FilePath[0] == '"' || FilePath[0] == '<') - ? FilePath - : "\"" + FilePath + "\""); + // FIXME: Support full match. At this point, we only find symbols in + // database which end with the same contexts with the identifier. + if (IsMatched && IdentiferContext == Names.rend()) { + // FIXME: file path should never be in the form of <...> or "...", but + // the unit test with fixed database use <...> file path, which might + // need to be changed. + // FIXME: if the file path is a system header name, we want to use + // angle brackets. + std::string FilePath = Symbol.getFilePath().str(); + Results.push_back((FilePath[0] == '"' || FilePath[0] == '<') + ? FilePath + : "\"" + FilePath + "\""); + } } } + Names.pop_back(); } + return Results; } Index: clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp =================================================================== --- clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp +++ clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp @@ -55,9 +55,6 @@ {{SymbolInfo::ContextType::Namespace, "std"}}), SymbolInfo("sting", SymbolInfo::SymbolKind::Class, "\"sting\"", 1, {{SymbolInfo::ContextType::Namespace, "std"}}), - SymbolInfo("size_type", SymbolInfo::SymbolKind::Variable, "", 1, - {{SymbolInfo::ContextType::Namespace, "string"}, - {SymbolInfo::ContextType::Namespace, "std"}}), SymbolInfo("foo", SymbolInfo::SymbolKind::Class, "\"dir/otherdir/qux.h\"", 1, {{SymbolInfo::ContextType::Namespace, "b"}, {SymbolInfo::ContextType::Namespace, "a"}}),