diff options
| author | Benjamin Kramer <benny.kra@googlemail.com> | 2016-05-10 08:25:31 +0000 |
|---|---|---|
| committer | Benjamin Kramer <benny.kra@googlemail.com> | 2016-05-10 08:25:31 +0000 |
| commit | ad93500c52b6407dc854b7a19ad00da86b98d575 (patch) | |
| tree | 2a6aa3019a42e0d0afc4699c6ba692ea73bbb7a6 | |
| parent | c3459a50022a64e695560fbb43b3248c55ad29ac (diff) | |
| download | bcm5719-llvm-ad93500c52b6407dc854b7a19ad00da86b98d575.tar.gz bcm5719-llvm-ad93500c52b6407dc854b7a19ad00da86b98d575.zip | |
[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.
llvm-svn: 269029
| -rw-r--r-- | clang-tools-extra/include-fixer/IncludeFixer.cpp | 31 | ||||
| -rw-r--r-- | clang-tools-extra/unittests/include-fixer/IncludeFixerTest.cpp | 6 |
2 files changed, 29 insertions, 8 deletions
diff --git a/clang-tools-extra/include-fixer/IncludeFixer.cpp b/clang-tools-extra/include-fixer/IncludeFixer.cpp index 44fb7c096cf..f86a071eec9 100644 --- a/clang-tools-extra/include-fixer/IncludeFixer.cpp +++ b/clang-tools-extra/include-fixer/IncludeFixer.cpp @@ -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(); } diff --git a/clang-tools-extra/unittests/include-fixer/IncludeFixerTest.cpp b/clang-tools-extra/unittests/include-fixer/IncludeFixerTest.cpp index 09ee01211da..44be4c6fdd9 100644 --- a/clang-tools-extra/unittests/include-fixer/IncludeFixerTest.cpp +++ b/clang-tools-extra/unittests/include-fixer/IncludeFixerTest.cpp @@ -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")); |

