r355008 - Support framework import/include auto-completion

David Goldman via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 27 09:40:34 PST 2019


Author: dgoldman
Date: Wed Feb 27 09:40:33 2019
New Revision: 355008

URL: http://llvm.org/viewvc/llvm-project?rev=355008&view=rev
Log:
Support framework import/include auto-completion

Frameworks filesystem representations:
  UIKit.framework/Headers/%header%

Framework import format:
  #import <UIKit/%header%>

Thus the completion code must map the input format of <UIKit/> to
the path of UIKit.framework/Headers as well as strip the
".framework" suffix when auto-completing the framework name.

Added:
    cfe/trunk/test/CodeCompletion/included-frameworks.m
Modified:
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=355008&r1=355007&r2=355008&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Wed Feb 27 09:40:33 2019
@@ -8404,10 +8404,23 @@ void Sema::CodeCompleteIncludedFile(llvm
   };
 
   // Helper: scans IncludeDir for nice files, and adds results for each.
-  auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) {
+  auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,
+                                    bool IsSystem,
+                                    DirectoryLookup::LookupType_t LookupType) {
     llvm::SmallString<128> Dir = IncludeDir;
-    if (!NativeRelDir.empty())
-      llvm::sys::path::append(Dir, NativeRelDir);
+    if (!NativeRelDir.empty()) {
+      if (LookupType == DirectoryLookup::LT_Framework) {
+        // For a framework dir, #include <Foo/Bar/> actually maps to
+        // a path of Foo.framework/Headers/Bar/.
+        auto Begin = llvm::sys::path::begin(NativeRelDir);
+        auto End = llvm::sys::path::end(NativeRelDir);
+
+        llvm::sys::path::append(Dir, *Begin + ".framework", "Headers");
+        llvm::sys::path::append(Dir, ++Begin, End);
+      } else {
+        llvm::sys::path::append(Dir, NativeRelDir);
+      }
+    }
 
     std::error_code EC;
     unsigned Count = 0;
@@ -8418,6 +8431,12 @@ void Sema::CodeCompleteIncludedFile(llvm
       StringRef Filename = llvm::sys::path::filename(It->path());
       switch (It->type()) {
       case llvm::sys::fs::file_type::directory_file:
+        // All entries in a framework directory must have a ".framework" suffix,
+        // but the suffix does not appear in the source code's include/import.
+        if (LookupType == DirectoryLookup::LT_Framework &&
+            NativeRelDir.empty() && !Filename.consume_back(".framework"))
+          break;
+
         AddCompletion(Filename, /*IsDirectory=*/true);
         break;
       case llvm::sys::fs::file_type::regular_file:
@@ -8446,10 +8465,12 @@ void Sema::CodeCompleteIncludedFile(llvm
       // header maps are not (currently) enumerable.
       break;
     case DirectoryLookup::LT_NormalDir:
-      AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem);
+      AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem,
+                             DirectoryLookup::LT_NormalDir);
       break;
     case DirectoryLookup::LT_Framework:
-      AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem);
+      AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem,
+                             DirectoryLookup::LT_Framework);
       break;
     }
   };
@@ -8463,7 +8484,8 @@ void Sema::CodeCompleteIncludedFile(llvm
     // The current directory is on the include path for "quoted" includes.
     auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
     if (CurFile && CurFile->getDir())
-      AddFilesFromIncludeDir(CurFile->getDir()->getName(), false);
+      AddFilesFromIncludeDir(CurFile->getDir()->getName(), false,
+                             DirectoryLookup::LT_NormalDir);
     for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
       AddFilesFromDirLookup(D, false);
   }

Added: cfe/trunk/test/CodeCompletion/included-frameworks.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/included-frameworks.m?rev=355008&view=auto
==============================================================================
--- cfe/trunk/test/CodeCompletion/included-frameworks.m (added)
+++ cfe/trunk/test/CodeCompletion/included-frameworks.m Wed Feb 27 09:40:33 2019
@@ -0,0 +1,29 @@
+// RUN: rm -rf %t && mkdir -p %t/Foo.framework/Headers/SubFolder && mkdir %t/NotAFramework/
+// RUN: touch %t/Foo.framework/Headers/Foo.h && touch %t/Foo.framework/Headers/FOOClass.h
+// RUN: touch %t/Foo.framework/Headers/SubFolder/FOOInternal.h
+
+#import <Foo/Foo.h>
+
+#import <Foo/SubFolder/FOOInternal.h>
+
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+// Autocomplete frameworks without the ".framework" extension.
+//
+// RUN: %clang -fsyntax-only -F %t -Xclang -code-completion-at=%s:5:10 %s -o - | FileCheck -check-prefix=CHECK-1 %s
+// CHECK-1-NOT: Foo.framework/
+// CHECK-1-NOT: NotAFramework/
+// CHECK-1: Foo/
+
+// Autocomplete for frameworks inside its Headers folder.
+//
+// RUN: %clang -fsyntax-only -F %t -Xclang -code-completion-at=%s:5:14 %s -o - | FileCheck -check-prefix=CHECK-2 %s
+// CHECK-2: Foo.h>
+// CHECK-2: FOOClass.h>
+// CHECK-2: SubFolder/
+
+// Autocomplete for folders inside of a frameworks.
+//
+// RUN: %clang -fsyntax-only -F %t -Xclang -code-completion-at=%s:7:24 %s -o - | FileCheck -check-prefix=CHECK-3 %s
+// CHECK-3: FOOInternal.h>




More information about the cfe-commits mailing list