[clang-tools-extra] r269029 - [include-fixer] Work around partial names in both directions.

Benjamin Kramer via cfe-commits cfe-commits at lists.llvm.org
Tue May 10 01:25:31 PDT 2016


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"));




More information about the cfe-commits mailing list