Author: d0k Date: Tue May 10 03:25:31 2016 New Revision: 269029 URL: http://llvm.org/viewvc/llvm-project?rev=269029&view=rev Log: [include-fixer] Work around partial names in both directions.
We already handled the case where we had a nested name specifier where parts from the beginning don't get a callback, also handle the case where the end doesn't get a callback. This happens with function calls in unknown namespaces. The way we do this for now based on character data is a bit of a hack, we may need to refine this later or fix clang to produce different callbacks. Modified: clang-tools-extra/trunk/include-fixer/IncludeFixer.cpp clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp Modified: clang-tools-extra/trunk/include-fixer/IncludeFixer.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/include-fixer/IncludeFixer.cpp?rev=269029&r1=269028&r2=269029&view=diff ============================================================================== --- clang-tools-extra/trunk/include-fixer/IncludeFixer.cpp (original) +++ clang-tools-extra/trunk/include-fixer/IncludeFixer.cpp Tue May 10 03:25:31 2016 @@ -109,21 +109,36 @@ public: DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT) override { - // We don't want to look up inner parts of nested name specifies. Looking up - // the header where a namespace is defined in is rarely useful. - if (LookupKind == clang::Sema::LookupNestedNameSpecifierName) { - DEBUG(llvm::dbgs() << "ignoring " << Typo.getAsString() << "\n"); - return clang::TypoCorrection(); - } - /// If we have a scope specification, use that to get more precise results. std::string QueryString; if (SS && SS->getRange().isValid()) { auto Range = CharSourceRange::getTokenRange(SS->getRange().getBegin(), Typo.getLoc()); - QueryString = + StringRef Source = Lexer::getSourceText(Range, getCompilerInstance().getSourceManager(), getCompilerInstance().getLangOpts()); + + // Skip forward until we find a character that's neither identifier nor + // colon. This is a bit of a hack around the fact that we will only get a + // single callback for a long nested name if a part of the beginning is + // unknown. For example: + // + // llvm::sys::path::parent_path(...) + // ^~~~ ^~~ + // known + // ^~~~ + // unknown, last callback + // ^~~~~~~~~~~ + // no callback + // + // With the extension we get the full nested name specifier including + // parent_path. + // FIXME: Don't rely on source text. + const char *End = Source.end(); + while (isIdentifierBody(*End) || *End == ':') + ++End; + + QueryString = std::string(Source.begin(), End); } else { QueryString = Typo.getAsString(); } Modified: clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp?rev=269029&r1=269028&r2=269029&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp (original) +++ clang-tools-extra/trunk/unittests/include-fixer/IncludeFixerTest.cpp Tue May 10 03:25:31 2016 @@ -115,6 +115,12 @@ TEST(IncludeFixer, MinimizeInclude) { runIncludeFixer("a::b::foo bar;\n", IncludePath)); } +TEST(IncludeFixer, NestedName) { + EXPECT_EQ("#include \"dir/otherdir/qux.h\"\n" + "namespace a {}\nint a = a::b::foo(0);\n", + runIncludeFixer("namespace a {}\nint a = a::b::foo(0);\n")); +} + TEST(IncludeFixer, MultipleMissingSymbols) { EXPECT_EQ("#include <string>\nstd::string bar;\nstd::sting foo;\n", runIncludeFixer("std::string bar;\nstd::sting foo;\n")); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits