[PATCH] D156704: [clang][HeaderSearch] Treat framework headers as System for suggestPath

2023-08-09 Thread David Goldman via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG9fe632ba18f1: [clang][HeaderSearch] Treat framework headers 
as Angled for suggestPath (authored by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156704/new/

https://reviews.llvm.org/D156704

Files:
  clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
  clang-tools-extra/include-cleaner/lib/HTMLReport.cpp
  clang-tools-extra/include-cleaner/lib/IncludeSpeller.cpp
  clang/include/clang/Lex/HeaderSearch.h
  clang/lib/Lex/HeaderSearch.cpp
  clang/lib/Sema/SemaLookup.cpp
  clang/unittests/Lex/HeaderSearchTest.cpp

Index: clang/unittests/Lex/HeaderSearchTest.cpp
===
--- clang/unittests/Lex/HeaderSearchTest.cpp
+++ clang/unittests/Lex/HeaderSearchTest.cpp
@@ -47,14 +47,18 @@
 Search.AddSearchPath(DL, /*isAngled=*/false);
   }
 
-  void addSystemFrameworkSearchDir(llvm::StringRef Dir) {
+  void addFrameworkSearchDir(llvm::StringRef Dir, bool IsSystem = true) {
 VFS->addFile(
 Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/std::nullopt,
 /*Group=*/std::nullopt, llvm::sys::fs::file_type::directory_file);
 auto DE = FileMgr.getOptionalDirectoryRef(Dir);
 assert(DE);
-auto DL = DirectoryLookup(*DE, SrcMgr::C_System, /*isFramework=*/true);
-Search.AddSystemSearchPath(DL);
+auto DL = DirectoryLookup(*DE, IsSystem ? SrcMgr::C_System : SrcMgr::C_User,
+  /*isFramework=*/true);
+if (IsSystem)
+  Search.AddSystemSearchPath(DL);
+else
+  Search.AddSearchPath(DL, /*isAngled=*/true);
   }
 
   void addHeaderMap(llvm::StringRef Filename,
@@ -175,20 +179,32 @@
 }
 
 TEST_F(HeaderSearchTest, SdkFramework) {
-  addSystemFrameworkSearchDir(
+  addFrameworkSearchDir(
   "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/Frameworks/");
-  bool IsSystem = false;
+  bool IsAngled = false;
   EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
 "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/"
 "Frameworks/AppKit.framework/Headers/NSView.h",
 /*WorkingDir=*/"",
-/*MainFile=*/"", ),
+/*MainFile=*/"", ),
 "AppKit/NSView.h");
-  EXPECT_TRUE(IsSystem);
+  EXPECT_TRUE(IsAngled);
+
+  addFrameworkSearchDir("/System/Developer/Library/Framworks/",
+/*IsSystem*/ false);
+  EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
+"/System/Developer/Library/Framworks/"
+"Foo.framework/Headers/Foo.h",
+/*WorkingDir=*/"",
+/*MainFile=*/"", ),
+"Foo/Foo.h");
+  // Expect to be true even though we passed false to IsSystem earlier since
+  // all frameworks should be treated as <>.
+  EXPECT_TRUE(IsAngled);
 }
 
 TEST_F(HeaderSearchTest, NestedFramework) {
-  addSystemFrameworkSearchDir("/Platforms/MacOSX/Frameworks");
+  addFrameworkSearchDir("/Platforms/MacOSX/Frameworks");
   EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
 "/Platforms/MacOSX/Frameworks/AppKit.framework/Frameworks/"
 "Sub.framework/Headers/Sub.h",
@@ -199,7 +215,7 @@
 
 TEST_F(HeaderSearchTest, HeaderFrameworkLookup) {
   std::string HeaderPath = "/tmp/Frameworks/Foo.framework/Headers/Foo.h";
-  addSystemFrameworkSearchDir("/tmp/Frameworks");
+  addFrameworkSearchDir("/tmp/Frameworks");
   VFS->addFile(HeaderPath, 0,
llvm::MemoryBuffer::getMemBufferCopy("", HeaderPath),
/*User=*/std::nullopt, /*Group=*/std::nullopt,
Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -5701,10 +5701,10 @@
 /// suggesting the addition of a #include of the specified file.
 static std::string getHeaderNameForHeader(Preprocessor , const FileEntry *E,
   llvm::StringRef IncludingFile) {
-  bool IsSystem = false;
+  bool IsAngled = false;
   auto Path = PP.getHeaderSearchInfo().suggestPathToFileForDiagnostics(
-  E, IncludingFile, );
-  return (IsSystem ? '<' : '"') + Path + (IsSystem ? '>' : '"');
+  E, IncludingFile, );
+  return (IsAngled ? '<' : '"') + Path + (IsAngled ? '>' : '"');
 }
 
 void Sema::diagnoseMissingImport(SourceLocation UseLoc, const NamedDecl *Decl,
Index: clang/lib/Lex/HeaderSearch.cpp
===
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -1928,17 +1928,17 @@
 }
 
 std::string HeaderSearch::suggestPathToFileForDiagnostics(
-const FileEntry *File, llvm::StringRef MainFile, bool *IsSystem) const {
+

[PATCH] D156704: [clang][HeaderSearch] Treat framework headers as System for suggestPath

2023-08-03 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 547011.
dgoldman added a comment.

run clang-format again


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156704/new/

https://reviews.llvm.org/D156704

Files:
  clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
  clang-tools-extra/include-cleaner/lib/HTMLReport.cpp
  clang-tools-extra/include-cleaner/lib/IncludeSpeller.cpp
  clang/include/clang/Lex/HeaderSearch.h
  clang/lib/Lex/HeaderSearch.cpp
  clang/lib/Sema/SemaLookup.cpp
  clang/unittests/Lex/HeaderSearchTest.cpp

Index: clang/unittests/Lex/HeaderSearchTest.cpp
===
--- clang/unittests/Lex/HeaderSearchTest.cpp
+++ clang/unittests/Lex/HeaderSearchTest.cpp
@@ -47,14 +47,18 @@
 Search.AddSearchPath(DL, /*isAngled=*/false);
   }
 
-  void addSystemFrameworkSearchDir(llvm::StringRef Dir) {
+  void addFrameworkSearchDir(llvm::StringRef Dir, bool IsSystem = true) {
 VFS->addFile(
 Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/std::nullopt,
 /*Group=*/std::nullopt, llvm::sys::fs::file_type::directory_file);
 auto DE = FileMgr.getOptionalDirectoryRef(Dir);
 assert(DE);
-auto DL = DirectoryLookup(*DE, SrcMgr::C_System, /*isFramework=*/true);
-Search.AddSystemSearchPath(DL);
+auto DL = DirectoryLookup(*DE, IsSystem ? SrcMgr::C_System : SrcMgr::C_User,
+  /*isFramework=*/true);
+if (IsSystem)
+  Search.AddSystemSearchPath(DL);
+else
+  Search.AddSearchPath(DL, /*isAngled=*/true);
   }
 
   void addHeaderMap(llvm::StringRef Filename,
@@ -175,20 +179,32 @@
 }
 
 TEST_F(HeaderSearchTest, SdkFramework) {
-  addSystemFrameworkSearchDir(
+  addFrameworkSearchDir(
   "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/Frameworks/");
-  bool IsSystem = false;
+  bool IsAngled = false;
   EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
 "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/"
 "Frameworks/AppKit.framework/Headers/NSView.h",
 /*WorkingDir=*/"",
-/*MainFile=*/"", ),
+/*MainFile=*/"", ),
 "AppKit/NSView.h");
-  EXPECT_TRUE(IsSystem);
+  EXPECT_TRUE(IsAngled);
+
+  addFrameworkSearchDir("/System/Developer/Library/Framworks/",
+/*IsSystem*/ false);
+  EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
+"/System/Developer/Library/Framworks/"
+"Foo.framework/Headers/Foo.h",
+/*WorkingDir=*/"",
+/*MainFile=*/"", ),
+"Foo/Foo.h");
+  // Expect to be true even though we passed false to IsSystem earlier since
+  // all frameworks should be treated as <>.
+  EXPECT_TRUE(IsAngled);
 }
 
 TEST_F(HeaderSearchTest, NestedFramework) {
-  addSystemFrameworkSearchDir("/Platforms/MacOSX/Frameworks");
+  addFrameworkSearchDir("/Platforms/MacOSX/Frameworks");
   EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
 "/Platforms/MacOSX/Frameworks/AppKit.framework/Frameworks/"
 "Sub.framework/Headers/Sub.h",
@@ -199,7 +215,7 @@
 
 TEST_F(HeaderSearchTest, HeaderFrameworkLookup) {
   std::string HeaderPath = "/tmp/Frameworks/Foo.framework/Headers/Foo.h";
-  addSystemFrameworkSearchDir("/tmp/Frameworks");
+  addFrameworkSearchDir("/tmp/Frameworks");
   VFS->addFile(HeaderPath, 0,
llvm::MemoryBuffer::getMemBufferCopy("", HeaderPath),
/*User=*/std::nullopt, /*Group=*/std::nullopt,
Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -5682,10 +5682,10 @@
 /// suggesting the addition of a #include of the specified file.
 static std::string getHeaderNameForHeader(Preprocessor , const FileEntry *E,
   llvm::StringRef IncludingFile) {
-  bool IsSystem = false;
+  bool IsAngled = false;
   auto Path = PP.getHeaderSearchInfo().suggestPathToFileForDiagnostics(
-  E, IncludingFile, );
-  return (IsSystem ? '<' : '"') + Path + (IsSystem ? '>' : '"');
+  E, IncludingFile, );
+  return (IsAngled ? '<' : '"') + Path + (IsAngled ? '>' : '"');
 }
 
 void Sema::diagnoseMissingImport(SourceLocation UseLoc, const NamedDecl *Decl,
Index: clang/lib/Lex/HeaderSearch.cpp
===
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -1928,17 +1928,17 @@
 }
 
 std::string HeaderSearch::suggestPathToFileForDiagnostics(
-const FileEntry *File, llvm::StringRef MainFile, bool *IsSystem) const {
+const FileEntry *File, llvm::StringRef MainFile, bool *IsAngled) const {
   // FIXME: We assume that the 

[PATCH] D156704: [clang][HeaderSearch] Treat framework headers as System for suggestPath

2023-08-03 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 546927.
dgoldman added a comment.

Rename IsSystem to IsAngled


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156704/new/

https://reviews.llvm.org/D156704

Files:
  clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
  clang-tools-extra/include-cleaner/lib/HTMLReport.cpp
  clang-tools-extra/include-cleaner/lib/IncludeSpeller.cpp
  clang/include/clang/Lex/HeaderSearch.h
  clang/lib/Lex/HeaderSearch.cpp
  clang/lib/Sema/SemaLookup.cpp
  clang/unittests/Lex/HeaderSearchTest.cpp

Index: clang/unittests/Lex/HeaderSearchTest.cpp
===
--- clang/unittests/Lex/HeaderSearchTest.cpp
+++ clang/unittests/Lex/HeaderSearchTest.cpp
@@ -47,14 +47,18 @@
 Search.AddSearchPath(DL, /*isAngled=*/false);
   }
 
-  void addSystemFrameworkSearchDir(llvm::StringRef Dir) {
+  void addFrameworkSearchDir(llvm::StringRef Dir, bool IsSystem = true) {
 VFS->addFile(
 Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/std::nullopt,
 /*Group=*/std::nullopt, llvm::sys::fs::file_type::directory_file);
 auto DE = FileMgr.getOptionalDirectoryRef(Dir);
 assert(DE);
-auto DL = DirectoryLookup(*DE, SrcMgr::C_System, /*isFramework=*/true);
-Search.AddSystemSearchPath(DL);
+auto DL = DirectoryLookup(*DE,
+IsSystem ? SrcMgr::C_System : SrcMgr::C_User, /*isFramework=*/true);
+if (IsSystem)
+  Search.AddSystemSearchPath(DL);
+else
+  Search.AddSearchPath(DL, /*isAngled=*/true);
   }
 
   void addHeaderMap(llvm::StringRef Filename,
@@ -175,20 +179,32 @@
 }
 
 TEST_F(HeaderSearchTest, SdkFramework) {
-  addSystemFrameworkSearchDir(
+  addFrameworkSearchDir(
   "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/Frameworks/");
-  bool IsSystem = false;
+  bool IsAngled = false;
   EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
 "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/"
 "Frameworks/AppKit.framework/Headers/NSView.h",
 /*WorkingDir=*/"",
-/*MainFile=*/"", ),
+/*MainFile=*/"", ),
 "AppKit/NSView.h");
-  EXPECT_TRUE(IsSystem);
+  EXPECT_TRUE(IsAngled);
+
+  addFrameworkSearchDir(
+  "/System/Developer/Library/Framworks/", /*IsSystem*/false);
+  EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
+"/System/Developer/Library/Framworks/"
+"Foo.framework/Headers/Foo.h",
+/*WorkingDir=*/"",
+/*MainFile=*/"", ),
+"Foo/Foo.h");
+  // Expect to be true even though we passed false to IsSystem earlier since
+  // all frameworks should be treated as <>.
+  EXPECT_TRUE(IsAngled);
 }
 
 TEST_F(HeaderSearchTest, NestedFramework) {
-  addSystemFrameworkSearchDir("/Platforms/MacOSX/Frameworks");
+  addFrameworkSearchDir("/Platforms/MacOSX/Frameworks");
   EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
 "/Platforms/MacOSX/Frameworks/AppKit.framework/Frameworks/"
 "Sub.framework/Headers/Sub.h",
@@ -199,7 +215,7 @@
 
 TEST_F(HeaderSearchTest, HeaderFrameworkLookup) {
   std::string HeaderPath = "/tmp/Frameworks/Foo.framework/Headers/Foo.h";
-  addSystemFrameworkSearchDir("/tmp/Frameworks");
+  addFrameworkSearchDir("/tmp/Frameworks");
   VFS->addFile(HeaderPath, 0,
llvm::MemoryBuffer::getMemBufferCopy("", HeaderPath),
/*User=*/std::nullopt, /*Group=*/std::nullopt,
Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -5682,10 +5682,10 @@
 /// suggesting the addition of a #include of the specified file.
 static std::string getHeaderNameForHeader(Preprocessor , const FileEntry *E,
   llvm::StringRef IncludingFile) {
-  bool IsSystem = false;
+  bool IsAngled = false;
   auto Path = PP.getHeaderSearchInfo().suggestPathToFileForDiagnostics(
-  E, IncludingFile, );
-  return (IsSystem ? '<' : '"') + Path + (IsSystem ? '>' : '"');
+  E, IncludingFile, );
+  return (IsAngled ? '<' : '"') + Path + (IsAngled ? '>' : '"');
 }
 
 void Sema::diagnoseMissingImport(SourceLocation UseLoc, const NamedDecl *Decl,
Index: clang/lib/Lex/HeaderSearch.cpp
===
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -1928,17 +1928,17 @@
 }
 
 std::string HeaderSearch::suggestPathToFileForDiagnostics(
-const FileEntry *File, llvm::StringRef MainFile, bool *IsSystem) const {
+const FileEntry *File, llvm::StringRef MainFile, bool *IsAngled) const {
   // FIXME: We assume that the path name currently cached in the 

[PATCH] D156704: [clang][HeaderSearch] Treat framework headers as System for suggestPath

2023-08-01 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 546017.
dgoldman added a comment.

run clang-format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156704/new/

https://reviews.llvm.org/D156704

Files:
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
  clang/lib/Lex/HeaderSearch.cpp
  clang/unittests/Lex/HeaderSearchTest.cpp

Index: clang/unittests/Lex/HeaderSearchTest.cpp
===
--- clang/unittests/Lex/HeaderSearchTest.cpp
+++ clang/unittests/Lex/HeaderSearchTest.cpp
@@ -47,14 +47,18 @@
 Search.AddSearchPath(DL, /*isAngled=*/false);
   }
 
-  void addSystemFrameworkSearchDir(llvm::StringRef Dir) {
+  void addFrameworkSearchDir(llvm::StringRef Dir, bool IsSystem = true) {
 VFS->addFile(
 Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/std::nullopt,
 /*Group=*/std::nullopt, llvm::sys::fs::file_type::directory_file);
 auto DE = FileMgr.getOptionalDirectoryRef(Dir);
 assert(DE);
-auto DL = DirectoryLookup(*DE, SrcMgr::C_System, /*isFramework=*/true);
-Search.AddSystemSearchPath(DL);
+auto DL = DirectoryLookup(*DE, IsSystem ? SrcMgr::C_System : SrcMgr::C_User,
+  /*isFramework=*/true);
+if (IsSystem)
+  Search.AddSystemSearchPath(DL);
+else
+  Search.AddSearchPath(DL, /*isAngled=*/true);
   }
 
   void addHeaderMap(llvm::StringRef Filename,
@@ -175,7 +179,7 @@
 }
 
 TEST_F(HeaderSearchTest, SdkFramework) {
-  addSystemFrameworkSearchDir(
+  addFrameworkSearchDir(
   "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/Frameworks/");
   bool IsSystem = false;
   EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
@@ -185,10 +189,22 @@
 /*MainFile=*/"", ),
 "AppKit/NSView.h");
   EXPECT_TRUE(IsSystem);
+
+  addFrameworkSearchDir("/System/Developer/Library/Framworks/",
+/*IsSystem*/ false);
+  EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
+"/System/Developer/Library/Framworks/"
+"Foo.framework/Headers/Foo.h",
+/*WorkingDir=*/"",
+/*MainFile=*/"", ),
+"Foo/Foo.h");
+  // Expect to be true even though we passed false to IsSystem earlier since
+  // all frameworks should be treated as <>.
+  EXPECT_TRUE(IsSystem);
 }
 
 TEST_F(HeaderSearchTest, NestedFramework) {
-  addSystemFrameworkSearchDir("/Platforms/MacOSX/Frameworks");
+  addFrameworkSearchDir("/Platforms/MacOSX/Frameworks");
   EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
 "/Platforms/MacOSX/Frameworks/AppKit.framework/Frameworks/"
 "Sub.framework/Headers/Sub.h",
@@ -199,7 +215,7 @@
 
 TEST_F(HeaderSearchTest, HeaderFrameworkLookup) {
   std::string HeaderPath = "/tmp/Frameworks/Foo.framework/Headers/Foo.h";
-  addSystemFrameworkSearchDir("/tmp/Frameworks");
+  addFrameworkSearchDir("/tmp/Frameworks");
   VFS->addFile(HeaderPath, 0,
llvm::MemoryBuffer::getMemBufferCopy("", HeaderPath),
/*User=*/std::nullopt, /*Group=*/std::nullopt,
Index: clang/lib/Lex/HeaderSearch.cpp
===
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -2003,8 +2003,10 @@
 } else if (DL.isFramework()) {
   StringRef Dir = DL.getFrameworkDirRef()->getName();
   if (CheckDir(Dir)) {
+// Framework includes by convention use <> so mark these as system
+// so the caller know to use <> instead of "" as well.
 if (IsSystem)
-  *IsSystem = BestPrefixLength && isSystem(DL.getDirCharacteristic());
+  *IsSystem = BestPrefixLength;
 BestPrefixIsFramework = true;
   }
 }
Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -702,9 +702,9 @@
   EXPECT_THAT(
   Symbols,
   UnorderedElementsAre(
-  AllOf(qName("NSObject"), includeHeader("\"Foundation/NSObject.h\"")),
+  AllOf(qName("NSObject"), includeHeader("")),
   AllOf(qName("PrivateClass"),
-includeHeader("\"Foundation/NSObject+Private.h\"")),
+includeHeader("")),
   AllOf(qName("Container";
 
   // After adding the umbrella headers, we should use that spelling instead.
@@ -722,13 +722,13 @@
"Foundation_Private.h"),
   0, llvm::MemoryBuffer::getMemBuffer(PrivateUmbrellaHeader));
   runSymbolCollector(Header, Main, {"-F", FrameworksPath, "-xobjective-c++"});
-  EXPECT_THAT(Symbols,
-  UnorderedElementsAre(
-  AllOf(qName("NSObject"),
-includeHeader("\"Foundation/Foundation.h\"")),
-

[PATCH] D156704: [clang][HeaderSearch] Treat framework headers as System for suggestPath

2023-07-31 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
Herald added projects: clang, clang-tools-extra.

All callers will use the IsSystem flag to decide whether to use <> or ""
style includes, so we treat all frameworks as System since by convention
they use <> style includes.

Also update clangd's custom logic for frameworks accordingly.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156704

Files:
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
  clang/lib/Lex/HeaderSearch.cpp
  clang/unittests/Lex/HeaderSearchTest.cpp

Index: clang/unittests/Lex/HeaderSearchTest.cpp
===
--- clang/unittests/Lex/HeaderSearchTest.cpp
+++ clang/unittests/Lex/HeaderSearchTest.cpp
@@ -47,14 +47,18 @@
 Search.AddSearchPath(DL, /*isAngled=*/false);
   }
 
-  void addSystemFrameworkSearchDir(llvm::StringRef Dir) {
+  void addFrameworkSearchDir(llvm::StringRef Dir, bool IsSystem = true) {
 VFS->addFile(
 Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/std::nullopt,
 /*Group=*/std::nullopt, llvm::sys::fs::file_type::directory_file);
 auto DE = FileMgr.getOptionalDirectoryRef(Dir);
 assert(DE);
-auto DL = DirectoryLookup(*DE, SrcMgr::C_System, /*isFramework=*/true);
-Search.AddSystemSearchPath(DL);
+auto DL = DirectoryLookup(*DE,
+IsSystem ? SrcMgr::C_System : SrcMgr::C_User, /*isFramework=*/true);
+if (IsSystem)
+  Search.AddSystemSearchPath(DL);
+else
+  Search.AddSearchPath(DL, /*isAngled=*/true);
   }
 
   void addHeaderMap(llvm::StringRef Filename,
@@ -175,7 +179,7 @@
 }
 
 TEST_F(HeaderSearchTest, SdkFramework) {
-  addSystemFrameworkSearchDir(
+  addFrameworkSearchDir(
   "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/Frameworks/");
   bool IsSystem = false;
   EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
@@ -185,10 +189,22 @@
 /*MainFile=*/"", ),
 "AppKit/NSView.h");
   EXPECT_TRUE(IsSystem);
+
+  addFrameworkSearchDir(
+  "/System/Developer/Library/Framworks/", /*IsSystem*/false);
+  EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
+"/System/Developer/Library/Framworks/"
+"Foo.framework/Headers/Foo.h",
+/*WorkingDir=*/"",
+/*MainFile=*/"", ),
+"Foo/Foo.h");
+  // Expect to be true even though we passed false to IsSystem earlier since
+  // all frameworks should be treated as <>.
+  EXPECT_TRUE(IsSystem);
 }
 
 TEST_F(HeaderSearchTest, NestedFramework) {
-  addSystemFrameworkSearchDir("/Platforms/MacOSX/Frameworks");
+  addFrameworkSearchDir("/Platforms/MacOSX/Frameworks");
   EXPECT_EQ(Search.suggestPathToFileForDiagnostics(
 "/Platforms/MacOSX/Frameworks/AppKit.framework/Frameworks/"
 "Sub.framework/Headers/Sub.h",
@@ -199,7 +215,7 @@
 
 TEST_F(HeaderSearchTest, HeaderFrameworkLookup) {
   std::string HeaderPath = "/tmp/Frameworks/Foo.framework/Headers/Foo.h";
-  addSystemFrameworkSearchDir("/tmp/Frameworks");
+  addFrameworkSearchDir("/tmp/Frameworks");
   VFS->addFile(HeaderPath, 0,
llvm::MemoryBuffer::getMemBufferCopy("", HeaderPath),
/*User=*/std::nullopt, /*Group=*/std::nullopt,
Index: clang/lib/Lex/HeaderSearch.cpp
===
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -2003,8 +2003,10 @@
 } else if (DL.isFramework()) {
   StringRef Dir = DL.getFrameworkDirRef()->getName();
   if (CheckDir(Dir)) {
+// Framework includes by convention use <> so mark these as system
+// so the caller know to use <> instead of "" as well.
 if (IsSystem)
-  *IsSystem = BestPrefixLength && isSystem(DL.getDirCharacteristic());
+  *IsSystem = BestPrefixLength;
 BestPrefixIsFramework = true;
   }
 }
Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -702,9 +702,9 @@
   EXPECT_THAT(
   Symbols,
   UnorderedElementsAre(
-  AllOf(qName("NSObject"), includeHeader("\"Foundation/NSObject.h\"")),
+  AllOf(qName("NSObject"), includeHeader("")),
   AllOf(qName("PrivateClass"),
-includeHeader("\"Foundation/NSObject+Private.h\"")),
+includeHeader("")),
   AllOf(qName("Container";
 
   // After adding the umbrella headers, we should use that spelling instead.
@@ -725,9 +725,9 @@
   EXPECT_THAT(Symbols,
   

[PATCH] D150978: [clang][Sema] Add CodeCompletionContext::CCC_ObjCClassForwardDecl

2023-06-27 Thread David Goldman via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa42ce094d903: [clang][Sema] Add 
CodeCompletionContext::CCC_ObjCClassForwardDecl (authored by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D150978/new/

https://reviews.llvm.org/D150978

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang/include/clang/Sema/CodeCompleteConsumer.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Frontend/ASTUnit.cpp
  clang/lib/Parse/ParseObjc.cpp
  clang/lib/Sema/CodeCompleteConsumer.cpp
  clang/lib/Sema/SemaCodeComplete.cpp
  clang/tools/libclang/CIndexCodeCompletion.cpp

Index: clang/tools/libclang/CIndexCodeCompletion.cpp
===
--- clang/tools/libclang/CIndexCodeCompletion.cpp
+++ clang/tools/libclang/CIndexCodeCompletion.cpp
@@ -537,6 +537,7 @@
 case CodeCompletionContext::CCC_Other:
 case CodeCompletionContext::CCC_ObjCInterface:
 case CodeCompletionContext::CCC_ObjCImplementation:
+case CodeCompletionContext::CCC_ObjCClassForwardDecl:
 case CodeCompletionContext::CCC_NewName:
 case CodeCompletionContext::CCC_MacroName:
 case CodeCompletionContext::CCC_PreprocessorExpression:
Index: clang/lib/Sema/SemaCodeComplete.cpp
===
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -8460,6 +8460,24 @@
 Results.data(), Results.size());
 }
 
+void Sema::CodeCompleteObjCClassForwardDecl(Scope *S) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+CodeCompleter->getCodeCompletionTUInfo(),
+CodeCompletionContext::CCC_ObjCClassForwardDecl);
+  Results.EnterNewScope();
+
+  if (CodeCompleter->includeGlobals()) {
+// Add all classes.
+AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+false, Results);
+  }
+
+  Results.ExitScope();
+
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+Results.data(), Results.size());
+}
+
 void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
   SourceLocation ClassNameLoc) {
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Index: clang/lib/Sema/CodeCompleteConsumer.cpp
===
--- clang/lib/Sema/CodeCompleteConsumer.cpp
+++ clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -83,6 +83,7 @@
   case CCC_ObjCCategoryName:
   case CCC_IncludedFile:
   case CCC_Attribute:
+  case CCC_ObjCClassForwardDecl:
 return false;
   }
 
@@ -166,6 +167,8 @@
 return "Attribute";
   case CCKind::CCC_Recovery:
 return "Recovery";
+  case CCKind::CCC_ObjCClassForwardDecl:
+return "ObjCClassForwardDecl";
   }
   llvm_unreachable("Invalid CodeCompletionContext::Kind!");
 }
Index: clang/lib/Parse/ParseObjc.cpp
===
--- clang/lib/Parse/ParseObjc.cpp
+++ clang/lib/Parse/ParseObjc.cpp
@@ -153,6 +153,11 @@
 
   while (true) {
 MaybeSkipAttributes(tok::objc_class);
+if (Tok.is(tok::code_completion)) {
+  cutOffParsing();
+  Actions.CodeCompleteObjCClassForwardDecl(getCurScope());
+  return Actions.ConvertDeclToDeclGroup(nullptr);
+}
 if (expectIdentifier()) {
   SkipUntil(tok::semi);
   return Actions.ConvertDeclToDeclGroup(nullptr);
Index: clang/lib/Frontend/ASTUnit.cpp
===
--- clang/lib/Frontend/ASTUnit.cpp
+++ clang/lib/Frontend/ASTUnit.cpp
@@ -322,6 +322,7 @@
   if (ID->getDefinition())
 Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
   Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
+  Contexts |= (1LL << CodeCompletionContext::CCC_ObjCClassForwardDecl);
 }
 
 // Deal with tag names.
@@ -2028,6 +2029,7 @@
   case CodeCompletionContext::CCC_IncludedFile:
   case CodeCompletionContext::CCC_Attribute:
   case CodeCompletionContext::CCC_NewName:
+  case CodeCompletionContext::CCC_ObjCClassForwardDecl:
 // We're looking for nothing, or we're looking for names that cannot
 // be hidden.
 return;
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -13429,6 +13429,7 @@
  ArrayRef Protocols);
   void CodeCompleteObjCProtocolDecl(Scope *S);
   void CodeCompleteObjCInterfaceDecl(Scope *S);
+  void CodeCompleteObjCClassForwardDecl(Scope *S);
   void CodeCompleteObjCSuperclass(Scope *S,
  

[PATCH] D150978: [clang][Sema] Add CodeCompletionContext::CCC_ObjCClassForwardDecl

2023-06-26 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 534714.
dgoldman added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D150978/new/

https://reviews.llvm.org/D150978

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang/include/clang/Sema/CodeCompleteConsumer.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Frontend/ASTUnit.cpp
  clang/lib/Parse/ParseObjc.cpp
  clang/lib/Sema/CodeCompleteConsumer.cpp
  clang/lib/Sema/SemaCodeComplete.cpp
  clang/tools/libclang/CIndexCodeCompletion.cpp

Index: clang/tools/libclang/CIndexCodeCompletion.cpp
===
--- clang/tools/libclang/CIndexCodeCompletion.cpp
+++ clang/tools/libclang/CIndexCodeCompletion.cpp
@@ -537,6 +537,7 @@
 case CodeCompletionContext::CCC_Other:
 case CodeCompletionContext::CCC_ObjCInterface:
 case CodeCompletionContext::CCC_ObjCImplementation:
+case CodeCompletionContext::CCC_ObjCClassForwardDecl:
 case CodeCompletionContext::CCC_NewName:
 case CodeCompletionContext::CCC_MacroName:
 case CodeCompletionContext::CCC_PreprocessorExpression:
Index: clang/lib/Sema/SemaCodeComplete.cpp
===
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -8460,6 +8460,24 @@
 Results.data(), Results.size());
 }
 
+void Sema::CodeCompleteObjCClassForwardDecl(Scope *S) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+CodeCompleter->getCodeCompletionTUInfo(),
+CodeCompletionContext::CCC_ObjCClassForwardDecl);
+  Results.EnterNewScope();
+
+  if (CodeCompleter->includeGlobals()) {
+// Add all classes.
+AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+false, Results);
+  }
+
+  Results.ExitScope();
+
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+Results.data(), Results.size());
+}
+
 void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
   SourceLocation ClassNameLoc) {
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Index: clang/lib/Sema/CodeCompleteConsumer.cpp
===
--- clang/lib/Sema/CodeCompleteConsumer.cpp
+++ clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -83,6 +83,7 @@
   case CCC_ObjCCategoryName:
   case CCC_IncludedFile:
   case CCC_Attribute:
+  case CCC_ObjCClassForwardDecl:
 return false;
   }
 
@@ -166,6 +167,8 @@
 return "Attribute";
   case CCKind::CCC_Recovery:
 return "Recovery";
+  case CCKind::CCC_ObjCClassForwardDecl:
+return "ObjCClassForwardDecl";
   }
   llvm_unreachable("Invalid CodeCompletionContext::Kind!");
 }
Index: clang/lib/Parse/ParseObjc.cpp
===
--- clang/lib/Parse/ParseObjc.cpp
+++ clang/lib/Parse/ParseObjc.cpp
@@ -153,6 +153,11 @@
 
   while (true) {
 MaybeSkipAttributes(tok::objc_class);
+if (Tok.is(tok::code_completion)) {
+  cutOffParsing();
+  Actions.CodeCompleteObjCClassForwardDecl(getCurScope());
+  return Actions.ConvertDeclToDeclGroup(nullptr);
+}
 if (expectIdentifier()) {
   SkipUntil(tok::semi);
   return Actions.ConvertDeclToDeclGroup(nullptr);
Index: clang/lib/Frontend/ASTUnit.cpp
===
--- clang/lib/Frontend/ASTUnit.cpp
+++ clang/lib/Frontend/ASTUnit.cpp
@@ -322,6 +322,7 @@
   if (ID->getDefinition())
 Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
   Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
+  Contexts |= (1LL << CodeCompletionContext::CCC_ObjCClassForwardDecl);
 }
 
 // Deal with tag names.
@@ -2028,6 +2029,7 @@
   case CodeCompletionContext::CCC_IncludedFile:
   case CodeCompletionContext::CCC_Attribute:
   case CodeCompletionContext::CCC_NewName:
+  case CodeCompletionContext::CCC_ObjCClassForwardDecl:
 // We're looking for nothing, or we're looking for names that cannot
 // be hidden.
 return;
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -13429,6 +13429,7 @@
  ArrayRef Protocols);
   void CodeCompleteObjCProtocolDecl(Scope *S);
   void CodeCompleteObjCInterfaceDecl(Scope *S);
+  void CodeCompleteObjCClassForwardDecl(Scope *S);
   void CodeCompleteObjCSuperclass(Scope *S,
   IdentifierInfo *ClassName,
   SourceLocation ClassNameLoc);
Index: clang/include/clang/Sema/CodeCompleteConsumer.h

[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-26 Thread David Goldman via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG1b66840f7103: [clangd][ObjC] Support ObjC class rename from 
implementation decls (authored by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152720/new/

https://reviews.llvm.org/D152720

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp

Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,20 @@
   foo('x');
 }
   )cpp",
+
+  // ObjC class with a category.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+@implementation [[F^oo]]
+@end
+@interface [[Fo^o]] (Category)
+@end
+@implementation [[F^oo]] (Category)
+@end
+
+void func([[Fo^o]] *f) {}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -890,6 +904,15 @@
   )cpp",
"not a supported kind", HeaderFile},
 
+  {R"cpp(// disallow - category rename.
+@interface Foo
+@end
+@interface Foo (Cate^gory)
+@end
+  )cpp",
+   "Cannot rename symbol: there is no symbol at the given location",
+   HeaderFile},
+
   {
   R"cpp(
  #define MACRO 1
@@ -1468,7 +1491,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1557,13 +1580,12 @@
 }
   )cpp",
   },
-  {
-  // virtual templated method
-  R"cpp(
+  {// virtual templated method
+   R"cpp(
 template  class Foo { virtual void [[m]](); };
 class Bar : Foo { void [[^m]]() override; };
   )cpp",
-  R"cpp(
+   R"cpp(
   #include "foo.h"
 
   template void Foo::[[m]]() {}
@@ -1571,8 +1593,7 @@
   // the canonical Foo::m().
   // https://github.com/clangd/clangd/issues/1325
   class Baz : Foo { void m() override; };
-)cpp"
-  },
+)cpp"},
   {
   // rename on constructor and destructor.
   R"cpp(
@@ -1677,6 +1698,20 @@
 }
   )cpp",
   },
+  {
+  // Objective-C classes.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+  )cpp",
+  R"cpp(
+#include "foo.h"
+@implementation [[Foo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
+  },
   };
 
   trace::TestTracer Tracer;
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1127,6 +1127,16 @@
   )cpp";
   EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");
 
+  Code = R"cpp(
+@interface Foo
+@end
+@interface Foo (Ext)
+@end
+@implementation Foo ([[Ext]])
+@end
+  )cpp";
+  EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");
+
   Code = R"cpp(
 void test(id p);
   )cpp";
@@ -1216,10 +1226,7 @@
 std::string DumpedReferences;
   };
 
-  /// Parses \p Code, finds function or namespace '::foo' and annotates its body
-  /// with results of findExplicitReferences.
-  /// See actual tests for examples of annotation format.
-  AllRefs annotateReferencesInFoo(llvm::StringRef Code) {
+  TestTU newTU(llvm::StringRef Code) {
 TestTU TU;
 TU.Code = std::string(Code);
 
@@ -1228,30 +1235,11 @@
 TU.ExtraArgs.push_back("-std=c++20");
 TU.ExtraArgs.push_back("-xobjective-c++");
 
-auto AST = TU.build();
-auto *TestDecl = (AST, "foo");
-if (auto *T = llvm::dyn_cast(TestDecl))
-  TestDecl = T->getTemplatedDecl();
-
-std::vector Refs;
-if (const auto *Func = llvm::dyn_cast(TestDecl))
-  findExplicitReferences(
-  Func->getBody(),
-  [](ReferenceLoc R) { Refs.push_back(std::move(R)); },
-  AST.getHeuristicResolver());
-else if (const auto *NS = llvm::dyn_cast(TestDecl))
-  findExplicitReferences(
-  NS,
-  [, ](ReferenceLoc R) {
-// Avoid adding the namespace foo decl to the results.
-if (R.Targets.size() == 1 && R.Targets.front() == NS)
-  return;
-Refs.push_back(std::move(R));
-  },
-  AST.getHeuristicResolver());
-else
-  ADD_FAILURE() << "Failed 

[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-26 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 534618.
dgoldman marked an inline comment as done.
dgoldman added a comment.

Fixes for review + rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152720/new/

https://reviews.llvm.org/D152720

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp

Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,20 @@
   foo('x');
 }
   )cpp",
+
+  // ObjC class with a category.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+@implementation [[F^oo]]
+@end
+@interface [[Fo^o]] (Category)
+@end
+@implementation [[F^oo]] (Category)
+@end
+
+void func([[Fo^o]] *f) {}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -890,6 +904,15 @@
   )cpp",
"not a supported kind", HeaderFile},
 
+  {R"cpp(// disallow - category rename.
+@interface Foo
+@end
+@interface Foo (Cate^gory)
+@end
+  )cpp",
+   "Cannot rename symbol: there is no symbol at the given location",
+   HeaderFile},
+
   {
   R"cpp(
  #define MACRO 1
@@ -1468,7 +1491,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1557,13 +1580,12 @@
 }
   )cpp",
   },
-  {
-  // virtual templated method
-  R"cpp(
+  {// virtual templated method
+   R"cpp(
 template  class Foo { virtual void [[m]](); };
 class Bar : Foo { void [[^m]]() override; };
   )cpp",
-  R"cpp(
+   R"cpp(
   #include "foo.h"
 
   template void Foo::[[m]]() {}
@@ -1571,8 +1593,7 @@
   // the canonical Foo::m().
   // https://github.com/clangd/clangd/issues/1325
   class Baz : Foo { void m() override; };
-)cpp"
-  },
+)cpp"},
   {
   // rename on constructor and destructor.
   R"cpp(
@@ -1677,6 +1698,20 @@
 }
   )cpp",
   },
+  {
+  // Objective-C classes.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+  )cpp",
+  R"cpp(
+#include "foo.h"
+@implementation [[Foo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
+  },
   };
 
   trace::TestTracer Tracer;
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1127,6 +1127,16 @@
   )cpp";
   EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");
 
+  Code = R"cpp(
+@interface Foo
+@end
+@interface Foo (Ext)
+@end
+@implementation Foo ([[Ext]])
+@end
+  )cpp";
+  EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");
+
   Code = R"cpp(
 void test(id p);
   )cpp";
@@ -1216,10 +1226,7 @@
 std::string DumpedReferences;
   };
 
-  /// Parses \p Code, finds function or namespace '::foo' and annotates its body
-  /// with results of findExplicitReferences.
-  /// See actual tests for examples of annotation format.
-  AllRefs annotateReferencesInFoo(llvm::StringRef Code) {
+  TestTU newTU(llvm::StringRef Code) {
 TestTU TU;
 TU.Code = std::string(Code);
 
@@ -1228,30 +1235,11 @@
 TU.ExtraArgs.push_back("-std=c++20");
 TU.ExtraArgs.push_back("-xobjective-c++");
 
-auto AST = TU.build();
-auto *TestDecl = (AST, "foo");
-if (auto *T = llvm::dyn_cast(TestDecl))
-  TestDecl = T->getTemplatedDecl();
-
-std::vector Refs;
-if (const auto *Func = llvm::dyn_cast(TestDecl))
-  findExplicitReferences(
-  Func->getBody(),
-  [](ReferenceLoc R) { Refs.push_back(std::move(R)); },
-  AST.getHeuristicResolver());
-else if (const auto *NS = llvm::dyn_cast(TestDecl))
-  findExplicitReferences(
-  NS,
-  [, ](ReferenceLoc R) {
-// Avoid adding the namespace foo decl to the results.
-if (R.Targets.size() == 1 && R.Targets.front() == NS)
-  return;
-Refs.push_back(std::move(R));
-  },
-  AST.getHeuristicResolver());
-else
-  ADD_FAILURE() << "Failed to find ::foo decl for test";
+return TU;
+  }
 
+ 

[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-23 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:787
+  // names like class and protocol names.
+  if (const auto *CD = dyn_cast())
+if (CD->getName() != IdentifierToken->text(SM))

kadircet wrote:
> this special casing should no longer be needed if we just map CategoryDecls 
> to InterfaceDecls in `locateDeclAt` rather than at canonicalization time
Yep, no longer needed since the `Check the rename-triggering location is 
actually being renamed` check catches this although the error is no symbol 
found instead of unsupported symbol.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152720/new/

https://reviews.llvm.org/D152720

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-23 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 533993.
dgoldman marked 4 inline comments as done.
dgoldman added a comment.

Fixes for review


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152720/new/

https://reviews.llvm.org/D152720

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp

Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,20 @@
   foo('x');
 }
   )cpp",
+
+  // ObjC class with a category.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+@implementation [[F^oo]]
+@end
+@interface [[Fo^o]] (Category)
+@end
+@implementation [[F^oo]] (Category)
+@end
+
+void func([[Fo^o]] *f) {}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -890,6 +904,15 @@
   )cpp",
"not a supported kind", HeaderFile},
 
+  {R"cpp(// disallow - category rename.
+@interface Foo
+@end
+@interface Foo (Cate^gory)
+@end
+  )cpp",
+   "Cannot rename symbol: there is no symbol at the given location",
+   HeaderFile},
+
   {
   R"cpp(
  #define MACRO 1
@@ -1468,7 +1491,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1557,13 +1580,12 @@
 }
   )cpp",
   },
-  {
-  // virtual templated method
-  R"cpp(
+  {// virtual templated method
+   R"cpp(
 template  class Foo { virtual void [[m]](); };
 class Bar : Foo { void [[^m]]() override; };
   )cpp",
-  R"cpp(
+   R"cpp(
   #include "foo.h"
 
   template void Foo::[[m]]() {}
@@ -1571,8 +1593,7 @@
   // the canonical Foo::m().
   // https://github.com/clangd/clangd/issues/1325
   class Baz : Foo { void m() override; };
-)cpp"
-  },
+)cpp"},
   {
   // rename on constructor and destructor.
   R"cpp(
@@ -1677,6 +1698,20 @@
 }
   )cpp",
   },
+  {
+  // Objective-C classes.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+  )cpp",
+  R"cpp(
+#include "foo.h"
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
+  },
   };
 
   trace::TestTracer Tracer;
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1054,6 +1054,16 @@
   )cpp";
   EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");
 
+  Code = R"cpp(
+@interface Foo
+@end
+@interface Foo (Ext)
+@end
+@implementation Foo ([[Ext]])
+@end
+  )cpp";
+  EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");
+
   Code = R"cpp(
 void test(id p);
   )cpp";
@@ -1143,10 +1153,7 @@
 std::string DumpedReferences;
   };
 
-  /// Parses \p Code, finds function or namespace '::foo' and annotates its body
-  /// with results of findExplicitReferences.
-  /// See actual tests for examples of annotation format.
-  AllRefs annotateReferencesInFoo(llvm::StringRef Code) {
+  TestTU newTU(llvm::StringRef Code) {
 TestTU TU;
 TU.Code = std::string(Code);
 
@@ -1155,30 +1162,11 @@
 TU.ExtraArgs.push_back("-std=c++20");
 TU.ExtraArgs.push_back("-xobjective-c++");
 
-auto AST = TU.build();
-auto *TestDecl = (AST, "foo");
-if (auto *T = llvm::dyn_cast(TestDecl))
-  TestDecl = T->getTemplatedDecl();
-
-std::vector Refs;
-if (const auto *Func = llvm::dyn_cast(TestDecl))
-  findExplicitReferences(
-  Func->getBody(),
-  [](ReferenceLoc R) { Refs.push_back(std::move(R)); },
-  AST.getHeuristicResolver());
-else if (const auto *NS = llvm::dyn_cast(TestDecl))
-  findExplicitReferences(
-  NS,
-  [, ](ReferenceLoc R) {
-// Avoid adding the namespace foo decl to the results.
-if (R.Targets.size() == 1 && R.Targets.front() == NS)
-  return;
-Refs.push_back(std::move(R));
-  },
-  AST.getHeuristicResolver());
-else
-  ADD_FAILURE() << "Failed to find ::foo decl for test";
+return TU;
+  }
 
+  

[PATCH] D150978: [clang][Sema] Add CodeCompletionContext::CCC_ObjCClassForwardDecl

2023-06-23 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 533969.
dgoldman marked an inline comment as done.
dgoldman added a comment.

Add a contextAllowsHeaderInsertion helper to clangd


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D150978/new/

https://reviews.llvm.org/D150978

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang/include/clang/Sema/CodeCompleteConsumer.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Frontend/ASTUnit.cpp
  clang/lib/Parse/ParseObjc.cpp
  clang/lib/Sema/CodeCompleteConsumer.cpp
  clang/lib/Sema/SemaCodeComplete.cpp
  clang/tools/libclang/CIndexCodeCompletion.cpp

Index: clang/tools/libclang/CIndexCodeCompletion.cpp
===
--- clang/tools/libclang/CIndexCodeCompletion.cpp
+++ clang/tools/libclang/CIndexCodeCompletion.cpp
@@ -537,6 +537,7 @@
 case CodeCompletionContext::CCC_Other:
 case CodeCompletionContext::CCC_ObjCInterface:
 case CodeCompletionContext::CCC_ObjCImplementation:
+case CodeCompletionContext::CCC_ObjCClassForwardDecl:
 case CodeCompletionContext::CCC_NewName:
 case CodeCompletionContext::CCC_MacroName:
 case CodeCompletionContext::CCC_PreprocessorExpression:
Index: clang/lib/Sema/SemaCodeComplete.cpp
===
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -8460,6 +8460,24 @@
 Results.data(), Results.size());
 }
 
+void Sema::CodeCompleteObjCClassForwardDecl(Scope *S) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+CodeCompleter->getCodeCompletionTUInfo(),
+CodeCompletionContext::CCC_ObjCClassForwardDecl);
+  Results.EnterNewScope();
+
+  if (CodeCompleter->includeGlobals()) {
+// Add all classes.
+AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+false, Results);
+  }
+
+  Results.ExitScope();
+
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+Results.data(), Results.size());
+}
+
 void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
   SourceLocation ClassNameLoc) {
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Index: clang/lib/Sema/CodeCompleteConsumer.cpp
===
--- clang/lib/Sema/CodeCompleteConsumer.cpp
+++ clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -83,6 +83,7 @@
   case CCC_ObjCCategoryName:
   case CCC_IncludedFile:
   case CCC_Attribute:
+  case CCC_ObjCClassForwardDecl:
 return false;
   }
 
@@ -166,6 +167,8 @@
 return "Attribute";
   case CCKind::CCC_Recovery:
 return "Recovery";
+  case CCKind::CCC_ObjCClassForwardDecl:
+return "ObjCClassForwardDecl";
   }
   llvm_unreachable("Invalid CodeCompletionContext::Kind!");
 }
Index: clang/lib/Parse/ParseObjc.cpp
===
--- clang/lib/Parse/ParseObjc.cpp
+++ clang/lib/Parse/ParseObjc.cpp
@@ -153,6 +153,11 @@
 
   while (true) {
 MaybeSkipAttributes(tok::objc_class);
+if (Tok.is(tok::code_completion)) {
+  cutOffParsing();
+  Actions.CodeCompleteObjCClassForwardDecl(getCurScope());
+  return Actions.ConvertDeclToDeclGroup(nullptr);
+}
 if (expectIdentifier()) {
   SkipUntil(tok::semi);
   return Actions.ConvertDeclToDeclGroup(nullptr);
Index: clang/lib/Frontend/ASTUnit.cpp
===
--- clang/lib/Frontend/ASTUnit.cpp
+++ clang/lib/Frontend/ASTUnit.cpp
@@ -322,6 +322,7 @@
   if (ID->getDefinition())
 Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
   Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
+  Contexts |= (1LL << CodeCompletionContext::CCC_ObjCClassForwardDecl);
 }
 
 // Deal with tag names.
@@ -2027,6 +2028,7 @@
   case CodeCompletionContext::CCC_IncludedFile:
   case CodeCompletionContext::CCC_Attribute:
   case CodeCompletionContext::CCC_NewName:
+  case CodeCompletionContext::CCC_ObjCClassForwardDecl:
 // We're looking for nothing, or we're looking for names that cannot
 // be hidden.
 return;
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -13417,6 +13417,7 @@
  ArrayRef Protocols);
   void CodeCompleteObjCProtocolDecl(Scope *S);
   void CodeCompleteObjCInterfaceDecl(Scope *S);
+  void CodeCompleteObjCClassForwardDecl(Scope *S);
   void CodeCompleteObjCSuperclass(Scope *S,
   IdentifierInfo *ClassName,
   

[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-22 Thread David Goldman via Phabricator via cfe-commits
dgoldman marked an inline comment as done.
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/FindTarget.cpp:716
+void VisitObjCImplementationDecl(const ObjCImplementationDecl *OIMD) {
+  if (const auto *CI = OIMD->getClassInterface())
+Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),

kadircet wrote:
> we don't have the null check in other places, what's the significance here?
Removed, doesn't look like it's needed.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152720/new/

https://reviews.llvm.org/D152720

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-22 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 533769.
dgoldman marked an inline comment as done.
dgoldman added a comment.

Add more FindTarget tests


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152720/new/

https://reviews.llvm.org/D152720

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp

Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,20 @@
   foo('x');
 }
   )cpp",
+
+  // ObjC class with a category.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+@implementation [[F^oo]]
+@end
+@interface [[Fo^o]] (Category)
+@end
+@implementation [[F^oo]] (Category)
+@end
+
+void func([[Fo^o]] *f) {}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -890,6 +904,14 @@
   )cpp",
"not a supported kind", HeaderFile},
 
+  {R"cpp(// disallow - category rename.
+@interface Foo
+@end
+@interface Foo (Cate^gory)
+@end
+  )cpp",
+   "not a supported kind", HeaderFile},
+
   {
   R"cpp(
  #define MACRO 1
@@ -1468,7 +1490,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1557,13 +1579,12 @@
 }
   )cpp",
   },
-  {
-  // virtual templated method
-  R"cpp(
+  {// virtual templated method
+   R"cpp(
 template  class Foo { virtual void [[m]](); };
 class Bar : Foo { void [[^m]]() override; };
   )cpp",
-  R"cpp(
+   R"cpp(
   #include "foo.h"
 
   template void Foo::[[m]]() {}
@@ -1571,8 +1592,7 @@
   // the canonical Foo::m().
   // https://github.com/clangd/clangd/issues/1325
   class Baz : Foo { void m() override; };
-)cpp"
-  },
+)cpp"},
   {
   // rename on constructor and destructor.
   R"cpp(
@@ -1677,6 +1697,20 @@
 }
   )cpp",
   },
+  {
+  // Objective-C classes.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+  )cpp",
+  R"cpp(
+#include "foo.h"
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
+  },
   };
 
   trace::TestTracer Tracer;
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1054,6 +1054,16 @@
   )cpp";
   EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");
 
+  Code = R"cpp(
+@interface Foo
+@end
+@interface Foo (Ext)
+@end
+@implementation Foo ([[Ext]])
+@end
+  )cpp";
+  EXPECT_DECLS("ObjCCategoryImplDecl", "@interface Foo(Ext)");
+
   Code = R"cpp(
 void test(id p);
   )cpp";
@@ -1143,10 +1153,7 @@
 std::string DumpedReferences;
   };
 
-  /// Parses \p Code, finds function or namespace '::foo' and annotates its body
-  /// with results of findExplicitReferences.
-  /// See actual tests for examples of annotation format.
-  AllRefs annotateReferencesInFoo(llvm::StringRef Code) {
+  TestTU newTU(llvm::StringRef Code) {
 TestTU TU;
 TU.Code = std::string(Code);
 
@@ -1155,30 +1162,11 @@
 TU.ExtraArgs.push_back("-std=c++20");
 TU.ExtraArgs.push_back("-xobjective-c++");
 
-auto AST = TU.build();
-auto *TestDecl = (AST, "foo");
-if (auto *T = llvm::dyn_cast(TestDecl))
-  TestDecl = T->getTemplatedDecl();
-
-std::vector Refs;
-if (const auto *Func = llvm::dyn_cast(TestDecl))
-  findExplicitReferences(
-  Func->getBody(),
-  [](ReferenceLoc R) { Refs.push_back(std::move(R)); },
-  AST.getHeuristicResolver());
-else if (const auto *NS = llvm::dyn_cast(TestDecl))
-  findExplicitReferences(
-  NS,
-  [, ](ReferenceLoc R) {
-// Avoid adding the namespace foo decl to the results.
-if (R.Targets.size() == 1 && R.Targets.front() == NS)
-  return;
-Refs.push_back(std::move(R));
-  },
-  AST.getHeuristicResolver());
-else
-  ADD_FAILURE() << "Failed to find ::foo decl for test";
+return TU;
+  }
 
+  AllRefs annotatedReferences(llvm::StringRef 

[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-22 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 533640.
dgoldman added a comment.

Disable renaming categories


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152720/new/

https://reviews.llvm.org/D152720

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp

Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,20 @@
   foo('x');
 }
   )cpp",
+
+  // ObjC class with a category.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+@implementation [[F^oo]]
+@end
+@interface [[Fo^o]] (Category)
+@end
+@implementation [[F^oo]] (Category)
+@end
+
+void func([[Fo^o]] *f) {}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -890,6 +904,14 @@
   )cpp",
"not a supported kind", HeaderFile},
 
+  {R"cpp(// disallow - category rename.
+@interface Foo
+@end
+@interface Foo (Cate^gory)
+@end
+  )cpp",
+   "not a supported kind", HeaderFile},
+
   {
   R"cpp(
  #define MACRO 1
@@ -1468,7 +1490,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1557,13 +1579,12 @@
 }
   )cpp",
   },
-  {
-  // virtual templated method
-  R"cpp(
+  {// virtual templated method
+   R"cpp(
 template  class Foo { virtual void [[m]](); };
 class Bar : Foo { void [[^m]]() override; };
   )cpp",
-  R"cpp(
+   R"cpp(
   #include "foo.h"
 
   template void Foo::[[m]]() {}
@@ -1571,8 +1592,7 @@
   // the canonical Foo::m().
   // https://github.com/clangd/clangd/issues/1325
   class Baz : Foo { void m() override; };
-)cpp"
-  },
+)cpp"},
   {
   // rename on constructor and destructor.
   R"cpp(
@@ -1677,6 +1697,20 @@
 }
   )cpp",
   },
+  {
+  // Objective-C classes.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+  )cpp",
+  R"cpp(
+#include "foo.h"
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
+  },
   };
 
   trace::TestTracer Tracer;
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -19,6 +19,7 @@
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ParentMapContext.h"
 #include "clang/AST/Stmt.h"
@@ -137,6 +138,10 @@
 if (const auto *TargetDecl = UD->getTargetDecl())
   return canonicalRenameDecl(TargetDecl);
   }
+  if (const auto *CD = dyn_cast(D)) {
+if (const auto CI = CD->getClassInterface())
+  return canonicalRenameDecl(CI);
+  }
   return dyn_cast(D->getCanonicalDecl());
 }
 
@@ -278,6 +283,10 @@
   if (Ref.Targets.empty())
 return;
   for (const auto *Target : Ref.Targets) {
+// Skip categories since we don't support renaming them, only
+// the interface(s) which they reference.
+if (isa(Target))
+  continue;
 if (canonicalRenameDecl(Target) == ) {
   Results.push_back(Ref.NameLoc);
   return;
@@ -773,6 +782,12 @@
   if (Invalid)
 return makeError(std::move(*Invalid));
 
+  // We don't support renaming the category name, only ObjC top level container
+  // names like class and protocol names.
+  if (const auto *CD = dyn_cast())
+if (CD->getName() != IdentifierToken->text(SM))
+  return makeError(ReasonToReject::UnsupportedSymbol);
+
   auto Reject =
   renameable(RenameDecl, RInputs.MainFilePath, RInputs.Index, Opts);
   if (Reject)
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -128,7 +128,7 @@
 return HighlightingKind::Class;
   if (isa(D))
 return HighlightingKind::Interface;
-  if (isa(D))
+  if (isa(D))
 return HighlightingKind::Namespace;
   if (auto *MD = dyn_cast(D))
 return 

[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-20 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:131
 return HighlightingKind::Interface;
-  if (isa(D))
+  if (isa(D))
 return HighlightingKind::Namespace;

kadircet wrote:
> let's do this in a separate change, with some tests
Given the other changes, this is needed otherwise the semantic highlighting 
test fails.



Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:171-177
+if (const auto *C = dyn_cast(D)) {
+  if (C->getLocation() == TokenStartLoc)
+D = C->getClassInterface();
+  else if (const auto *I = C->getImplementation())
+if (I->getLocation() == TokenStartLoc)
+  D = C->getClassInterface();
+}

kadircet wrote:
> sorry i don't follow what's the logic doing here and we're likely doing these 
> in the wrong layer.
> 
> we should either:
> - Fix selection tree to pick the correct ASTNode, if it's picking the wrong 
> one due to not having special cases for these locations here
> - Fix the `targetDecl` logic to make sure it emits all the declarations that 
> might be referenced by this ast node, if it's missing ClassInterface.
> - Fix the canonicalRenameDecl, if we should always prefer `ClassInterface` in 
> these cases.
Replied to you in chat, LMK what you think.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152720/new/

https://reviews.llvm.org/D152720

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-14 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 531439.
dgoldman added a comment.

- Implement discussed fixes + category support


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152720/new/

https://reviews.llvm.org/D152720

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp

Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,30 @@
   foo('x');
 }
   )cpp",
+
+  // ObjC class with a category.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+@implementation [[F^oo]]
+@end
+@interface [[Fo^o]] (Category)
+@end
+@implementation [[F^oo]] (Category)
+@end
+
+void func([[Fo^o]] *f) {}
+  )cpp",
+
+  // ObjC category.
+  R"cpp(
+@interface Foo
+@end
+@interface Foo ([[Cate^gory]])
+@end
+@implementation Foo ([[Cate^gory]])
+@end
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1468,7 +1492,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1557,13 +1581,12 @@
 }
   )cpp",
   },
-  {
-  // virtual templated method
-  R"cpp(
+  {// virtual templated method
+   R"cpp(
 template  class Foo { virtual void [[m]](); };
 class Bar : Foo { void [[^m]]() override; };
   )cpp",
-  R"cpp(
+   R"cpp(
   #include "foo.h"
 
   template void Foo::[[m]]() {}
@@ -1571,8 +1594,7 @@
   // the canonical Foo::m().
   // https://github.com/clangd/clangd/issues/1325
   class Baz : Foo { void m() override; };
-)cpp"
-  },
+)cpp"},
   {
   // rename on constructor and destructor.
   R"cpp(
@@ -1677,6 +1699,20 @@
 }
   )cpp",
   },
+  {
+  // Objective-C classes.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+  )cpp",
+  R"cpp(
+#include "foo.h"
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
+  },
   };
 
   trace::TestTracer Tracer;
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -19,6 +19,7 @@
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ParentMapContext.h"
 #include "clang/AST/Stmt.h"
@@ -137,6 +138,14 @@
 if (const auto *TargetDecl = UD->getTargetDecl())
   return canonicalRenameDecl(TargetDecl);
   }
+  if (const auto *ID = dyn_cast(D)) {
+if (const auto CI = ID->getClassInterface())
+  return canonicalRenameDecl(CI);
+  }
+  if (const auto *CID = dyn_cast(D)) {
+if (const auto CD = CID->getCategoryDecl())
+  return canonicalRenameDecl(CD);
+  }
   return dyn_cast(D->getCanonicalDecl());
 }
 
@@ -156,6 +165,16 @@
targetDecl(SelectedNode->ASTNode,
   DeclRelation::Alias | DeclRelation::TemplatePattern,
   AST.getHeuristicResolver())) {
+// If we select the interface name in `@interface Class (CategoryName)` or
+// the implementation, the decl to rename is actually the interface, not
+// the category.
+if (const auto *C = dyn_cast(D)) {
+  if (C->getLocation() == TokenStartLoc)
+D = C->getClassInterface();
+  else if (const auto *I = C->getImplementation())
+if (I->getLocation() == TokenStartLoc)
+  D = C->getClassInterface();
+}
 Result.insert(canonicalRenameDecl(D));
   }
   return Result;
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -128,7 +128,7 @@
 return HighlightingKind::Class;
   if (isa(D))
 return HighlightingKind::Interface;
-  if (isa(D))
+  if (isa(D))
 return HighlightingKind::Namespace;
   if (auto *MD = dyn_cast(D))
 return MD->isStatic() ? HighlightingKind::StaticMethod
Index: clang-tools-extra/clangd/FindTarget.cpp
===
--- 

[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-12 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 530665.
dgoldman added a comment.

Run clang format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152720/new/

https://reviews.llvm.org/D152720

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,16 @@
   foo('x');
 }
   )cpp",
+
+  // ObjC class.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1468,7 +1478,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1557,13 +1567,12 @@
 }
   )cpp",
   },
-  {
-  // virtual templated method
-  R"cpp(
+  {// virtual templated method
+   R"cpp(
 template  class Foo { virtual void [[m]](); };
 class Bar : Foo { void [[^m]]() override; };
   )cpp",
-  R"cpp(
+   R"cpp(
   #include "foo.h"
 
   template void Foo::[[m]]() {}
@@ -1571,8 +1580,7 @@
   // the canonical Foo::m().
   // https://github.com/clangd/clangd/issues/1325
   class Baz : Foo { void m() override; };
-)cpp"
-  },
+)cpp"},
   {
   // rename on constructor and destructor.
   R"cpp(
@@ -1677,6 +1685,20 @@
 }
   )cpp",
   },
+  {
+  // Objective-C classes.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+  )cpp",
+  R"cpp(
+#include "foo.h"
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
+  },
   };
 
   trace::TestTracer Tracer;
Index: clang-tools-extra/clangd/FindTarget.cpp
===
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -707,6 +707,14 @@
   /*IsDecl=*/true,
   {OCID->getCategoryDecl()}});
 }
+
+void VisitObjCImplementationDecl(const ObjCImplementationDecl *OIMD) {
+  if (const auto *CI = OIMD->getClassInterface())
+Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+OIMD->getLocation(),
+/*IsDecl=*/true,
+{CI}});
+}
   };
 
   Visitor V{Resolver};


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,16 @@
   foo('x');
 }
   )cpp",
+
+  // ObjC class.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1468,7 +1478,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1557,13 +1567,12 @@
 }
   )cpp",
   },
-  {
-  // virtual templated method
-  R"cpp(
+  {// virtual templated method
+   R"cpp(
 template  class Foo { virtual void [[m]](); };
 class Bar : Foo { void [[^m]]() override; };
   )cpp",
-  R"cpp(
+   R"cpp(
   #include "foo.h"
 
   template void Foo::[[m]]() {}
@@ -1571,8 +1580,7 @@
   // the canonical Foo::m().
   // https://github.com/clangd/clangd/issues/1325
   class Baz : Foo { void m() override; };
-)cpp"
-  },
+)cpp"},
   {
   // rename on constructor and destructor.
   R"cpp(
@@ -1677,6 +1685,20 @@
 }
   )cpp",
   },
+  {
+  // Objective-C classes.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+  )cpp",
+  R"cpp(
+#include "foo.h"
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
+  },
   };
 
   trace::TestTracer Tracer;
Index: 

[PATCH] D152720: [clangd][ObjC] Support ObjC class rename from implementation decls

2023-06-12 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D152720

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,16 @@
   foo('x');
 }
   )cpp",
+
+  // ObjC class.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1468,7 +1478,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1677,6 +1687,20 @@
 }
   )cpp",
   },
+  {
+  // Objective-C classes.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+  )cpp",
+  R"cpp(
+#include "foo.h"
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
+  },
   };
 
   trace::TestTracer Tracer;
Index: clang-tools-extra/clangd/FindTarget.cpp
===
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -707,6 +707,14 @@
   /*IsDecl=*/true,
   {OCID->getCategoryDecl()}});
 }
+
+void VisitObjCImplementationDecl(const ObjCImplementationDecl *OIMD) {
+  if (const auto *CI = OIMD->getClassInterface())
+Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+OIMD->getLocation(),
+/*IsDecl=*/true,
+{CI}});
+}
   };
 
   Visitor V{Resolver};


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -840,6 +840,16 @@
   foo('x');
 }
   )cpp",
+
+  // ObjC class.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1468,7 +1478,7 @@
 
 TEST(CrossFileRenameTests, WithUpToDateIndex) {
   MockCompilationDatabase CDB;
-  CDB.ExtraClangFlags = {"-xc++"};
+  CDB.ExtraClangFlags = {"-xobjective-c++"};
   // rename is runnning on all "^" points in FooH, and "[[]]" ranges are the
   // expected rename occurrences.
   struct Case {
@@ -1677,6 +1687,20 @@
 }
   )cpp",
   },
+  {
+  // Objective-C classes.
+  R"cpp(
+@interface [[Fo^o]]
+@end
+  )cpp",
+  R"cpp(
+#include "foo.h"
+@implementation [[F^oo]]
+@end
+
+void func([[Foo]] *f) {}
+  )cpp",
+  },
   };
 
   trace::TestTracer Tracer;
Index: clang-tools-extra/clangd/FindTarget.cpp
===
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -707,6 +707,14 @@
   /*IsDecl=*/true,
   {OCID->getCategoryDecl()}});
 }
+
+void VisitObjCImplementationDecl(const ObjCImplementationDecl *OIMD) {
+  if (const auto *CI = OIMD->getClassInterface())
+Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+OIMD->getLocation(),
+/*IsDecl=*/true,
+{CI}});
+}
   };
 
   Visitor V{Resolver};
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D150978: [clang][Sema] Add CodeCompletionContext::CCC_ObjCClassForwardDecl

2023-05-19 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
Herald added projects: clang, clang-tools-extra.

- Use this new context in Sema to limit completions to seen ObjC class names

- Use this new context in clangd to disable include insertions when completing 
ObjC forward decls


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D150978

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang/include/clang/Sema/CodeCompleteConsumer.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Frontend/ASTUnit.cpp
  clang/lib/Parse/ParseObjc.cpp
  clang/lib/Sema/CodeCompleteConsumer.cpp
  clang/lib/Sema/SemaCodeComplete.cpp
  clang/tools/libclang/CIndexCodeCompletion.cpp

Index: clang/tools/libclang/CIndexCodeCompletion.cpp
===
--- clang/tools/libclang/CIndexCodeCompletion.cpp
+++ clang/tools/libclang/CIndexCodeCompletion.cpp
@@ -537,6 +537,7 @@
 case CodeCompletionContext::CCC_Other:
 case CodeCompletionContext::CCC_ObjCInterface:
 case CodeCompletionContext::CCC_ObjCImplementation:
+case CodeCompletionContext::CCC_ObjCClassForwardDecl:
 case CodeCompletionContext::CCC_NewName:
 case CodeCompletionContext::CCC_MacroName:
 case CodeCompletionContext::CCC_PreprocessorExpression:
Index: clang/lib/Sema/SemaCodeComplete.cpp
===
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -8460,6 +8460,24 @@
 Results.data(), Results.size());
 }
 
+void Sema::CodeCompleteObjCClassForwardDecl(Scope *S) {
+  ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+CodeCompleter->getCodeCompletionTUInfo(),
+CodeCompletionContext::CCC_ObjCClassForwardDecl);
+  Results.EnterNewScope();
+
+  if (CodeCompleter->includeGlobals()) {
+// Add all classes.
+AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
+false, Results);
+  }
+
+  Results.ExitScope();
+
+  HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+Results.data(), Results.size());
+}
+
 void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
   SourceLocation ClassNameLoc) {
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Index: clang/lib/Sema/CodeCompleteConsumer.cpp
===
--- clang/lib/Sema/CodeCompleteConsumer.cpp
+++ clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -83,6 +83,7 @@
   case CCC_ObjCCategoryName:
   case CCC_IncludedFile:
   case CCC_Attribute:
+  case CCC_ObjCClassForwardDecl:
 return false;
   }
 
@@ -166,6 +167,8 @@
 return "Attribute";
   case CCKind::CCC_Recovery:
 return "Recovery";
+  case CCKind::CCC_ObjCClassForwardDecl:
+return "ObjCClassForwardDecl";
   }
   llvm_unreachable("Invalid CodeCompletionContext::Kind!");
 }
Index: clang/lib/Parse/ParseObjc.cpp
===
--- clang/lib/Parse/ParseObjc.cpp
+++ clang/lib/Parse/ParseObjc.cpp
@@ -153,6 +153,11 @@
 
   while (true) {
 MaybeSkipAttributes(tok::objc_class);
+if (Tok.is(tok::code_completion)) {
+  cutOffParsing();
+  Actions.CodeCompleteObjCClassForwardDecl(getCurScope());
+  return Actions.ConvertDeclToDeclGroup(nullptr);
+}
 if (expectIdentifier()) {
   SkipUntil(tok::semi);
   return Actions.ConvertDeclToDeclGroup(nullptr);
Index: clang/lib/Frontend/ASTUnit.cpp
===
--- clang/lib/Frontend/ASTUnit.cpp
+++ clang/lib/Frontend/ASTUnit.cpp
@@ -322,6 +322,7 @@
   if (ID->getDefinition())
 Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
   Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
+  Contexts |= (1LL << CodeCompletionContext::CCC_ObjCClassForwardDecl);
 }
 
 // Deal with tag names.
@@ -2027,6 +2028,7 @@
   case CodeCompletionContext::CCC_IncludedFile:
   case CodeCompletionContext::CCC_Attribute:
   case CodeCompletionContext::CCC_NewName:
+  case CodeCompletionContext::CCC_ObjCClassForwardDecl:
 // We're looking for nothing, or we're looking for names that cannot
 // be hidden.
 return;
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -13417,6 +13417,7 @@
  ArrayRef Protocols);
   void CodeCompleteObjCProtocolDecl(Scope *S);
   void 

[PATCH] D140275: [clangd] Tweak to add doxygen comment to the function declaration

2023-05-10 Thread David Goldman via Phabricator via cfe-commits
dgoldman added a comment.

In D140275#4203456 , @tupos wrote:

> Could you please also advice me what else need to be done for the ObjC, since 
> there were many years since I wrote ObjC last time I'm not sure what else 
> need to be done there.
>
> Thanks.

I think this is fine for a v1 - I think the main improvement would be changing 
the style/format, Xcode itself uses the following format instead where 
<#Placeholder Name#> denotes a placeholder:

  /// <#Description#>
  /// - Parameters:
  ///   - arg1: <#model description#>
  ///   - arg2: <#user description#>
  /// - Returns: <#description#>


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140275/new/

https://reviews.llvm.org/D140275

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D140275: [clangd] Tweak to add doxygen comment to the function declaration

2023-03-14 Thread David Goldman via Phabricator via cfe-commits
dgoldman added a comment.
Herald added a subscriber: ChuanqiXu.

Hey, are you still planning to work on this? Otherwise, is it okay if I take 
over this patch to implement this feature?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140275/new/

https://reviews.llvm.org/D140275

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D140275: [clangd] Tweak to add doxygen comment to the function declaration

2023-01-12 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/AddDoxygenComment.cpp:37
+//* @param bar
+//* @return
+//*/

sammccall wrote:
> I'm a bit concerned about people generating these `@param bar` and `@return` 
> and leaving them there without filling them in - I've seen plenty of code 
> like that and it's substantially worse than no comments at all.
> 
> I'm not sure we can do much though: could generate `@return TODO` or so to 
> make it more visually obvious - WDYT?
VS Code itself has support for snippets - 
https://code.visualstudio.com/api/references/vscode-api#TextEditor - 
insertSnippet - but the LSP spec doesn't yet. Once it has it I think it would 
makes sense to use them here, but until then, TODO seems like the best we can 
do?



Comment at: clang-tools-extra/clangd/refactor/tweaks/AddDoxygenComment.cpp:74
+bool AddDoxygenComment::prepare(const Selection ) {
+  if (!Inputs.AST->getLangOpts().CPlusPlus) {
+return false;

sammccall wrote:
> why? doxygen supports C AFAIK
Would also be nice to support ObjC too, we'll just need to add support for 
ObjCMethodDecl as well to expand support for ObjC methods.  
(https://clang.llvm.org/doxygen/classclang_1_1ObjCMethodDecl.html vs 
https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html) But even if 
that's not done in this diff, still seems fine to enable it generally?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140275/new/

https://reviews.llvm.org/D140275

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D139458: [clangd] Full support for #import insertions

2023-01-09 Thread David Goldman via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
dgoldman marked an inline comment as done.
Closed by commit rG042dd99484d6: [clangd] Full support for #import insertions 
(authored by dgoldman).

Changed prior to commit:
  https://reviews.llvm.org/D139458?vs=486706=487418#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139458/new/

https://reviews.llvm.org/D139458

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/ASTSignals.cpp
  clang-tools-extra/clangd/ASTSignals.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Compiler.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/ParsedAST.cpp
  clang-tools-extra/clangd/ParsedAST.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
  clang-tools-extra/clangd/unittests/ASTTests.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2736,17 +2736,21 @@
   Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
   Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000,
   Symbol::Include | Symbol::Import);
-
-  auto Results = completions("Fun^", {Sym}).Completions;
+  CodeCompleteOptions Opts;
+  // Should only take effect in import contexts.
+  Opts.ImportInsertions = true;
+  auto Results = completions("Fun^", {Sym}, Opts).Completions;
   assert(!Results.empty());
   EXPECT_THAT(Results[0],
   AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
 
-  Results = completions("Fun^", {Sym}, {}, "Foo.m").Completions;
+  ASTSignals Signals;
+  Signals.InsertionDirective = Symbol::IncludeDirective::Import;
+  Opts.MainFileSignals = 
+  Results = completions("Fun^", {Sym}, Opts, "Foo.m").Completions;
   assert(!Results.empty());
-  // TODO: Once #import integration support is done this should be #import.
   EXPECT_THAT(Results[0],
-  AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
+  AllOf(named("Func"), insertIncludeText("#import \"bar.h\"\n")));
 
   Sym.IncludeHeaders[0].SupportedDirectives = Symbol::Import;
   Results = completions("Fun^", {Sym}).Completions;
Index: clang-tools-extra/clangd/unittests/ASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ASTTests.cpp
@@ -11,6 +11,7 @@
 #include "Annotations.h"
 #include "ParsedAST.h"
 #include "TestTU.h"
+#include "index/Symbol.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
@@ -618,6 +619,45 @@
   hasReservedScope(*findUnqualifiedDecl(AST, "secret").getDeclContext()));
 }
 
+TEST(ClangdAST, PreferredIncludeDirective) {
+  auto ComputePreferredDirective = [](TestTU ) {
+auto AST = TU.build();
+return preferredIncludeDirective(AST.tuPath(), AST.getLangOpts(),
+ AST.getIncludeStructure().MainFileIncludes,
+ AST.getLocalTopLevelDecls());
+  };
+  TestTU ObjCTU = TestTU::withCode(R"cpp(
+  int main() {}
+  )cpp");
+  ObjCTU.Filename = "TestTU.m";
+  EXPECT_EQ(ComputePreferredDirective(ObjCTU),
+Symbol::IncludeDirective::Import);
+
+  TestTU HeaderTU = TestTU::withCode(R"cpp(
+  #import "TestTU.h"
+  )cpp");
+  HeaderTU.Filename = "TestTUHeader.h";
+  HeaderTU.ExtraArgs = {"-xobjective-c++-header"};
+  EXPECT_EQ(ComputePreferredDirective(HeaderTU),
+Symbol::IncludeDirective::Import);
+
+  // ObjC language option is not enough for headers.
+  HeaderTU.Code = R"cpp(
+  #include "TestTU.h"
+  )cpp";
+  EXPECT_EQ(ComputePreferredDirective(HeaderTU),
+Symbol::IncludeDirective::Include);
+
+  HeaderTU.Code = R"cpp(
+  @interface Foo
+  @end
+
+  Foo * getFoo();
+  )cpp";
+  EXPECT_EQ(ComputePreferredDirective(HeaderTU),
+Symbol::IncludeDirective::Import);
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
===
--- clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
+++ clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
@@ -68,6 +68,7 @@
   Pair(sym("Y", index::SymbolKind::Variable, "@N@tar@S@X@FI@\\0").ID,
2),
   Pair(_ /*a*/, 3)));
+  EXPECT_EQ(Signals.InsertionDirective, 

[PATCH] D139446: [clangd] Add flag to control #import include insertions

2023-01-09 Thread David Goldman via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG814c0bb31660: [clangd] Add flag to control #import include 
insertions (authored by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139446/new/

https://reviews.llvm.org/D139446

Files:
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -264,6 +264,14 @@
 "Never insert #include directives as part of code completion")),
 };
 
+opt ImportInsertions{
+"import-insertions",
+cat(Features),
+desc("If header insertion is enabled, add #import directives when "
+ "accepting code completions or fixing includes in Objective-C code"),
+init(CodeCompleteOptions().ImportInsertions),
+};
+
 opt IncludeCleanerStdlib{
 "include-cleaner-stdlib",
 cat(Features),
@@ -913,6 +921,7 @@
 Opts.CodeComplete.BundleOverloads = CompletionStyle != Detailed;
   Opts.CodeComplete.ShowOrigins = ShowOrigins;
   Opts.CodeComplete.InsertIncludes = HeaderInsertion;
+  Opts.CodeComplete.ImportInsertions = ImportInsertions;
   if (!HeaderInsertionDecorators) {
 Opts.CodeComplete.IncludeIndicator.Insert.clear();
 Opts.CodeComplete.IncludeIndicator.NoInsert.clear();
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -70,6 +70,10 @@
 NeverInsert,
   } InsertIncludes = IncludeInsertion::IWYU;
 
+  /// Whether include insertions for Objective-C code should use #import 
instead
+  /// of #include.
+  bool ImportInsertions = false;
+
   /// A visual indicator to prepend to the completion label to indicate whether
   /// completion result would trigger an #include insertion or not.
   struct IncludeInsertionIndicator {


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -264,6 +264,14 @@
 "Never insert #include directives as part of code completion")),
 };
 
+opt ImportInsertions{
+"import-insertions",
+cat(Features),
+desc("If header insertion is enabled, add #import directives when "
+ "accepting code completions or fixing includes in Objective-C code"),
+init(CodeCompleteOptions().ImportInsertions),
+};
+
 opt IncludeCleanerStdlib{
 "include-cleaner-stdlib",
 cat(Features),
@@ -913,6 +921,7 @@
 Opts.CodeComplete.BundleOverloads = CompletionStyle != Detailed;
   Opts.CodeComplete.ShowOrigins = ShowOrigins;
   Opts.CodeComplete.InsertIncludes = HeaderInsertion;
+  Opts.CodeComplete.ImportInsertions = ImportInsertions;
   if (!HeaderInsertionDecorators) {
 Opts.CodeComplete.IncludeIndicator.Insert.clear();
 Opts.CodeComplete.IncludeIndicator.NoInsert.clear();
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -70,6 +70,10 @@
 NeverInsert,
   } InsertIncludes = IncludeInsertion::IWYU;
 
+  /// Whether include insertions for Objective-C code should use #import instead
+  /// of #include.
+  bool ImportInsertions = false;
+
   /// A visual indicator to prepend to the completion label to indicate whether
   /// completion result would trigger an #include insertion or not.
   struct IncludeInsertionIndicator {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D139458: [clangd] Full support for #import insertions

2023-01-05 Thread David Goldman via Phabricator via cfe-commits
dgoldman marked an inline comment as done.
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/ParsedAST.cpp:572
+  // case where a header file contains ObjC decls but no #imports.
+  Symbol::IncludeDirective Directive = preferredIncludeDirective(
+  Filename, Clang->getLangOpts(), MainFileIncludes, {});

kadircet wrote:
> as discussed offline can you guard this with the `import-insertion` flag as 
> well? we should pass it through ParseOptions.
Done, LMK if I did that properly.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139458/new/

https://reviews.llvm.org/D139458

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D139458: [clangd] Full support for #import insertions

2023-01-05 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 486706.
dgoldman added a comment.

Respect ImportInsertions flag in IncludeFixer


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139458/new/

https://reviews.llvm.org/D139458

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/ASTSignals.cpp
  clang-tools-extra/clangd/ASTSignals.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Compiler.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/ParsedAST.cpp
  clang-tools-extra/clangd/ParsedAST.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
  clang-tools-extra/clangd/unittests/ASTTests.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2718,17 +2718,21 @@
   Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
   Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000,
   Symbol::Include | Symbol::Import);
-
-  auto Results = completions("Fun^", {Sym}).Completions;
+  CodeCompleteOptions Opts;
+  // Should only take effect in import contexts.
+  Opts.ImportInsertions = true;
+  auto Results = completions("Fun^", {Sym}, Opts).Completions;
   assert(!Results.empty());
   EXPECT_THAT(Results[0],
   AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
 
-  Results = completions("Fun^", {Sym}, {}, "Foo.m").Completions;
+  ASTSignals Signals;
+  Signals.InsertionDirective = Symbol::IncludeDirective::Import;
+  Opts.MainFileSignals = 
+  Results = completions("Fun^", {Sym}, Opts, "Foo.m").Completions;
   assert(!Results.empty());
-  // TODO: Once #import integration support is done this should be #import.
   EXPECT_THAT(Results[0],
-  AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
+  AllOf(named("Func"), insertIncludeText("#import \"bar.h\"\n")));
 
   Sym.IncludeHeaders[0].SupportedDirectives = Symbol::Import;
   Results = completions("Fun^", {Sym}).Completions;
Index: clang-tools-extra/clangd/unittests/ASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ASTTests.cpp
@@ -11,6 +11,7 @@
 #include "Annotations.h"
 #include "ParsedAST.h"
 #include "TestTU.h"
+#include "index/Symbol.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
@@ -618,6 +619,45 @@
   hasReservedScope(*findUnqualifiedDecl(AST, "secret").getDeclContext()));
 }
 
+TEST(ClangdAST, PreferredIncludeDirective) {
+  auto ComputePreferredDirective = [](TestTU ) {
+auto AST = TU.build();
+return preferredIncludeDirective(AST.tuPath(), AST.getLangOpts(),
+ AST.getIncludeStructure().MainFileIncludes,
+ AST.getLocalTopLevelDecls());
+  };
+  TestTU ObjCTU = TestTU::withCode(R"cpp(
+  int main() {}
+  )cpp");
+  ObjCTU.Filename = "TestTU.m";
+  EXPECT_EQ(ComputePreferredDirective(ObjCTU),
+Symbol::IncludeDirective::Import);
+
+  TestTU HeaderTU = TestTU::withCode(R"cpp(
+  #import "TestTU.h"
+  )cpp");
+  HeaderTU.Filename = "TestTUHeader.h";
+  HeaderTU.ExtraArgs = {"-xobjective-c++-header"};
+  EXPECT_EQ(ComputePreferredDirective(HeaderTU),
+Symbol::IncludeDirective::Import);
+
+  // ObjC language option is not enough for headers.
+  HeaderTU.Code = R"cpp(
+  #include "TestTU.h"
+  )cpp";
+  EXPECT_EQ(ComputePreferredDirective(HeaderTU),
+Symbol::IncludeDirective::Include);
+
+  HeaderTU.Code = R"cpp(
+  @interface Foo
+  @end
+
+  Foo * getFoo();
+  )cpp";
+  EXPECT_EQ(ComputePreferredDirective(HeaderTU),
+Symbol::IncludeDirective::Import);
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
===
--- clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
+++ clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
@@ -68,6 +68,7 @@
   Pair(sym("Y", index::SymbolKind::Variable, "@N@tar@S@X@FI@\\0").ID,
2),
   Pair(_ /*a*/, 3)));
+  EXPECT_EQ(Signals.InsertionDirective, Symbol::IncludeDirective::Include);
 }
 } // namespace
 } // namespace clangd
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ 

[PATCH] D139446: [clangd] Add flag to control #import include insertions

2023-01-05 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 486700.
dgoldman marked 2 inline comments as done.
dgoldman added a comment.

Update comment + default value


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139446/new/

https://reviews.llvm.org/D139446

Files:
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -264,6 +264,14 @@
 "Never insert #include directives as part of code completion")),
 };
 
+opt ImportInsertions{
+"import-insertions",
+cat(Features),
+desc("If header insertion is enabled, add #import directives when "
+ "accepting code completions or fixing includes in Objective-C code"),
+init(CodeCompleteOptions().ImportInsertions),
+};
+
 opt IncludeCleanerStdlib{
 "include-cleaner-stdlib",
 cat(Features),
@@ -906,6 +914,7 @@
 Opts.CodeComplete.BundleOverloads = CompletionStyle != Detailed;
   Opts.CodeComplete.ShowOrigins = ShowOrigins;
   Opts.CodeComplete.InsertIncludes = HeaderInsertion;
+  Opts.CodeComplete.ImportInsertions = ImportInsertions;
   if (!HeaderInsertionDecorators) {
 Opts.CodeComplete.IncludeIndicator.Insert.clear();
 Opts.CodeComplete.IncludeIndicator.NoInsert.clear();
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -70,6 +70,10 @@
 NeverInsert,
   } InsertIncludes = IncludeInsertion::IWYU;
 
+  /// Whether include insertions for Objective-C code should use #import 
instead
+  /// of #include.
+  bool ImportInsertions = false;
+
   /// A visual indicator to prepend to the completion label to indicate whether
   /// completion result would trigger an #include insertion or not.
   struct IncludeInsertionIndicator {


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -264,6 +264,14 @@
 "Never insert #include directives as part of code completion")),
 };
 
+opt ImportInsertions{
+"import-insertions",
+cat(Features),
+desc("If header insertion is enabled, add #import directives when "
+ "accepting code completions or fixing includes in Objective-C code"),
+init(CodeCompleteOptions().ImportInsertions),
+};
+
 opt IncludeCleanerStdlib{
 "include-cleaner-stdlib",
 cat(Features),
@@ -906,6 +914,7 @@
 Opts.CodeComplete.BundleOverloads = CompletionStyle != Detailed;
   Opts.CodeComplete.ShowOrigins = ShowOrigins;
   Opts.CodeComplete.InsertIncludes = HeaderInsertion;
+  Opts.CodeComplete.ImportInsertions = ImportInsertions;
   if (!HeaderInsertionDecorators) {
 Opts.CodeComplete.IncludeIndicator.Insert.clear();
 Opts.CodeComplete.IncludeIndicator.NoInsert.clear();
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -70,6 +70,10 @@
 NeverInsert,
   } InsertIncludes = IncludeInsertion::IWYU;
 
+  /// Whether include insertions for Objective-C code should use #import instead
+  /// of #include.
+  bool ImportInsertions = false;
+
   /// A visual indicator to prepend to the completion label to indicate whether
   /// completion result would trigger an #include insertion or not.
   struct IncludeInsertionIndicator {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D139458: [clangd] Full support for #import insertions

2023-01-04 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 486291.
dgoldman marked 4 inline comments as done.
dgoldman added a comment.

Update comment + test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139458/new/

https://reviews.llvm.org/D139458

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/ASTSignals.cpp
  clang-tools-extra/clangd/ASTSignals.h
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/ParsedAST.cpp
  clang-tools-extra/clangd/ParsedAST.h
  clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
  clang-tools-extra/clangd/unittests/ASTTests.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2718,17 +2718,21 @@
   Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
   Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000,
   Symbol::Include | Symbol::Import);
-
-  auto Results = completions("Fun^", {Sym}).Completions;
+  CodeCompleteOptions Opts;
+  // Should only take effect in import contexts.
+  Opts.ImportInsertions = true;
+  auto Results = completions("Fun^", {Sym}, Opts).Completions;
   assert(!Results.empty());
   EXPECT_THAT(Results[0],
   AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
 
-  Results = completions("Fun^", {Sym}, {}, "Foo.m").Completions;
+  ASTSignals Signals;
+  Signals.InsertionDirective = Symbol::IncludeDirective::Import;
+  Opts.MainFileSignals = 
+  Results = completions("Fun^", {Sym}, Opts, "Foo.m").Completions;
   assert(!Results.empty());
-  // TODO: Once #import integration support is done this should be #import.
   EXPECT_THAT(Results[0],
-  AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
+  AllOf(named("Func"), insertIncludeText("#import \"bar.h\"\n")));
 
   Sym.IncludeHeaders[0].SupportedDirectives = Symbol::Import;
   Results = completions("Fun^", {Sym}).Completions;
Index: clang-tools-extra/clangd/unittests/ASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ASTTests.cpp
@@ -11,6 +11,7 @@
 #include "Annotations.h"
 #include "ParsedAST.h"
 #include "TestTU.h"
+#include "index/Symbol.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
@@ -618,6 +619,45 @@
   hasReservedScope(*findUnqualifiedDecl(AST, "secret").getDeclContext()));
 }
 
+TEST(ClangdAST, PreferredIncludeDirective) {
+  auto ComputePreferredDirective = [](TestTU ) {
+auto AST = TU.build();
+return preferredIncludeDirective(AST.tuPath(), AST.getLangOpts(),
+ AST.getIncludeStructure().MainFileIncludes,
+ AST.getLocalTopLevelDecls());
+  };
+  TestTU ObjCTU = TestTU::withCode(R"cpp(
+  int main() {}
+  )cpp");
+  ObjCTU.Filename = "TestTU.m";
+  EXPECT_EQ(ComputePreferredDirective(ObjCTU),
+Symbol::IncludeDirective::Import);
+
+  TestTU HeaderTU = TestTU::withCode(R"cpp(
+  #import "TestTU.h"
+  )cpp");
+  HeaderTU.Filename = "TestTUHeader.h";
+  HeaderTU.ExtraArgs = {"-xobjective-c++-header"};
+  EXPECT_EQ(ComputePreferredDirective(HeaderTU),
+Symbol::IncludeDirective::Import);
+
+  // ObjC language option is not enough for headers.
+  HeaderTU.Code = R"cpp(
+  #include "TestTU.h"
+  )cpp";
+  EXPECT_EQ(ComputePreferredDirective(HeaderTU),
+Symbol::IncludeDirective::Include);
+
+  HeaderTU.Code = R"cpp(
+  @interface Foo
+  @end
+
+  Foo * getFoo();
+  )cpp";
+  EXPECT_EQ(ComputePreferredDirective(HeaderTU),
+Symbol::IncludeDirective::Import);
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
===
--- clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
+++ clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
@@ -68,6 +68,7 @@
   Pair(sym("Y", index::SymbolKind::Variable, "@N@tar@S@X@FI@\\0").ID,
2),
   Pair(_ /*a*/, 3)));
+  EXPECT_EQ(Signals.InsertionDirective, Symbol::IncludeDirective::Include);
 }
 } // namespace
 } // namespace clangd
Index: clang-tools-extra/clangd/ParsedAST.h
===
--- clang-tools-extra/clangd/ParsedAST.h
+++ clang-tools-extra/clangd/ParsedAST.h
@@ -86,6 +86,7 @@
   /// The result does not include the decls that come from the preamble.
   /// (These should be const, but RecursiveASTVisitor 

[PATCH] D139458: [clangd] Full support for #import insertions

2023-01-03 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/ParsedAST.h:88
   /// (These should be const, but RecursiveASTVisitor requires Decl*).
-  ArrayRef getLocalTopLevelDecls();
+  ArrayRef getLocalTopLevelDecls() const;
 

kadircet wrote:
> can you rather introduce a new overload that returns `ArrayRef`
Did you mean an overload with `ArrayRef getLocalTopLevelDecls() 
const;`? ASTSignals gets a const ParsedAST &, unless you want me to const cast 
instead?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139458/new/

https://reviews.llvm.org/D139458

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D139458: [clangd] Full support for #import insertions

2023-01-03 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 486111.
dgoldman marked 7 inline comments as done.
dgoldman added a comment.

Minor fixes for review, moving stuff around


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139458/new/

https://reviews.llvm.org/D139458

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/ASTSignals.cpp
  clang-tools-extra/clangd/ASTSignals.h
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/ParsedAST.cpp
  clang-tools-extra/clangd/ParsedAST.h
  clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
  clang-tools-extra/clangd/unittests/ASTTests.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2718,17 +2718,21 @@
   Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
   Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000,
   Symbol::Include | Symbol::Import);
-
-  auto Results = completions("Fun^", {Sym}).Completions;
+  CodeCompleteOptions Opts;
+  // Should only take effect in import contexts.
+  Opts.ImportInsertions = true;
+  auto Results = completions("Fun^", {Sym}, Opts).Completions;
   assert(!Results.empty());
   EXPECT_THAT(Results[0],
   AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
 
-  Results = completions("Fun^", {Sym}, {}, "Foo.m").Completions;
+  ASTSignals Signals;
+  Signals.InsertionDirective = Symbol::IncludeDirective::Import;
+  Opts.MainFileSignals = 
+  Results = completions("Fun^", {Sym}, Opts, "Foo.m").Completions;
   assert(!Results.empty());
-  // TODO: Once #import integration support is done this should be #import.
   EXPECT_THAT(Results[0],
-  AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
+  AllOf(named("Func"), insertIncludeText("#import \"bar.h\"\n")));
 
   Sym.IncludeHeaders[0].SupportedDirectives = Symbol::Import;
   Results = completions("Fun^", {Sym}).Completions;
Index: clang-tools-extra/clangd/unittests/ASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ASTTests.cpp
@@ -11,6 +11,7 @@
 #include "Annotations.h"
 #include "ParsedAST.h"
 #include "TestTU.h"
+#include "index/Symbol.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
@@ -618,6 +619,46 @@
   hasReservedScope(*findUnqualifiedDecl(AST, "secret").getDeclContext()));
 }
 
+Symbol::IncludeDirective preferredIncludeDirective(TestTU ) {
+  auto AST = TU.build();
+  return preferredIncludeDirective(AST.tuPath(), AST.getLangOpts(),
+   AST.getIncludeStructure().MainFileIncludes,
+   AST.getLocalTopLevelDecls());
+}
+
+TEST(ClangdAST, PreferredIncludeDirective) {
+  TestTU ObjCTU = TestTU::withCode(R"cpp(
+  int main() {}
+  )cpp");
+  ObjCTU.Filename = "TestTU.m";
+  EXPECT_EQ(preferredIncludeDirective(ObjCTU),
+Symbol::IncludeDirective::Import);
+
+  TestTU HeaderTU = TestTU::withCode(R"cpp(
+  #import "TestTU.h"
+  )cpp");
+  HeaderTU.Filename = "TestTUHeader.h";
+  HeaderTU.ExtraArgs = {"-xobjective-c++-header"};
+  EXPECT_EQ(preferredIncludeDirective(HeaderTU),
+Symbol::IncludeDirective::Import);
+
+  // ObjC language option is not enough for headers.
+  HeaderTU.Code = R"cpp(
+  #include "TestTU.h"
+  )cpp";
+  EXPECT_EQ(preferredIncludeDirective(HeaderTU),
+Symbol::IncludeDirective::Include);
+
+  HeaderTU.Code = R"cpp(
+  @interface Foo
+  @end
+
+  Foo * getFoo();
+  )cpp";
+  EXPECT_EQ(preferredIncludeDirective(HeaderTU),
+Symbol::IncludeDirective::Import);
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
===
--- clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
+++ clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
@@ -68,6 +68,7 @@
   Pair(sym("Y", index::SymbolKind::Variable, "@N@tar@S@X@FI@\\0").ID,
2),
   Pair(_ /*a*/, 3)));
+  EXPECT_EQ(Signals.InsertionDirective, Symbol::IncludeDirective::Include);
 }
 } // namespace
 } // namespace clangd
Index: clang-tools-extra/clangd/ParsedAST.h
===
--- clang-tools-extra/clangd/ParsedAST.h
+++ clang-tools-extra/clangd/ParsedAST.h
@@ -85,7 +85,7 @@
   /// This function returns top-level decls present in the main file of the AST.
   /// The result does 

[PATCH] D139458: [clangd] Full support for #import insertions

2022-12-15 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 483205.
dgoldman added a comment.

Don't pass ASTSignals through ParsedAST


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139458/new/

https://reviews.llvm.org/D139458

Files:
  clang-tools-extra/clangd/ASTSignals.cpp
  clang-tools-extra/clangd/ASTSignals.h
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/ParsedAST.cpp
  clang-tools-extra/clangd/ParsedAST.h
  clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2718,17 +2718,21 @@
   Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
   Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000,
   Symbol::Include | Symbol::Import);
-
-  auto Results = completions("Fun^", {Sym}).Completions;
+  CodeCompleteOptions Opts;
+  // Should only take effect in import contexts.
+  Opts.ImportInsertions = true;
+  auto Results = completions("Fun^", {Sym}, Opts).Completions;
   assert(!Results.empty());
   EXPECT_THAT(Results[0],
   AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
 
-  Results = completions("Fun^", {Sym}, {}, "Foo.m").Completions;
+  ASTSignals Signals;
+  Signals.InsertionDirective = Symbol::IncludeDirective::Import;
+  Opts.MainFileSignals = 
+  Results = completions("Fun^", {Sym}, Opts, "Foo.m").Completions;
   assert(!Results.empty());
-  // TODO: Once #import integration support is done this should be #import.
   EXPECT_THAT(Results[0],
-  AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
+  AllOf(named("Func"), insertIncludeText("#import \"bar.h\"\n")));
 
   Sym.IncludeHeaders[0].SupportedDirectives = Symbol::Import;
   Results = completions("Fun^", {Sym}).Completions;
Index: clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
===
--- clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
+++ clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
@@ -68,7 +68,44 @@
   Pair(sym("Y", index::SymbolKind::Variable, "@N@tar@S@X@FI@\\0").ID,
2),
   Pair(_ /*a*/, 3)));
+  EXPECT_EQ(Signals.InsertionDirective, Symbol::IncludeDirective::Include);
 }
+
+TEST(ASTSignals, DeriveInsertionDirective) {
+  TestTU ObjCTU = TestTU::withCode(R"cpp(
+  int main() {}
+  )cpp");
+  ObjCTU.Filename = "TestTU.m";
+  ASTSignals Signals = ASTSignals::derive(ObjCTU.build());
+  EXPECT_EQ(Signals.InsertionDirective, Symbol::IncludeDirective::Import);
+
+  TestTU HeaderTU = TestTU::withCode(R"cpp(
+  #import "TestTU.h"
+  )cpp");
+  HeaderTU.Filename = "TestTUHeader.h";
+  HeaderTU.ExtraArgs = {"-xobjective-c++-header"};
+  Signals = ASTSignals::derive(HeaderTU.build());
+  EXPECT_EQ(Signals.InsertionDirective, Symbol::IncludeDirective::Import);
+
+  // ObjC language option is not enough for headers.
+  HeaderTU.Code = R"cpp(
+  #include "TestTU.h"
+  )cpp";
+  Signals = ASTSignals::derive(HeaderTU.build());
+  EXPECT_EQ(Signals.InsertionDirective, Symbol::IncludeDirective::Include);
+
+  HeaderTU.Code = R"cpp(
+  #include "TestTU.h"
+
+  @interface Foo
+  @end
+
+  Foo * getFoo();
+  )cpp";
+  Signals = ASTSignals::derive(HeaderTU.build());
+  EXPECT_EQ(Signals.InsertionDirective, Symbol::IncludeDirective::Import);
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/ParsedAST.h
===
--- clang-tools-extra/clangd/ParsedAST.h
+++ clang-tools-extra/clangd/ParsedAST.h
@@ -85,7 +85,7 @@
   /// This function returns top-level decls present in the main file of the AST.
   /// The result does not include the decls that come from the preamble.
   /// (These should be const, but RecursiveASTVisitor requires Decl*).
-  ArrayRef getLocalTopLevelDecls();
+  ArrayRef getLocalTopLevelDecls() const;
 
   const llvm::Optional> () const {
 return Diags;
Index: clang-tools-extra/clangd/ParsedAST.cpp
===
--- clang-tools-extra/clangd/ParsedAST.cpp
+++ clang-tools-extra/clangd/ParsedAST.cpp
@@ -11,6 +11,7 @@
 #include "../clang-tidy/ClangTidyDiagnosticConsumer.h"
 #include "../clang-tidy/ClangTidyModuleRegistry.h"
 #include "AST.h"
+#include "ASTSignals.h"
 #include "Compiler.h"
 #include "Config.h"
 #include "Diagnostics.h"
@@ -25,6 +26,7 @@
 #include "TidyProvider.h"
 #include "index/CanonicalIncludes.h"
 #include "index/Index.h"
+#include "index/Symbol.h"
 #include "support/Logger.h"
 #include "support/Trace.h"
 #include 

[PATCH] D139458: [clangd] Full support for #import insertions

2022-12-14 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 482950.
dgoldman marked 5 inline comments as done.
dgoldman added a comment.

Fixes for review


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139458/new/

https://reviews.llvm.org/D139458

Files:
  clang-tools-extra/clangd/ASTSignals.cpp
  clang-tools-extra/clangd/ASTSignals.h
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/ParsedAST.cpp
  clang-tools-extra/clangd/ParsedAST.h
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/tool/Check.cpp
  clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
  clang-tools-extra/clangd/unittests/PreambleTests.cpp
  clang-tools-extra/clangd/unittests/TestTU.cpp
  clang-tools-extra/clangd/unittests/TestTU.h

Index: clang-tools-extra/clangd/unittests/TestTU.h
===
--- clang-tools-extra/clangd/unittests/TestTU.h
+++ clang-tools-extra/clangd/unittests/TestTU.h
@@ -18,6 +18,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_TESTTU_H
 
 #include "../TidyProvider.h"
+#include "ASTSignals.h"
 #include "Compiler.h"
 #include "FeatureModule.h"
 #include "ParsedAST.h"
@@ -72,6 +73,9 @@
   // Parse options pass on to the ParseInputs
   ParseOptions ParseOpts = {};
 
+  // ASTSignals to use. Must be manually set.
+  std::shared_ptr Signals;
+
   // Whether to use overlay the TestFS over the real filesystem. This is
   // required for use of implicit modules.where the module file is written to
   // disk and later read back.
Index: clang-tools-extra/clangd/unittests/TestTU.cpp
===
--- clang-tools-extra/clangd/unittests/TestTU.cpp
+++ clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -127,7 +127,7 @@
/*StoreInMemory=*/true,
/*PreambleCallback=*/nullptr);
   auto AST = ParsedAST::build(testPath(Filename), Inputs, std::move(CI),
-  Diags.take(), Preamble);
+  Diags.take(), Preamble, Signals);
   if (!AST) {
 llvm::errs() << "Failed to build code:\n" << Code;
 std::abort();
Index: clang-tools-extra/clangd/unittests/PreambleTests.cpp
===
--- clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -206,7 +206,7 @@
 return std::nullopt;
   }
   return ParsedAST::build(testPath(TU.Filename), TU.inputs(FS), std::move(CI),
-  {}, BaselinePreamble);
+  {}, BaselinePreamble, {});
 }
 
 std::string getPreamblePatch(llvm::StringRef Baseline,
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -505,7 +505,7 @@
   TU.Code = ModifiedContents.str();
   Inputs = TU.inputs(FS);
   auto PatchedAST = ParsedAST::build(testPath("foo.cpp"), Inputs, std::move(CI),
- {}, EmptyPreamble);
+ {}, EmptyPreamble, {});
   ASSERT_TRUE(PatchedAST);
   ASSERT_FALSE(PatchedAST->getDiagnostics());
 
@@ -550,7 +550,7 @@
   TU.Code = "";
   Inputs = TU.inputs(FS);
   auto PatchedAST = ParsedAST::build(testPath("foo.cpp"), Inputs, std::move(CI),
- {}, BaselinePreamble);
+ {}, BaselinePreamble, {});
   ASSERT_TRUE(PatchedAST);
 
   // Ensure source location information is correct.
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2718,17 +2718,21 @@
   Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();
   Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000,
   Symbol::Include | Symbol::Import);
-
-  auto Results = completions("Fun^", {Sym}).Completions;
+  CodeCompleteOptions Opts;
+  // Should only take effect in import contexts.
+  Opts.ImportInsertions = true;
+  auto Results = completions("Fun^", {Sym}, Opts).Completions;
   assert(!Results.empty());
   EXPECT_THAT(Results[0],
   AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
 
-  Results = completions("Fun^", {Sym}, {}, "Foo.m").Completions;
+  ASTSignals Signals;
+  Signals.InsertionDirective = Symbol::IncludeDirective::Import;
+  Opts.MainFileSignals = 
+  Results = completions("Fun^", {Sym}, 

[PATCH] D139458: [clangd] Full support for #import insertions

2022-12-07 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 481022.
dgoldman added a comment.

Add tests


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139458/new/

https://reviews.llvm.org/D139458

Files:
  clang-tools-extra/clangd/ASTSignals.cpp
  clang-tools-extra/clangd/ASTSignals.h
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/ParsedAST.cpp
  clang-tools-extra/clangd/ParsedAST.h
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/tool/Check.cpp
  clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
  clang-tools-extra/clangd/unittests/PreambleTests.cpp
  clang-tools-extra/clangd/unittests/TestTU.cpp
  clang-tools-extra/clangd/unittests/TestTU.h

Index: clang-tools-extra/clangd/unittests/TestTU.h
===
--- clang-tools-extra/clangd/unittests/TestTU.h
+++ clang-tools-extra/clangd/unittests/TestTU.h
@@ -18,6 +18,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_TESTTU_H
 
 #include "../TidyProvider.h"
+#include "ASTSignals.h"
 #include "Compiler.h"
 #include "FeatureModule.h"
 #include "ParsedAST.h"
@@ -72,6 +73,9 @@
   // Parse options pass on to the ParseInputs
   ParseOptions ParseOpts = {};
 
+  // ASTSignals to use. Must be manually set.
+  std::shared_ptr Signals;
+
   // Whether to use overlay the TestFS over the real filesystem. This is
   // required for use of implicit modules.where the module file is written to
   // disk and later read back.
Index: clang-tools-extra/clangd/unittests/TestTU.cpp
===
--- clang-tools-extra/clangd/unittests/TestTU.cpp
+++ clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -127,7 +127,7 @@
/*StoreInMemory=*/true,
/*PreambleCallback=*/nullptr);
   auto AST = ParsedAST::build(testPath(Filename), Inputs, std::move(CI),
-  Diags.take(), Preamble);
+  Diags.take(), Preamble, Signals);
   if (!AST) {
 llvm::errs() << "Failed to build code:\n" << Code;
 std::abort();
Index: clang-tools-extra/clangd/unittests/PreambleTests.cpp
===
--- clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -206,7 +206,7 @@
 return std::nullopt;
   }
   return ParsedAST::build(testPath(TU.Filename), TU.inputs(FS), std::move(CI),
-  {}, BaselinePreamble);
+  {}, BaselinePreamble, {});
 }
 
 std::string getPreamblePatch(llvm::StringRef Baseline,
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -505,7 +505,7 @@
   TU.Code = ModifiedContents.str();
   Inputs = TU.inputs(FS);
   auto PatchedAST = ParsedAST::build(testPath("foo.cpp"), Inputs, std::move(CI),
- {}, EmptyPreamble);
+ {}, EmptyPreamble, {});
   ASSERT_TRUE(PatchedAST);
   ASSERT_FALSE(PatchedAST->getDiagnostics());
 
@@ -550,7 +550,7 @@
   TU.Code = "";
   Inputs = TU.inputs(FS);
   auto PatchedAST = ParsedAST::build(testPath("foo.cpp"), Inputs, std::move(CI),
- {}, BaselinePreamble);
+ {}, BaselinePreamble, {});
   ASSERT_TRUE(PatchedAST);
 
   // Ensure source location information is correct.
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2724,11 +2724,15 @@
   EXPECT_THAT(Results[0],
   AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
 
-  Results = completions("Fun^", {Sym}, {}, "Foo.m").Completions;
+  CodeCompleteOptions Opts;
+  Opts.ImportInsertions = true;
+  ASTSignals Signals;
+  Signals.InsertionDirective = Symbol::IncludeDirective::Import;
+  Opts.MainFileSignals = 
+  Results = completions("Fun^", {Sym}, Opts, "Foo.m").Completions;
   assert(!Results.empty());
-  // TODO: Once #import integration support is done this should be #import.
   EXPECT_THAT(Results[0],
-  AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));
+  AllOf(named("Func"), insertIncludeText("#import \"bar.h\"\n")));
 
   Sym.IncludeHeaders[0].SupportedDirectives = Symbol::Import;
   Results = completions("Fun^", 

[PATCH] D139458: [clangd] Full support for #import insertions

2022-12-06 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
Herald added subscribers: kadircet, arphaman, javed.absar.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

These are still disabled by default, but will work in ObjC code if you
enable the `-import-insertions` flag.

This requires ASTSignals to be available; before ASTSignals are
available, we will always use #include. Once they are available, the
behavior varies as follows:

- For source files, use #import if the ObjC language flag is enabled
- For header files:
  - If the ObjC language flag is disabled, use #include
  - If the header file contains any #imports, use #import
  - If the header file references any ObjC decls, use #import
  - Otherwise, use #include


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D139458

Files:
  clang-tools-extra/clangd/ASTSignals.cpp
  clang-tools-extra/clangd/ASTSignals.h
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/ParsedAST.cpp
  clang-tools-extra/clangd/ParsedAST.h
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/tool/Check.cpp
  clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
  clang-tools-extra/clangd/unittests/PreambleTests.cpp
  clang-tools-extra/clangd/unittests/TestTU.cpp
  clang-tools-extra/clangd/unittests/TestTU.h

Index: clang-tools-extra/clangd/unittests/TestTU.h
===
--- clang-tools-extra/clangd/unittests/TestTU.h
+++ clang-tools-extra/clangd/unittests/TestTU.h
@@ -18,6 +18,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_TESTTU_H
 
 #include "../TidyProvider.h"
+#include "ASTSignals.h"
 #include "Compiler.h"
 #include "FeatureModule.h"
 #include "ParsedAST.h"
@@ -72,6 +73,9 @@
   // Parse options pass on to the ParseInputs
   ParseOptions ParseOpts = {};
 
+  // ASTSignals to use. Must be manually set.
+  std::shared_ptr Signals;
+
   // Whether to use overlay the TestFS over the real filesystem. This is
   // required for use of implicit modules.where the module file is written to
   // disk and later read back.
Index: clang-tools-extra/clangd/unittests/TestTU.cpp
===
--- clang-tools-extra/clangd/unittests/TestTU.cpp
+++ clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -127,7 +127,7 @@
/*StoreInMemory=*/true,
/*PreambleCallback=*/nullptr);
   auto AST = ParsedAST::build(testPath(Filename), Inputs, std::move(CI),
-  Diags.take(), Preamble);
+  Diags.take(), Preamble, Signals);
   if (!AST) {
 llvm::errs() << "Failed to build code:\n" << Code;
 std::abort();
Index: clang-tools-extra/clangd/unittests/PreambleTests.cpp
===
--- clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -206,7 +206,7 @@
 return std::nullopt;
   }
   return ParsedAST::build(testPath(TU.Filename), TU.inputs(FS), std::move(CI),
-  {}, BaselinePreamble);
+  {}, BaselinePreamble, {});
 }
 
 std::string getPreamblePatch(llvm::StringRef Baseline,
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -505,7 +505,7 @@
   TU.Code = ModifiedContents.str();
   Inputs = TU.inputs(FS);
   auto PatchedAST = ParsedAST::build(testPath("foo.cpp"), Inputs, std::move(CI),
- {}, EmptyPreamble);
+ {}, EmptyPreamble, {});
   ASSERT_TRUE(PatchedAST);
   ASSERT_FALSE(PatchedAST->getDiagnostics());
 
@@ -550,7 +550,7 @@
   TU.Code = "";
   Inputs = TU.inputs(FS);
   auto PatchedAST = ParsedAST::build(testPath("foo.cpp"), Inputs, std::move(CI),
- {}, BaselinePreamble);
+ {}, BaselinePreamble, {});
   ASSERT_TRUE(PatchedAST);
 
   // Ensure source location information is correct.
Index: clang-tools-extra/clangd/tool/Check.cpp
===
--- clang-tools-extra/clangd/tool/Check.cpp
+++ clang-tools-extra/clangd/tool/Check.cpp
@@ -223,7 +223,8 @@
 
 log("Building AST...");
 AST = ParsedAST::build(File, Inputs, std::move(Invocation),
-   /*InvocationDiags=*/std::vector{}, Preamble);
+   /*InvocationDiags=*/std::vector{}, Preamble,
+   /*Signals=*/{});
 if (!AST) {
   

[PATCH] D139446: [clangd] Add flag to control #import include insertions

2022-12-06 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

This will be disabled by default, hopefully we can enable for the next
major release.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D139446

Files:
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -264,6 +264,14 @@
 "Never insert #include directives as part of code completion")),
 };
 
+opt ImportInsertions{
+"import-insertions",
+cat(Features),
+desc("If header insertion is enabled, add #import directives when "
+ "accepting code completions in Objective-C code"),
+init(false),
+};
+
 opt IncludeCleanerStdlib{
 "include-cleaner-stdlib",
 cat(Features),
@@ -906,6 +914,7 @@
 Opts.CodeComplete.BundleOverloads = CompletionStyle != Detailed;
   Opts.CodeComplete.ShowOrigins = ShowOrigins;
   Opts.CodeComplete.InsertIncludes = HeaderInsertion;
+  Opts.CodeComplete.ImportInsertions = ImportInsertions;
   if (!HeaderInsertionDecorators) {
 Opts.CodeComplete.IncludeIndicator.Insert.clear();
 Opts.CodeComplete.IncludeIndicator.NoInsert.clear();
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -70,6 +70,10 @@
 NeverInsert,
   } InsertIncludes = IncludeInsertion::IWYU;
 
+  /// Whether include insertions for Objective-C code should use #import 
instead
+  /// of #include.
+  bool ImportInsertions = false;
+
   /// A visual indicator to prepend to the completion label to indicate whether
   /// completion result would trigger an #include insertion or not.
   struct IncludeInsertionIndicator {


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -264,6 +264,14 @@
 "Never insert #include directives as part of code completion")),
 };
 
+opt ImportInsertions{
+"import-insertions",
+cat(Features),
+desc("If header insertion is enabled, add #import directives when "
+ "accepting code completions in Objective-C code"),
+init(false),
+};
+
 opt IncludeCleanerStdlib{
 "include-cleaner-stdlib",
 cat(Features),
@@ -906,6 +914,7 @@
 Opts.CodeComplete.BundleOverloads = CompletionStyle != Detailed;
   Opts.CodeComplete.ShowOrigins = ShowOrigins;
   Opts.CodeComplete.InsertIncludes = HeaderInsertion;
+  Opts.CodeComplete.ImportInsertions = ImportInsertions;
   if (!HeaderInsertionDecorators) {
 Opts.CodeComplete.IncludeIndicator.Insert.clear();
 Opts.CodeComplete.IncludeIndicator.NoInsert.clear();
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -70,6 +70,10 @@
 NeverInsert,
   } InsertIncludes = IncludeInsertion::IWYU;
 
+  /// Whether include insertions for Objective-C code should use #import instead
+  /// of #include.
+  bool ImportInsertions = false;
+
   /// A visual indicator to prepend to the completion label to indicate whether
   /// completion result would trigger an #include insertion or not.
   struct IncludeInsertionIndicator {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128677: [clang][Tooling] Add support for generating #import edits

2022-12-06 Thread David Goldman via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGfc46d6e67fab: [clang][Tooling] Add support for generating 
#import edits (authored by dgoldman).

Changed prior to commit:
  https://reviews.llvm.org/D128677?vs=480524=480547#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128677/new/

https://reviews.llvm.org/D128677

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/unittests/HeadersTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Format/Format.cpp
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Tooling/HeaderIncludesTest.cpp

Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -20,10 +20,12 @@
 
 class HeaderIncludesTest : public ::testing::Test {
 protected:
-  std::string insert(llvm::StringRef Code, llvm::StringRef Header) {
+  std::string insert(llvm::StringRef Code, llvm::StringRef Header,
+ IncludeDirective Directive = IncludeDirective::Include) {
 HeaderIncludes Includes(FileName, Code, Style);
 assert(Header.startswith("\"") || Header.startswith("<"));
-auto R = Includes.insert(Header.trim("\"<>"), Header.startswith("<"));
+auto R =
+Includes.insert(Header.trim("\"<>"), Header.startswith("<"), Directive);
 if (!R)
   return std::string(Code);
 auto Result = applyAllReplacements(Code, Replacements(*R));
@@ -60,6 +62,25 @@
   EXPECT_EQ(Expected, insert(Code, "\"a2.h\""));
 }
 
+TEST_F(HeaderIncludesTest, InsertImportWithSameInclude) {
+  std::string Code = "#include \"a.h\"\n";
+  std::string Expected = Code + "#import \"a.h\"\n";
+  EXPECT_EQ(Expected, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
+TEST_F(HeaderIncludesTest, DontInsertAlreadyImported) {
+  std::string Code = "#import \"a.h\"\n";
+  EXPECT_EQ(Code, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
+TEST_F(HeaderIncludesTest, DeleteImportAndSameInclude) {
+  std::string Code = R"cpp(
+#include 
+#import 
+int x;)cpp";
+  EXPECT_EQ("\nint x;", remove(Code, ""));
+}
+
 TEST_F(HeaderIncludesTest, NoExistingIncludeWithDefine) {
   std::string Code = "#ifndef A_H\n"
  "#define A_H\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -296,7 +296,9 @@
   addExistingInclude(
   Include(Matches[2],
   tooling::Range(
-  Offset, std::min(Line.size() + 1, Code.size() - Offset))),
+  Offset, std::min(Line.size() + 1, Code.size() - Offset)),
+  Matches[1] == "import" ? tooling::IncludeDirective::Import
+ : tooling::IncludeDirective::Include),
   NextLineOffset);
 }
 Offset = NextLineOffset;
@@ -342,17 +344,20 @@
 }
 
 llvm::Optional
-HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
+HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled,
+   IncludeDirective Directive) const {
   assert(IncludeName == trimInclude(IncludeName));
   // If a  ("header") already exists in code, "header" () with
-  // different quotation will still be inserted.
+  // different quotation and/or directive will still be inserted.
   // FIXME: figure out if this is the best behavior.
   auto It = ExistingIncludes.find(IncludeName);
-  if (It != ExistingIncludes.end())
+  if (It != ExistingIncludes.end()) {
 for (const auto  : It->second)
-  if ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
-  (!IsAngled && StringRef(Inc.Name).startswith("\"")))
+  if (Inc.Directive == Directive &&
+  ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
+   (!IsAngled && StringRef(Inc.Name).startswith("\""
 return std::nullopt;
+  }
   std::string Quoted =
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
   StringRef QuotedName = Quoted;
@@ -371,8 +376,10 @@
 }
   }
   assert(InsertOffset <= Code.size());
+  llvm::StringRef DirectiveSpelling =
+  Directive == IncludeDirective::Include ? "include" : "import";
   std::string NewInclude =
-  std::string(llvm::formatv("#include {0}\n", QuotedName));
+  llvm::formatv("#{0} {1}\n", DirectiveSpelling, QuotedName);
   // When inserting headers at end of the code, also append '\n' to the code
   // if it does not end with '\n'.
  

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-12-06 Thread David Goldman via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG51f1ae52b0c9: [clangd] Add new IncludeDirective to 
IncludeHeaderWithReferences (authored by dgoldman).

Changed prior to commit:
  https://reviews.llvm.org/D128457?vs=480513=480546#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderAnalysis.h
  clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
  clang/unittests/Tooling/HeaderAnalysisTest.cpp

Index: clang/unittests/Tooling/HeaderAnalysisTest.cpp
===
--- clang/unittests/Tooling/HeaderAnalysisTest.cpp
+++ clang/unittests/Tooling/HeaderAnalysisTest.cpp
@@ -56,11 +56,42 @@
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("headerguard.h").get(), SM, HI));
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("pragmaonce.h").get(), SM, HI));
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("imported.h").get(), SM, HI));
+  EXPECT_TRUE(
+  isSelfContainedHeader(SM.getFileEntryForID(SM.getMainFileID()), SM, HI));
 
   EXPECT_FALSE(isSelfContainedHeader(FM.getFile("unguarded.h").get(), SM, HI));
   EXPECT_FALSE(isSelfContainedHeader(FM.getFile("bad.h").get(), SM, HI));
 }
 
+TEST(HeaderAnalysisTest, CodeContainsImports) {
+  EXPECT_TRUE(codeContainsImports(R"cpp(
+  #include "foo.h"
+  #import "NSFoo.h"
+
+  int main() {
+foo();
+  }
+  )cpp"));
+
+  EXPECT_TRUE(codeContainsImports(R"cpp(
+  #include "foo.h"
+
+  int main() {
+foo();
+  }
+
+  #import "NSFoo.h"
+  )cpp"));
+
+  EXPECT_FALSE(codeContainsImports(R"cpp(
+  #include "foo.h"
+
+  int main() {
+foo();
+  }
+  )cpp"));
+}
+
 TEST(HeaderAnalysisTest, ParseIWYUPragma) {
   EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep"), ValueIs(Eq("keep")));
   EXPECT_THAT(parseIWYUPragma("// IWYU pragma:   keep  me\netc"),
Index: clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
+++ clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
@@ -37,8 +37,7 @@
 }
 
 // Heuristically headers that only want to be included via an umbrella.
-bool isDontIncludeMeHeader(llvm::MemoryBufferRef Buffer) {
-  StringRef Content = Buffer.getBuffer();
+bool isDontIncludeMeHeader(StringRef Content) {
   llvm::StringRef Line;
   // Only sniff up to 100 lines or 10KB.
   Content = Content.take_front(100 * 100);
@@ -50,19 +49,48 @@
   return false;
 }
 
+bool isImportLine(llvm::StringRef Line) {
+  Line = Line.ltrim();
+  if (!Line.consume_front("#"))
+return false;
+  Line = Line.ltrim();
+  return Line.startswith("import");
+}
+
+llvm::StringRef getFileContents(const FileEntry *FE, const SourceManager ) {
+  return const_cast(SM)
+  .getMemoryBufferForFileOrNone(FE)
+  .value_or(llvm::MemoryBufferRef())
+  .getBuffer();
+}
+
 } // namespace
 
 bool isSelfContainedHeader(const FileEntry *FE, const SourceManager ,
HeaderSearch ) {
   assert(FE);
   if (!HeaderInfo.isFileMultipleIncludeGuarded(FE) &&
-  !HeaderInfo.hasFileBeenImported(FE))
+  !HeaderInfo.hasFileBeenImported(FE) &&
+  // Any header that contains #imports is supposed to be #import'd so no
+  // need to check for anything but the main-file.
+  (SM.getFileEntryForID(SM.getMainFileID()) != FE ||
+   !codeContainsImports(getFileContents(FE, SM
 return false;
   // This pattern indicates that a header can't be used without
   // particular preprocessor state, usually set up by another header.
-  return !isDontIncludeMeHeader(
-  const_cast(SM).getMemoryBufferForFileOrNone(FE).value_or(
-  llvm::MemoryBufferRef()));
+  return !isDontIncludeMeHeader(getFileContents(FE, SM));
+}
+
+bool codeContainsImports(llvm::StringRef Code) {
+  // Only sniff up to 100 lines or 10KB.
+  Code = Code.take_front(100 * 100);
+  llvm::StringRef Line;
+  for (unsigned I = 0; I < 100 && 

[PATCH] D128677: [clang][Tooling] Add support for generating #import edits

2022-12-06 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 480524.
dgoldman marked 2 inline comments as done.
dgoldman added a comment.

Use raw string literal


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128677/new/

https://reviews.llvm.org/D128677

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/unittests/HeadersTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Format/Format.cpp
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Tooling/HeaderIncludesTest.cpp

Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -20,10 +20,12 @@
 
 class HeaderIncludesTest : public ::testing::Test {
 protected:
-  std::string insert(llvm::StringRef Code, llvm::StringRef Header) {
+  std::string insert(llvm::StringRef Code, llvm::StringRef Header,
+ IncludeDirective Directive = IncludeDirective::Include) {
 HeaderIncludes Includes(FileName, Code, Style);
 assert(Header.startswith("\"") || Header.startswith("<"));
-auto R = Includes.insert(Header.trim("\"<>"), Header.startswith("<"));
+auto R =
+Includes.insert(Header.trim("\"<>"), Header.startswith("<"), Directive);
 if (!R)
   return std::string(Code);
 auto Result = applyAllReplacements(Code, Replacements(*R));
@@ -60,6 +62,25 @@
   EXPECT_EQ(Expected, insert(Code, "\"a2.h\""));
 }
 
+TEST_F(HeaderIncludesTest, InsertImportWithSameInclude) {
+  std::string Code = "#include \"a.h\"\n";
+  std::string Expected = Code + "#import \"a.h\"\n";
+  EXPECT_EQ(Expected, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
+TEST_F(HeaderIncludesTest, DontInsertAlreadyImported) {
+  std::string Code = "#import \"a.h\"\n";
+  EXPECT_EQ(Code, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
+TEST_F(HeaderIncludesTest, DeleteImportAndSameInclude) {
+  std::string Code = R"cpp(
+#include 
+#import 
+int x;)cpp";
+  EXPECT_EQ("\nint x;", remove(Code, ""));
+}
+
 TEST_F(HeaderIncludesTest, NoExistingIncludeWithDefine) {
   std::string Code = "#ifndef A_H\n"
  "#define A_H\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -296,7 +296,9 @@
   addExistingInclude(
   Include(Matches[2],
   tooling::Range(
-  Offset, std::min(Line.size() + 1, Code.size() - Offset))),
+  Offset, std::min(Line.size() + 1, Code.size() - Offset)),
+  Matches[1] == "import" ? tooling::IncludeDirective::Import
+ : tooling::IncludeDirective::Include),
   NextLineOffset);
 }
 Offset = NextLineOffset;
@@ -342,17 +344,20 @@
 }
 
 llvm::Optional
-HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
+HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled,
+   IncludeDirective Directive) const {
   assert(IncludeName == trimInclude(IncludeName));
   // If a  ("header") already exists in code, "header" () with
-  // different quotation will still be inserted.
+  // different quotation and/or directive will still be inserted.
   // FIXME: figure out if this is the best behavior.
   auto It = ExistingIncludes.find(IncludeName);
-  if (It != ExistingIncludes.end())
+  if (It != ExistingIncludes.end()) {
 for (const auto  : It->second)
-  if ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
-  (!IsAngled && StringRef(Inc.Name).startswith("\"")))
+  if (Inc.Directive == Directive &&
+  ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
+   (!IsAngled && StringRef(Inc.Name).startswith("\""
 return llvm::None;
+  }
   std::string Quoted =
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
   StringRef QuotedName = Quoted;
@@ -371,8 +376,10 @@
 }
   }
   assert(InsertOffset <= Code.size());
+  llvm::StringRef DirectiveSpelling =
+  Directive == IncludeDirective::Include ? "include" : "import";
   std::string NewInclude =
-  std::string(llvm::formatv("#include {0}\n", QuotedName));
+  llvm::formatv("#{0} {1}\n", DirectiveSpelling, QuotedName);
   // When inserting headers at end of the code, also append '\n' to the code
   // if it does not end with '\n'.
   // FIXME: when inserting multiple #includes at the end of code, only one
Index: clang/lib/Format/Format.cpp
===
--- 

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-12-06 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 480513.
dgoldman marked 2 inline comments as done.
dgoldman added a comment.

Update test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderAnalysis.h
  clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
  clang/unittests/Tooling/HeaderAnalysisTest.cpp

Index: clang/unittests/Tooling/HeaderAnalysisTest.cpp
===
--- clang/unittests/Tooling/HeaderAnalysisTest.cpp
+++ clang/unittests/Tooling/HeaderAnalysisTest.cpp
@@ -56,11 +56,42 @@
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("headerguard.h").get(), SM, HI));
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("pragmaonce.h").get(), SM, HI));
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("imported.h").get(), SM, HI));
+  EXPECT_TRUE(
+  isSelfContainedHeader(SM.getFileEntryForID(SM.getMainFileID()), SM, HI));
 
   EXPECT_FALSE(isSelfContainedHeader(FM.getFile("unguarded.h").get(), SM, HI));
   EXPECT_FALSE(isSelfContainedHeader(FM.getFile("bad.h").get(), SM, HI));
 }
 
+TEST(HeaderAnalysisTest, CodeContainsImports) {
+  EXPECT_TRUE(codeContainsImports(R"cpp(
+  #include "foo.h"
+  #import "NSFoo.h"
+
+  int main() {
+foo();
+  }
+  )cpp"));
+
+  EXPECT_TRUE(codeContainsImports(R"cpp(
+  #include "foo.h"
+
+  int main() {
+foo();
+  }
+
+  #import "NSFoo.h"
+  )cpp"));
+
+  EXPECT_FALSE(codeContainsImports(R"cpp(
+  #include "foo.h"
+
+  int main() {
+foo();
+  }
+  )cpp"));
+}
+
 TEST(HeaderAnalysisTest, ParseIWYUPragma) {
   EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep"), ValueIs(Eq("keep")));
   EXPECT_THAT(parseIWYUPragma("// IWYU pragma:   keep  me\netc"),
Index: clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
+++ clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
@@ -37,8 +37,7 @@
 }
 
 // Heuristically headers that only want to be included via an umbrella.
-bool isDontIncludeMeHeader(llvm::MemoryBufferRef Buffer) {
-  StringRef Content = Buffer.getBuffer();
+bool isDontIncludeMeHeader(StringRef Content) {
   llvm::StringRef Line;
   // Only sniff up to 100 lines or 10KB.
   Content = Content.take_front(100 * 100);
@@ -50,19 +49,48 @@
   return false;
 }
 
+bool isImportLine(llvm::StringRef Line) {
+  Line = Line.ltrim();
+  if (!Line.consume_front("#"))
+return false;
+  Line = Line.ltrim();
+  return Line.startswith("import");
+}
+
+llvm::StringRef getFileContents(const FileEntry *FE, const SourceManager ) {
+  return const_cast(SM)
+  .getMemoryBufferForFileOrNone(FE)
+  .value_or(llvm::MemoryBufferRef())
+  .getBuffer();
+}
+
 } // namespace
 
 bool isSelfContainedHeader(const FileEntry *FE, const SourceManager ,
HeaderSearch ) {
   assert(FE);
   if (!HeaderInfo.isFileMultipleIncludeGuarded(FE) &&
-  !HeaderInfo.hasFileBeenImported(FE))
+  !HeaderInfo.hasFileBeenImported(FE) &&
+  // Any header that contains #imports is supposed to be #import'd so no
+  // need to check for anything but the main-file.
+  (SM.getFileEntryForID(SM.getMainFileID()) != FE ||
+   !codeContainsImports(getFileContents(FE, SM
 return false;
   // This pattern indicates that a header can't be used without
   // particular preprocessor state, usually set up by another header.
-  return !isDontIncludeMeHeader(
-  const_cast(SM).getMemoryBufferForFileOrNone(FE).value_or(
-  llvm::MemoryBufferRef()));
+  return !isDontIncludeMeHeader(getFileContents(FE, SM));
+}
+
+bool codeContainsImports(llvm::StringRef Code) {
+  // Only sniff up to 100 lines or 10KB.
+  Code = Code.take_front(100 * 100);
+  llvm::StringRef Line;
+  for (unsigned I = 0; I < 100 && !Code.empty(); ++I) {
+std::tie(Line, Code) = Code.split('\n');
+if (isImportLine(Line))
+  return true;
+  }
+  return false;
 }
 
 llvm::Optional parseIWYUPragma(const char *Text) {
Index: 

[PATCH] D128677: [clang][Tooling] Add support for generating #import edits

2022-12-06 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang/unittests/Tooling/HeaderIncludesTest.cpp:65
 
+TEST_F(HeaderIncludesTest, InsertImportWithSameInclude) {
+  std::string Code = "#include \"a.h\"\n";

kadircet wrote:
> can you also add a removal test?
> 
> i know we didn't change the implementation, but today there's nothing 
> checking the behaviour. so explicitly encoding the expectation here, 
> especially for the case where we have both #include and #import with same 
> spelling is useful. btw is it likely that `#include "foo.h"` and `#import 
> "foo.h"` can refer to different physical headers (e.g. due to framework 
> handling and whatnot)?
> 
> we're not changing the behaviour today, but if there's a difference, this is 
> likely a bug (that already exists), so we should leave a fixme (or address it 
> here if you got time, by introducing a IncludeDirective parameter into 
> remove. updating users is likely harder in this case, as everyone needs to 
> propagate/store the directive during their analysis).
No, I don't think #import and #include can refer to different headers.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128677/new/

https://reviews.llvm.org/D128677

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128677: [clang][Tooling] Add support for generating #import edits

2022-12-06 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 480482.
dgoldman marked 9 inline comments as done.
dgoldman added a comment.

Fixes for review + fix diffbase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128677/new/

https://reviews.llvm.org/D128677

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/unittests/HeadersTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Format/Format.cpp
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Tooling/HeaderIncludesTest.cpp

Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -20,10 +20,12 @@
 
 class HeaderIncludesTest : public ::testing::Test {
 protected:
-  std::string insert(llvm::StringRef Code, llvm::StringRef Header) {
+  std::string insert(llvm::StringRef Code, llvm::StringRef Header,
+ IncludeDirective Directive = IncludeDirective::Include) {
 HeaderIncludes Includes(FileName, Code, Style);
 assert(Header.startswith("\"") || Header.startswith("<"));
-auto R = Includes.insert(Header.trim("\"<>"), Header.startswith("<"));
+auto R =
+Includes.insert(Header.trim("\"<>"), Header.startswith("<"), Directive);
 if (!R)
   return std::string(Code);
 auto Result = applyAllReplacements(Code, Replacements(*R));
@@ -60,6 +62,25 @@
   EXPECT_EQ(Expected, insert(Code, "\"a2.h\""));
 }
 
+TEST_F(HeaderIncludesTest, InsertImportWithSameInclude) {
+  std::string Code = "#include \"a.h\"\n";
+  std::string Expected = Code + "#import \"a.h\"\n";
+  EXPECT_EQ(Expected, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
+TEST_F(HeaderIncludesTest, DontInsertAlreadyImported) {
+  std::string Code = "#import \"a.h\"\n";
+  EXPECT_EQ(Code, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
+TEST_F(HeaderIncludesTest, DeleteImportAndSameInclude) {
+  std::string Code = "#include \"abc.h\"\n"
+ "#import \"abc.h\"\n"
+ "int x;\n";
+  std::string Expected = "int x;\n";
+  EXPECT_EQ(Expected, remove(Code, "\"abc.h\""));
+}
+
 TEST_F(HeaderIncludesTest, NoExistingIncludeWithDefine) {
   std::string Code = "#ifndef A_H\n"
  "#define A_H\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -296,7 +296,9 @@
   addExistingInclude(
   Include(Matches[2],
   tooling::Range(
-  Offset, std::min(Line.size() + 1, Code.size() - Offset))),
+  Offset, std::min(Line.size() + 1, Code.size() - Offset)),
+  Matches[1] == "import" ? tooling::IncludeDirective::Import
+ : tooling::IncludeDirective::Include),
   NextLineOffset);
 }
 Offset = NextLineOffset;
@@ -342,17 +344,20 @@
 }
 
 llvm::Optional
-HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
+HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled,
+   IncludeDirective Directive) const {
   assert(IncludeName == trimInclude(IncludeName));
   // If a  ("header") already exists in code, "header" () with
-  // different quotation will still be inserted.
+  // different quotation and/or directive will still be inserted.
   // FIXME: figure out if this is the best behavior.
   auto It = ExistingIncludes.find(IncludeName);
-  if (It != ExistingIncludes.end())
+  if (It != ExistingIncludes.end()) {
 for (const auto  : It->second)
-  if ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
-  (!IsAngled && StringRef(Inc.Name).startswith("\"")))
+  if (Inc.Directive == Directive &&
+  ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
+   (!IsAngled && StringRef(Inc.Name).startswith("\""
 return llvm::None;
+  }
   std::string Quoted =
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
   StringRef QuotedName = Quoted;
@@ -371,8 +376,10 @@
 }
   }
   assert(InsertOffset <= Code.size());
+  llvm::StringRef DirectiveSpelling =
+  Directive == IncludeDirective::Include ? "include" : "import";
   std::string NewInclude =
-  std::string(llvm::formatv("#include {0}\n", QuotedName));
+  llvm::formatv("#{0} {1}\n", DirectiveSpelling, QuotedName);
   // When inserting headers at end of the code, also append '\n' to the code
   // if it does not end with '\n'.
   // FIXME: when inserting multiple #includes at the end of code, only one

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-12-06 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 480465.
dgoldman marked 4 inline comments as done.
dgoldman added a comment.

Fixes + hopefully proper diffbase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderAnalysis.h
  clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
  clang/unittests/Tooling/HeaderAnalysisTest.cpp

Index: clang/unittests/Tooling/HeaderAnalysisTest.cpp
===
--- clang/unittests/Tooling/HeaderAnalysisTest.cpp
+++ clang/unittests/Tooling/HeaderAnalysisTest.cpp
@@ -56,11 +56,32 @@
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("headerguard.h").get(), SM, HI));
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("pragmaonce.h").get(), SM, HI));
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("imported.h").get(), SM, HI));
+  EXPECT_TRUE(
+  isSelfContainedHeader(SM.getFileEntryForID(SM.getMainFileID()), SM, HI));
 
   EXPECT_FALSE(isSelfContainedHeader(FM.getFile("unguarded.h").get(), SM, HI));
   EXPECT_FALSE(isSelfContainedHeader(FM.getFile("bad.h").get(), SM, HI));
 }
 
+TEST(HeaderAnalysisTest, CodeContainsImports) {
+  EXPECT_TRUE(codeContainsImports(R"cpp(
+  #include "foo.h"
+#import "NSFoo.h"
+
+  int main() {
+foo();
+  }
+  )cpp"));
+
+  EXPECT_FALSE(codeContainsImports(R"cpp(
+  #include "foo.h"
+
+  int main() {
+foo();
+  }
+  )cpp"));
+}
+
 TEST(HeaderAnalysisTest, ParseIWYUPragma) {
   EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep"), ValueIs(Eq("keep")));
   EXPECT_THAT(parseIWYUPragma("// IWYU pragma:   keep  me\netc"),
Index: clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
+++ clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
@@ -37,8 +37,7 @@
 }
 
 // Heuristically headers that only want to be included via an umbrella.
-bool isDontIncludeMeHeader(llvm::MemoryBufferRef Buffer) {
-  StringRef Content = Buffer.getBuffer();
+bool isDontIncludeMeHeader(StringRef Content) {
   llvm::StringRef Line;
   // Only sniff up to 100 lines or 10KB.
   Content = Content.take_front(100 * 100);
@@ -50,19 +49,48 @@
   return false;
 }
 
+bool isImportLine(llvm::StringRef Line) {
+  Line = Line.ltrim();
+  if (!Line.consume_front("#"))
+return false;
+  Line = Line.ltrim();
+  return Line.startswith("import");
+}
+
+llvm::StringRef getFileContents(const FileEntry *FE, const SourceManager ) {
+  return const_cast(SM)
+  .getMemoryBufferForFileOrNone(FE)
+  .value_or(llvm::MemoryBufferRef())
+  .getBuffer();
+}
+
 } // namespace
 
 bool isSelfContainedHeader(const FileEntry *FE, const SourceManager ,
HeaderSearch ) {
   assert(FE);
   if (!HeaderInfo.isFileMultipleIncludeGuarded(FE) &&
-  !HeaderInfo.hasFileBeenImported(FE))
+  !HeaderInfo.hasFileBeenImported(FE) &&
+  // Any header that contains #imports is supposed to be #import'd so no
+  // need to check for anything but the main-file.
+  (SM.getFileEntryForID(SM.getMainFileID()) != FE ||
+   !codeContainsImports(getFileContents(FE, SM
 return false;
   // This pattern indicates that a header can't be used without
   // particular preprocessor state, usually set up by another header.
-  return !isDontIncludeMeHeader(
-  const_cast(SM).getMemoryBufferForFileOrNone(FE).value_or(
-  llvm::MemoryBufferRef()));
+  return !isDontIncludeMeHeader(getFileContents(FE, SM));
+}
+
+bool codeContainsImports(llvm::StringRef Code) {
+  // Only sniff up to 100 lines or 10KB.
+  Code = Code.take_front(100 * 100);
+  llvm::StringRef Line;
+  for (unsigned I = 0; I < 100 && !Code.empty(); ++I) {
+std::tie(Line, Code) = Code.split('\n');
+if (isImportLine(Line))
+  return true;
+  }
+  return false;
 }
 
 llvm::Optional parseIWYUPragma(const char *Text) {
Index: clang/include/clang/Tooling/Inclusions/HeaderAnalysis.h

[PATCH] D128677: [clang][Tooling] Add support for generating #import edits

2022-12-02 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 479665.
dgoldman added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128677/new/

https://reviews.llvm.org/D128677

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/unittests/HeadersTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Tooling/HeaderIncludesTest.cpp

Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -20,10 +20,12 @@
 
 class HeaderIncludesTest : public ::testing::Test {
 protected:
-  std::string insert(llvm::StringRef Code, llvm::StringRef Header) {
+  std::string insert(llvm::StringRef Code, llvm::StringRef Header,
+ IncludeDirective Directive = IncludeDirective::Include) {
 HeaderIncludes Includes(FileName, Code, Style);
 assert(Header.startswith("\"") || Header.startswith("<"));
-auto R = Includes.insert(Header.trim("\"<>"), Header.startswith("<"));
+auto R =
+Includes.insert(Header.trim("\"<>"), Header.startswith("<"), Directive);
 if (!R)
   return std::string(Code);
 auto Result = applyAllReplacements(Code, Replacements(*R));
@@ -60,6 +62,17 @@
   EXPECT_EQ(Expected, insert(Code, "\"a2.h\""));
 }
 
+TEST_F(HeaderIncludesTest, InsertImportWithSameInclude) {
+  std::string Code = "#include \"a.h\"\n";
+  std::string Expected = Code + "#import \"a.h\"\n";
+  EXPECT_EQ(Expected, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
+TEST_F(HeaderIncludesTest, DontInsertAlreadyImported) {
+  std::string Code = "#import \"a.h\"\n";
+  EXPECT_EQ(Code, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
 TEST_F(HeaderIncludesTest, NoExistingIncludeWithDefine) {
   std::string Code = "#ifndef A_H\n"
  "#define A_H\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -296,7 +296,9 @@
   addExistingInclude(
   Include(Matches[2],
   tooling::Range(
-  Offset, std::min(Line.size() + 1, Code.size() - Offset))),
+  Offset, std::min(Line.size() + 1, Code.size() - Offset)),
+  Matches[1] == "include" ? tooling::IncludeDirective::Include
+  : tooling::IncludeDirective::Import),
   NextLineOffset);
 }
 Offset = NextLineOffset;
@@ -342,16 +344,18 @@
 }
 
 llvm::Optional
-HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
+HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled,
+   IncludeDirective Directive) const {
   assert(IncludeName == trimInclude(IncludeName));
   // If a  ("header") already exists in code, "header" () with
-  // different quotation will still be inserted.
+  // different quotation and/or directive will still be inserted.
   // FIXME: figure out if this is the best behavior.
   auto It = ExistingIncludes.find(IncludeName);
   if (It != ExistingIncludes.end())
 for (const auto  : It->second)
-  if ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
-  (!IsAngled && StringRef(Inc.Name).startswith("\"")))
+  if (Inc.Directive == Directive &&
+  ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
+   (!IsAngled && StringRef(Inc.Name).startswith("\""
 return llvm::None;
   std::string Quoted =
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
@@ -372,7 +376,9 @@
   }
   assert(InsertOffset <= Code.size());
   std::string NewInclude =
-  std::string(llvm::formatv("#include {0}\n", QuotedName));
+  Directive == IncludeDirective::Include
+  ? std::string(llvm::formatv("#include {0}\n", QuotedName))
+  : std::string(llvm::formatv("#import {0}\n", QuotedName));
   // When inserting headers at end of the code, also append '\n' to the code
   // if it does not end with '\n'.
   // FIXME: when inserting multiple #includes at the end of code, only one
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -44,6 +44,8 @@
   SmallVector CategoryRegexs;
 };
 
+enum IncludeDirective { Include, Import };
+
 /// Generates replacements for inserting or deleting #include directives in a
 /// file.
 class 

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-12-02 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 479664.
dgoldman added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/unittests/HeadersTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Tooling/HeaderIncludesTest.cpp

Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -20,10 +20,12 @@
 
 class HeaderIncludesTest : public ::testing::Test {
 protected:
-  std::string insert(llvm::StringRef Code, llvm::StringRef Header) {
+  std::string insert(llvm::StringRef Code, llvm::StringRef Header,
+ IncludeDirective Directive = IncludeDirective::Include) {
 HeaderIncludes Includes(FileName, Code, Style);
 assert(Header.startswith("\"") || Header.startswith("<"));
-auto R = Includes.insert(Header.trim("\"<>"), Header.startswith("<"));
+auto R =
+Includes.insert(Header.trim("\"<>"), Header.startswith("<"), Directive);
 if (!R)
   return std::string(Code);
 auto Result = applyAllReplacements(Code, Replacements(*R));
@@ -60,6 +62,17 @@
   EXPECT_EQ(Expected, insert(Code, "\"a2.h\""));
 }
 
+TEST_F(HeaderIncludesTest, InsertImportWithSameInclude) {
+  std::string Code = "#include \"a.h\"\n";
+  std::string Expected = Code + "#import \"a.h\"\n";
+  EXPECT_EQ(Expected, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
+TEST_F(HeaderIncludesTest, DontInsertAlreadyImported) {
+  std::string Code = "#import \"a.h\"\n";
+  EXPECT_EQ(Code, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
 TEST_F(HeaderIncludesTest, NoExistingIncludeWithDefine) {
   std::string Code = "#ifndef A_H\n"
  "#define A_H\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -296,7 +296,9 @@
   addExistingInclude(
   Include(Matches[2],
   tooling::Range(
-  Offset, std::min(Line.size() + 1, Code.size() - Offset))),
+  Offset, std::min(Line.size() + 1, Code.size() - Offset)),
+  Matches[1] == "include" ? tooling::IncludeDirective::Include
+  : tooling::IncludeDirective::Import),
   NextLineOffset);
 }
 Offset = NextLineOffset;
@@ -342,16 +344,18 @@
 }
 
 llvm::Optional
-HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
+HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled,
+   IncludeDirective Directive) const {
   assert(IncludeName == trimInclude(IncludeName));
   // If a  ("header") already exists in code, "header" () with
-  // different quotation will still be inserted.
+  // different quotation and/or directive will still be inserted.
   // FIXME: figure out if this is the best behavior.
   auto It = ExistingIncludes.find(IncludeName);
   if (It != ExistingIncludes.end())
 for (const auto  : It->second)
-  if ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
-  (!IsAngled && StringRef(Inc.Name).startswith("\"")))
+  if (Inc.Directive == Directive &&
+  ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
+   (!IsAngled && StringRef(Inc.Name).startswith("\""
 return llvm::None;
   std::string Quoted =
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
@@ -372,7 +376,9 @@
   }
   assert(InsertOffset <= Code.size());
   std::string NewInclude =
-  std::string(llvm::formatv("#include {0}\n", QuotedName));
+  Directive == IncludeDirective::Include
+  ? std::string(llvm::formatv("#include {0}\n", QuotedName))
+  : std::string(llvm::formatv("#import {0}\n", QuotedName));
   // When inserting headers at end of the code, also append '\n' to the code
   // if it does not end with '\n'.
   // FIXME: when inserting multiple #includes at the end of code, only one
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -44,6 +44,8 @@
   SmallVector CategoryRegexs;
 };
 
+enum IncludeDirective { Include, Import };
+
 /// Generates replacements for inserting or deleting #include directives in a
 /// file.
 class 

[PATCH] D128677: [clangd] Add support for generating #import edits

2022-12-02 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 479659.
dgoldman marked 4 inline comments as done.
dgoldman added a comment.

Fixes for review


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128677/new/

https://reviews.llvm.org/D128677

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/unittests/HeadersTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Tooling/HeaderIncludesTest.cpp

Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -20,10 +20,12 @@
 
 class HeaderIncludesTest : public ::testing::Test {
 protected:
-  std::string insert(llvm::StringRef Code, llvm::StringRef Header) {
+  std::string insert(llvm::StringRef Code, llvm::StringRef Header,
+ IncludeDirective Directive = IncludeDirective::Include) {
 HeaderIncludes Includes(FileName, Code, Style);
 assert(Header.startswith("\"") || Header.startswith("<"));
-auto R = Includes.insert(Header.trim("\"<>"), Header.startswith("<"));
+auto R =
+Includes.insert(Header.trim("\"<>"), Header.startswith("<"), Directive);
 if (!R)
   return std::string(Code);
 auto Result = applyAllReplacements(Code, Replacements(*R));
@@ -60,6 +62,17 @@
   EXPECT_EQ(Expected, insert(Code, "\"a2.h\""));
 }
 
+TEST_F(HeaderIncludesTest, InsertImportWithSameInclude) {
+  std::string Code = "#include \"a.h\"\n";
+  std::string Expected = Code + "#import \"a.h\"\n";
+  EXPECT_EQ(Expected, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
+TEST_F(HeaderIncludesTest, DontInsertAlreadyImported) {
+  std::string Code = "#import \"a.h\"\n";
+  EXPECT_EQ(Code, insert(Code, "\"a.h\"", IncludeDirective::Import));
+}
+
 TEST_F(HeaderIncludesTest, NoExistingIncludeWithDefine) {
   std::string Code = "#ifndef A_H\n"
  "#define A_H\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -296,7 +296,9 @@
   addExistingInclude(
   Include(Matches[2],
   tooling::Range(
-  Offset, std::min(Line.size() + 1, Code.size() - Offset))),
+  Offset, std::min(Line.size() + 1, Code.size() - Offset)),
+  Matches[1] == "include" ? tooling::IncludeDirective::Include
+  : tooling::IncludeDirective::Import),
   NextLineOffset);
 }
 Offset = NextLineOffset;
@@ -342,16 +344,18 @@
 }
 
 llvm::Optional
-HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
+HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled,
+   IncludeDirective Directive) const {
   assert(IncludeName == trimInclude(IncludeName));
   // If a  ("header") already exists in code, "header" () with
-  // different quotation will still be inserted.
+  // different quotation and/or directive will still be inserted.
   // FIXME: figure out if this is the best behavior.
   auto It = ExistingIncludes.find(IncludeName);
   if (It != ExistingIncludes.end())
 for (const auto  : It->second)
-  if ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
-  (!IsAngled && StringRef(Inc.Name).startswith("\"")))
+  if (Inc.Directive == Directive &&
+  ((IsAngled && StringRef(Inc.Name).startswith("<")) ||
+   (!IsAngled && StringRef(Inc.Name).startswith("\""
 return llvm::None;
   std::string Quoted =
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
@@ -372,7 +376,9 @@
   }
   assert(InsertOffset <= Code.size());
   std::string NewInclude =
-  std::string(llvm::formatv("#include {0}\n", QuotedName));
+  Directive == IncludeDirective::Include
+  ? std::string(llvm::formatv("#include {0}\n", QuotedName))
+  : std::string(llvm::formatv("#import {0}\n", QuotedName));
   // When inserting headers at end of the code, also append '\n' to the code
   // if it does not end with '\n'.
   // FIXME: when inserting multiple #includes at the end of code, only one
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -44,6 +44,8 @@
   SmallVector CategoryRegexs;
 };
 
+enum IncludeDirective { Include, Import };
+
 /// Generates replacements for inserting 

[PATCH] D128677: [clangd] Support #import insertions

2022-12-01 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 479343.
dgoldman added a comment.

Run clang-format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128677/new/

https://reviews.llvm.org/D128677

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/unittests/HeadersTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp

Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -342,7 +342,8 @@
 }
 
 llvm::Optional
-HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
+HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled,
+   bool IsImport) const {
   assert(IncludeName == trimInclude(IncludeName));
   // If a  ("header") already exists in code, "header" () with
   // different quotation will still be inserted.
@@ -372,7 +373,8 @@
   }
   assert(InsertOffset <= Code.size());
   std::string NewInclude =
-  std::string(llvm::formatv("#include {0}\n", QuotedName));
+  IsImport ? std::string(llvm::formatv("#import {0}\n", QuotedName))
+   : std::string(llvm::formatv("#include {0}\n", QuotedName));
   // When inserting headers at end of the code, also append '\n' to the code
   // if it does not end with '\n'.
   // FIXME: when inserting multiple #includes at the end of code, only one
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -51,9 +51,9 @@
   HeaderIncludes(llvm::StringRef FileName, llvm::StringRef Code,
  const IncludeStyle );
 
-  /// Inserts an #include directive of \p Header into the code. If \p IsAngled
-  /// is true, \p Header will be quoted with <> in the directive; otherwise, it
-  /// will be quoted with "".
+  /// Inserts an #include or #import directive of \p Header into the code.
+  /// If \p IsAngled is true, \p Header will be quoted with <> in the directive;
+  /// otherwise, it will be quoted with "".
   ///
   /// When searching for points to insert new header, this ignores #include's
   /// after the #include block(s) in the beginning of a file to avoid inserting
@@ -70,13 +70,13 @@
   /// same category in the code that should be sorted after \p IncludeName. If
   /// \p IncludeName already exists (with exactly the same spelling), this
   /// returns None.
-  llvm::Optional insert(llvm::StringRef Header,
-  bool IsAngled) const;
+  llvm::Optional
+  insert(llvm::StringRef Header, bool IsAngled, bool IsImport = false) const;
 
   /// Removes all existing #includes of \p Header quoted with <> if \p IsAngled
   /// is true or "" if \p IsAngled is false.
-  /// This doesn't resolve the header file path; it only deletes #includes with
-  /// exactly the same spelling.
+  /// This doesn't resolve the header file path; it only deletes #includes and
+  /// #imports with exactly the same spelling.
   tooling::Replacements remove(llvm::StringRef Header, bool IsAngled) const;
 
   // Matches a whole #include directive.
Index: clang-tools-extra/clangd/unittests/HeadersTests.cpp
===
--- clang-tools-extra/clangd/unittests/HeadersTests.cpp
+++ clang-tools-extra/clangd/unittests/HeadersTests.cpp
@@ -117,7 +117,8 @@
 return Path.value_or("");
   }
 
-  llvm::Optional insert(llvm::StringRef VerbatimHeader) {
+  llvm::Optional insert(llvm::StringRef VerbatimHeader,
+  bool ViaImport) {
 Clang = setupClang();
 PreprocessOnlyAction Action;
 EXPECT_TRUE(
@@ -126,7 +127,7 @@
 IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
  CDB.getCompileCommand(MainFile)->Directory,
  >getPreprocessor().getHeaderSearchInfo());
-auto Edit = Inserter.insert(VerbatimHeader);
+auto Edit = Inserter.insert(VerbatimHeader, ViaImport);
 Action.EndSourceFile();
 return Edit;
   }
@@ -330,9 +331,13 @@
 }
 
 TEST_F(HeadersTest, PreferInserted) {
-  auto Edit = insert("");
+  auto Edit = insert("", /*ViaImport=*/false);
   EXPECT_TRUE(Edit);
-  EXPECT_TRUE(StringRef(Edit->newText).contains(""));
+  EXPECT_EQ(Edit->newText, "#include \n");
+
+  Edit = insert("\"header.h\"", /*ViaImport=*/true);
+  EXPECT_TRUE(Edit);
+  EXPECT_EQ(Edit->newText, "#import \"header.h\"\n");
 }
 
 TEST(Headers, NoHeaderSearchInfo) {
Index: 

[PATCH] D128677: [clangd] Support #import insertions

2022-12-01 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 479342.
dgoldman added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128677/new/

https://reviews.llvm.org/D128677

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/unittests/HeadersTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp

Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -342,7 +342,8 @@
 }
 
 llvm::Optional
-HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
+HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled,
+   bool IsImport) const {
   assert(IncludeName == trimInclude(IncludeName));
   // If a  ("header") already exists in code, "header" () with
   // different quotation will still be inserted.
@@ -372,7 +373,8 @@
   }
   assert(InsertOffset <= Code.size());
   std::string NewInclude =
-  std::string(llvm::formatv("#include {0}\n", QuotedName));
+  IsImport ? std::string(llvm::formatv("#import {0}\n", QuotedName))
+   : std::string(llvm::formatv("#include {0}\n", QuotedName));
   // When inserting headers at end of the code, also append '\n' to the code
   // if it does not end with '\n'.
   // FIXME: when inserting multiple #includes at the end of code, only one
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -51,9 +51,9 @@
   HeaderIncludes(llvm::StringRef FileName, llvm::StringRef Code,
  const IncludeStyle );
 
-  /// Inserts an #include directive of \p Header into the code. If \p IsAngled
-  /// is true, \p Header will be quoted with <> in the directive; otherwise, it
-  /// will be quoted with "".
+  /// Inserts an #include or #import directive of \p Header into the code.
+  /// If \p IsAngled is true, \p Header will be quoted with <> in the directive;
+  /// otherwise, it will be quoted with "".
   ///
   /// When searching for points to insert new header, this ignores #include's
   /// after the #include block(s) in the beginning of a file to avoid inserting
@@ -70,13 +70,13 @@
   /// same category in the code that should be sorted after \p IncludeName. If
   /// \p IncludeName already exists (with exactly the same spelling), this
   /// returns None.
-  llvm::Optional insert(llvm::StringRef Header,
-  bool IsAngled) const;
+  llvm::Optional
+  insert(llvm::StringRef Header, bool IsAngled, bool IsImport = false) const;
 
   /// Removes all existing #includes of \p Header quoted with <> if \p IsAngled
   /// is true or "" if \p IsAngled is false.
-  /// This doesn't resolve the header file path; it only deletes #includes with
-  /// exactly the same spelling.
+  /// This doesn't resolve the header file path; it only deletes #includes and
+  /// #imports with exactly the same spelling.
   tooling::Replacements remove(llvm::StringRef Header, bool IsAngled) const;
 
   // Matches a whole #include directive.
Index: clang-tools-extra/clangd/unittests/HeadersTests.cpp
===
--- clang-tools-extra/clangd/unittests/HeadersTests.cpp
+++ clang-tools-extra/clangd/unittests/HeadersTests.cpp
@@ -117,7 +117,8 @@
 return Path.value_or("");
   }
 
-  llvm::Optional insert(llvm::StringRef VerbatimHeader) {
+  llvm::Optional insert(llvm::StringRef VerbatimHeader,
+  bool ViaImport) {
 Clang = setupClang();
 PreprocessOnlyAction Action;
 EXPECT_TRUE(
@@ -126,7 +127,7 @@
 IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
  CDB.getCompileCommand(MainFile)->Directory,
  >getPreprocessor().getHeaderSearchInfo());
-auto Edit = Inserter.insert(VerbatimHeader);
+auto Edit = Inserter.insert(VerbatimHeader, ViaImport);
 Action.EndSourceFile();
 return Edit;
   }
@@ -330,9 +331,13 @@
 }
 
 TEST_F(HeadersTest, PreferInserted) {
-  auto Edit = insert("");
+  auto Edit = insert("", /*ViaImport=*/false);
   EXPECT_TRUE(Edit);
-  EXPECT_TRUE(StringRef(Edit->newText).contains(""));
+  EXPECT_EQ(Edit->newText, "#include \n");
+
+  Edit = insert("\"header.h\"", /*ViaImport=*/true);
+  EXPECT_TRUE(Edit);
+  EXPECT_EQ(Edit->newText, "#import \"header.h\"\n");
 }
 
 TEST(Headers, NoHeaderSearchInfo) {
Index: 

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-11-30 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 479066.
dgoldman added a comment.
Herald added a project: clang.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderAnalysis.h
  clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
  clang/unittests/Tooling/HeaderAnalysisTest.cpp

Index: clang/unittests/Tooling/HeaderAnalysisTest.cpp
===
--- clang/unittests/Tooling/HeaderAnalysisTest.cpp
+++ clang/unittests/Tooling/HeaderAnalysisTest.cpp
@@ -56,11 +56,32 @@
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("headerguard.h").get(), SM, HI));
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("pragmaonce.h").get(), SM, HI));
   EXPECT_TRUE(isSelfContainedHeader(FM.getFile("imported.h").get(), SM, HI));
+  EXPECT_TRUE(
+  isSelfContainedHeader(SM.getFileEntryForID(SM.getMainFileID()), SM, HI));
 
   EXPECT_FALSE(isSelfContainedHeader(FM.getFile("unguarded.h").get(), SM, HI));
   EXPECT_FALSE(isSelfContainedHeader(FM.getFile("bad.h").get(), SM, HI));
 }
 
+TEST(HeaderAnalysisTest, CodeContainsImports) {
+  EXPECT_TRUE(codeContainsImports(R"cpp(
+  #include "foo.h"
+#import "NSFoo.h"
+
+  int main() {
+foo();
+  }
+  )cpp"));
+
+  EXPECT_FALSE(codeContainsImports(R"cpp(
+  #include "foo.h"
+
+  int main() {
+foo();
+  }
+  )cpp"));
+}
+
 TEST(HeaderAnalysisTest, ParseIWYUPragma) {
   EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep"), ValueIs(Eq("keep")));
   EXPECT_THAT(parseIWYUPragma("// IWYU pragma:   keep  me\netc"),
Index: clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
+++ clang/lib/Tooling/Inclusions/HeaderAnalysis.cpp
@@ -37,8 +37,7 @@
 }
 
 // Heuristically headers that only want to be included via an umbrella.
-bool isDontIncludeMeHeader(llvm::MemoryBufferRef Buffer) {
-  StringRef Content = Buffer.getBuffer();
+bool isDontIncludeMeHeader(StringRef Content) {
   llvm::StringRef Line;
   // Only sniff up to 100 lines or 10KB.
   Content = Content.take_front(100 * 100);
@@ -50,19 +49,48 @@
   return false;
 }
 
+bool isImportLine(llvm::StringRef Line) {
+  Line = Line.ltrim();
+  if (!Line.consume_front("#"))
+return false;
+  Line = Line.ltrim();
+  return Line.startswith("import");
+}
+
+llvm::StringRef getFileContents(const FileEntry *FE, const SourceManager ) {
+  return const_cast(SM)
+  .getMemoryBufferForFileOrNone(FE)
+  .value_or(llvm::MemoryBufferRef())
+  .getBuffer();
+}
+
 } // namespace
 
 bool isSelfContainedHeader(const FileEntry *FE, const SourceManager ,
HeaderSearch ) {
   assert(FE);
   if (!HeaderInfo.isFileMultipleIncludeGuarded(FE) &&
-  !HeaderInfo.hasFileBeenImported(FE))
+  !HeaderInfo.hasFileBeenImported(FE) &&
+  // Any header that contains #imports is supposed to be #import'd so no
+  // need to check for anything but the main-file.
+  (!const_cast(SM).isMainFile(*FE) ||
+   !codeContainsImports(getFileContents(FE, SM
 return false;
   // This pattern indicates that a header can't be used without
   // particular preprocessor state, usually set up by another header.
-  return !isDontIncludeMeHeader(
-  const_cast(SM).getMemoryBufferForFileOrNone(FE).value_or(
-  llvm::MemoryBufferRef()));
+  return !isDontIncludeMeHeader(getFileContents(FE, SM));
+}
+
+bool codeContainsImports(llvm::StringRef Code) {
+  // Only sniff up to 100 lines or 10KB.
+  Code = Code.take_front(100 * 100);
+  llvm::StringRef Line;
+  for (unsigned I = 0; I < 100 && !Code.empty(); ++I) {
+std::tie(Line, Code) = Code.split('\n');
+if (isImportLine(Line))
+  return true;
+  }
+  return false;
 }
 
 llvm::Optional parseIWYUPragma(const char *Text) {
Index: clang/include/clang/Tooling/Inclusions/HeaderAnalysis.h
===
--- 

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-11-30 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 479024.
dgoldman marked 6 inline comments as done.
dgoldman added a comment.

Fixes for review


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp

Index: clang-tools-extra/clangd/unittests/SerializationTests.cpp
===
--- clang-tools-extra/clangd/unittests/SerializationTests.cpp
+++ clang-tools-extra/clangd/unittests/SerializationTests.cpp
@@ -53,8 +53,16 @@
 IncludeHeaders:
   - Header:'include1'
 References:7
+Directives:  [ Include ]
   - Header:'include2'
 References:3
+Directives:  [ Import ]
+  - Header:'include3'
+References:2
+Directives:  [ Include, Import ]
+  - Header:'include4'
+References:1
+Directives:  [ ]
 ...
 ---
 !Symbol
@@ -114,8 +122,11 @@
 
 MATCHER_P(id, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }
 MATCHER_P(qName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
-MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
-  return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
+MATCHER_P3(IncludeHeaderWithRefAndDirectives, IncludeHeader, References,
+   SupportedDirectives, "") {
+  return (arg.IncludeHeader == IncludeHeader) &&
+ (arg.References == References) &&
+ (arg.SupportedDirectives == SupportedDirectives);
 }
 
 auto readIndexFile(llvm::StringRef Text) {
@@ -148,9 +159,14 @@
   EXPECT_EQ(static_cast(Sym1.Flags), 129);
   EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
   EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
-  EXPECT_THAT(Sym1.IncludeHeaders,
-  UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
-   IncludeHeaderWithRef("include2", 3u)));
+  EXPECT_THAT(
+  Sym1.IncludeHeaders,
+  UnorderedElementsAre(
+  IncludeHeaderWithRefAndDirectives("include1", 7u, Symbol::Include),
+  IncludeHeaderWithRefAndDirectives("include2", 3u, Symbol::Import),
+  IncludeHeaderWithRefAndDirectives("include3", 2u,
+Symbol::Include | Symbol::Import),
+  IncludeHeaderWithRefAndDirectives("include4", 1u, Symbol::Invalid)));
 
   EXPECT_THAT(Sym2, qName("clang::Foo2"));
   EXPECT_EQ(Sym2.Signature, "-sig");
Index: clang-tools-extra/clangd/unittests/IndexTests.cpp
===
--- clang-tools-extra/clangd/unittests/IndexTests.cpp
+++ clang-tools-extra/clangd/unittests/IndexTests.cpp
@@ -567,9 +567,9 @@
   L.Name = "left";
   R.Name = "right";
   L.ID = R.ID = SymbolID("hello");
-  L.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("new", 1);
+  L.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("new", 1, Symbol::Include);
 
   // Both have no definition.
   Symbol M = mergeSymbol(L, R);
@@ -615,7 +615,7 @@
 std::move(DynData), DynSize);
 
   SymbolSlab::Builder StaticB;
-  S.IncludeHeaders.push_back({"", 0});
+  S.IncludeHeaders.push_back({"", 0, Symbol::Include});
   StaticB.insert(S);
   auto StaticIndex =
   MemIndex::build(std::move(StaticB).build(), RefSlab(), RelationSlab());
Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -1071,7 +1071,7 @@
 Sym.Flags |= Symbol::IndexedForCodeCompletion;
 Sym.CanonicalDeclaration.FileURI = S.DeclaringFile.c_str();
 Sym.Definition.FileURI = S.DeclaringFile.c_str();
-Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1);
+

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-11-17 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 476220.
dgoldman marked 10 inline comments as done.
dgoldman added a comment.

Fixes for review


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp

Index: clang-tools-extra/clangd/unittests/SerializationTests.cpp
===
--- clang-tools-extra/clangd/unittests/SerializationTests.cpp
+++ clang-tools-extra/clangd/unittests/SerializationTests.cpp
@@ -53,8 +53,16 @@
 IncludeHeaders:
   - Header:'include1'
 References:7
+Directives:  [ Include ]
   - Header:'include2'
 References:3
+Directives:  [ Import ]
+  - Header:'include3'
+References:2
+Directives:  [ Include, Import ]
+  - Header:'include4'
+References:1
+Directives:  [ ]
 ...
 ---
 !Symbol
@@ -114,8 +122,11 @@
 
 MATCHER_P(id, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }
 MATCHER_P(qName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
-MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
-  return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
+MATCHER_P3(IncludeHeaderWithRefAndDirectives, IncludeHeader, References,
+   SupportedDirectives, "") {
+  return (arg.IncludeHeader == IncludeHeader) &&
+ (arg.References == References) &&
+ (arg.SupportedDirectives == SupportedDirectives);
 }
 
 auto readIndexFile(llvm::StringRef Text) {
@@ -148,9 +159,14 @@
   EXPECT_EQ(static_cast(Sym1.Flags), 129);
   EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
   EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
-  EXPECT_THAT(Sym1.IncludeHeaders,
-  UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
-   IncludeHeaderWithRef("include2", 3u)));
+  EXPECT_THAT(
+  Sym1.IncludeHeaders,
+  UnorderedElementsAre(
+  IncludeHeaderWithRefAndDirectives("include1", 7u, Symbol::Include),
+  IncludeHeaderWithRefAndDirectives("include2", 3u, Symbol::Import),
+  IncludeHeaderWithRefAndDirectives("include3", 2u,
+Symbol::Include | Symbol::Import),
+  IncludeHeaderWithRefAndDirectives("include4", 1u, Symbol::Invalid)));
 
   EXPECT_THAT(Sym2, qName("clang::Foo2"));
   EXPECT_EQ(Sym2.Signature, "-sig");
Index: clang-tools-extra/clangd/unittests/IndexTests.cpp
===
--- clang-tools-extra/clangd/unittests/IndexTests.cpp
+++ clang-tools-extra/clangd/unittests/IndexTests.cpp
@@ -567,9 +567,9 @@
   L.Name = "left";
   R.Name = "right";
   L.ID = R.ID = SymbolID("hello");
-  L.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("new", 1);
+  L.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("new", 1, Symbol::Include);
 
   // Both have no definition.
   Symbol M = mergeSymbol(L, R);
@@ -615,7 +615,7 @@
 std::move(DynData), DynSize);
 
   SymbolSlab::Builder StaticB;
-  S.IncludeHeaders.push_back({"", 0});
+  S.IncludeHeaders.push_back({"", 0, Symbol::Include});
   StaticB.insert(S);
   auto StaticIndex =
   MemIndex::build(std::move(StaticB).build(), RefSlab(), RelationSlab());
Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -1071,7 +1071,7 @@
 Sym.Flags |= Symbol::IndexedForCodeCompletion;
 Sym.CanonicalDeclaration.FileURI = S.DeclaringFile.c_str();
 Sym.Definition.FileURI = S.DeclaringFile.c_str();
-Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1);
+Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1, Symbol::Include);
 Slab.insert(Sym);
   }
   return 

[PATCH] D138047: Fix use of dangling stack allocated string in IncludeFixer

2022-11-16 Thread David Goldman via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG2d5c4b8f6e04: Fix use of dangling stack allocated string in 
IncludeFixer (authored by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D138047/new/

https://reviews.llvm.org/D138047

Files:
  clang-tools-extra/clangd/ParsedAST.cpp


Index: clang-tools-extra/clangd/ParsedAST.cpp
===
--- clang-tools-extra/clangd/ParsedAST.cpp
+++ clang-tools-extra/clangd/ParsedAST.cpp
@@ -465,6 +465,8 @@
   std::vector> CTChecks;
   ast_matchers::MatchFinder CTFinder;
   llvm::Optional CTContext;
+  // Must outlive FixIncludes.
+  auto BuildDir = VFS->getCurrentWorkingDirectory();
   llvm::Optional FixIncludes;
   llvm::DenseMap OverriddenSeverity;
   // No need to run clang-tidy or IncludeFixerif we are not going to surface
@@ -551,7 +553,6 @@
 
 // Add IncludeFixer which can recover diagnostics caused by missing 
includes
 // (e.g. incomplete type) and attach include insertion fixes to 
diagnostics.
-auto BuildDir = VFS->getCurrentWorkingDirectory();
 if (Inputs.Index && !BuildDir.getError()) {
   auto Style =
   getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS);


Index: clang-tools-extra/clangd/ParsedAST.cpp
===
--- clang-tools-extra/clangd/ParsedAST.cpp
+++ clang-tools-extra/clangd/ParsedAST.cpp
@@ -465,6 +465,8 @@
   std::vector> CTChecks;
   ast_matchers::MatchFinder CTFinder;
   llvm::Optional CTContext;
+  // Must outlive FixIncludes.
+  auto BuildDir = VFS->getCurrentWorkingDirectory();
   llvm::Optional FixIncludes;
   llvm::DenseMap OverriddenSeverity;
   // No need to run clang-tidy or IncludeFixerif we are not going to surface
@@ -551,7 +553,6 @@
 
 // Add IncludeFixer which can recover diagnostics caused by missing includes
 // (e.g. incomplete type) and attach include insertion fixes to diagnostics.
-auto BuildDir = VFS->getCurrentWorkingDirectory();
 if (Inputs.Index && !BuildDir.getError()) {
   auto Style =
   getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D138047: Fix use of dangling stack allocated string in IncludeFixer

2022-11-16 Thread David Goldman via Phabricator via cfe-commits
dgoldman added a comment.

In D138047#3930211 , @kadircet wrote:

> yeah unfortunately testing this is hard, but bug are obvious so it's fine 
> to land without a test.
>
> but i think we should rather fix the broken call site at 
> clang-tools-extra/clangd/ParsedAST.cpp and move `BuildDir` to outer scope 
> where it'll outlive IncludeFixer (~line 468).

Done.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D138047/new/

https://reviews.llvm.org/D138047

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D138047: Fix use of dangling stack allocated string in IncludeFixer

2022-11-16 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 475850.
dgoldman added a comment.

Fix in ParsedAST.cpp


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D138047/new/

https://reviews.llvm.org/D138047

Files:
  clang-tools-extra/clangd/ParsedAST.cpp


Index: clang-tools-extra/clangd/ParsedAST.cpp
===
--- clang-tools-extra/clangd/ParsedAST.cpp
+++ clang-tools-extra/clangd/ParsedAST.cpp
@@ -465,6 +465,8 @@
   std::vector> CTChecks;
   ast_matchers::MatchFinder CTFinder;
   llvm::Optional CTContext;
+  // Must outlive FixIncludes.
+  auto BuildDir = VFS->getCurrentWorkingDirectory();
   llvm::Optional FixIncludes;
   llvm::DenseMap OverriddenSeverity;
   // No need to run clang-tidy or IncludeFixerif we are not going to surface
@@ -551,7 +553,6 @@
 
 // Add IncludeFixer which can recover diagnostics caused by missing 
includes
 // (e.g. incomplete type) and attach include insertion fixes to 
diagnostics.
-auto BuildDir = VFS->getCurrentWorkingDirectory();
 if (Inputs.Index && !BuildDir.getError()) {
   auto Style =
   getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS);


Index: clang-tools-extra/clangd/ParsedAST.cpp
===
--- clang-tools-extra/clangd/ParsedAST.cpp
+++ clang-tools-extra/clangd/ParsedAST.cpp
@@ -465,6 +465,8 @@
   std::vector> CTChecks;
   ast_matchers::MatchFinder CTFinder;
   llvm::Optional CTContext;
+  // Must outlive FixIncludes.
+  auto BuildDir = VFS->getCurrentWorkingDirectory();
   llvm::Optional FixIncludes;
   llvm::DenseMap OverriddenSeverity;
   // No need to run clang-tidy or IncludeFixerif we are not going to surface
@@ -551,7 +553,6 @@
 
 // Add IncludeFixer which can recover diagnostics caused by missing includes
 // (e.g. incomplete type) and attach include insertion fixes to diagnostics.
-auto BuildDir = VFS->getCurrentWorkingDirectory();
 if (Inputs.Index && !BuildDir.getError()) {
   auto Style =
   getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D138047: Fix use of dangling stack allocated string in IncludeFixer

2022-11-15 Thread David Goldman via Phabricator via cfe-commits
dgoldman added a comment.

LMK of the best way to add a test for this, maybe I can somehow make a test 
with relative path arguments?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D138047/new/

https://reviews.llvm.org/D138047

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D138047: Fix use of dangling stack allocated string in IncludeFixer

2022-11-15 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

IncludeFixer uses this BuildDir string later on if given relative paths.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D138047

Files:
  clang-tools-extra/clangd/Headers.h


Index: clang-tools-extra/clangd/Headers.h
===
--- clang-tools-extra/clangd/Headers.h
+++ clang-tools-extra/clangd/Headers.h
@@ -250,7 +250,7 @@
 private:
   StringRef FileName;
   StringRef Code;
-  StringRef BuildDir;
+  std::string BuildDir;
   HeaderSearch *HeaderSearchInfo = nullptr;
   llvm::StringSet<> IncludedHeaders; // Both written and resolved.
   tooling::HeaderIncludes Inserter;  // Computers insertion replacement.


Index: clang-tools-extra/clangd/Headers.h
===
--- clang-tools-extra/clangd/Headers.h
+++ clang-tools-extra/clangd/Headers.h
@@ -250,7 +250,7 @@
 private:
   StringRef FileName;
   StringRef Code;
-  StringRef BuildDir;
+  std::string BuildDir;
   HeaderSearch *HeaderSearchInfo = nullptr;
   llvm::StringSet<> IncludedHeaders; // Both written and resolved.
   tooling::HeaderIncludes Inserter;  // Computers insertion replacement.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-11-14 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 475180.
dgoldman added a comment.

Run clang format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp

Index: clang-tools-extra/clangd/unittests/SerializationTests.cpp
===
--- clang-tools-extra/clangd/unittests/SerializationTests.cpp
+++ clang-tools-extra/clangd/unittests/SerializationTests.cpp
@@ -53,8 +53,16 @@
 IncludeHeaders:
   - Header:'include1'
 References:7
+Directives:  [ Include ]
   - Header:'include2'
 References:3
+Directives:  [ Import ]
+  - Header:'include3'
+References:2
+Directives:  [ Include, Import ]
+  - Header:'include4'
+References:1
+Directives:  [ ]
 ...
 ---
 !Symbol
@@ -114,8 +122,11 @@
 
 MATCHER_P(id, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }
 MATCHER_P(qName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
-MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
-  return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
+MATCHER_P3(IncludeHeaderWithRefAndDirectives, IncludeHeader, References,
+   SupportedDirectives, "") {
+  return (arg.IncludeHeader == IncludeHeader) &&
+ (arg.References == References) &&
+ (arg.SupportedDirectives == SupportedDirectives);
 }
 
 auto readIndexFile(llvm::StringRef Text) {
@@ -148,9 +159,14 @@
   EXPECT_EQ(static_cast(Sym1.Flags), 129);
   EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
   EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
-  EXPECT_THAT(Sym1.IncludeHeaders,
-  UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
-   IncludeHeaderWithRef("include2", 3u)));
+  EXPECT_THAT(
+  Sym1.IncludeHeaders,
+  UnorderedElementsAre(
+  IncludeHeaderWithRefAndDirectives("include1", 7u, Symbol::Include),
+  IncludeHeaderWithRefAndDirectives("include2", 3u, Symbol::Import),
+  IncludeHeaderWithRefAndDirectives("include3", 2u,
+Symbol::Include | Symbol::Import),
+  IncludeHeaderWithRefAndDirectives("include4", 1u, Symbol::Invalid)));
 
   EXPECT_THAT(Sym2, qName("clang::Foo2"));
   EXPECT_EQ(Sym2.Signature, "-sig");
Index: clang-tools-extra/clangd/unittests/IndexTests.cpp
===
--- clang-tools-extra/clangd/unittests/IndexTests.cpp
+++ clang-tools-extra/clangd/unittests/IndexTests.cpp
@@ -567,9 +567,9 @@
   L.Name = "left";
   R.Name = "right";
   L.ID = R.ID = SymbolID("hello");
-  L.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("new", 1);
+  L.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("new", 1, Symbol::Include);
 
   // Both have no definition.
   Symbol M = mergeSymbol(L, R);
@@ -615,7 +615,7 @@
 std::move(DynData), DynSize);
 
   SymbolSlab::Builder StaticB;
-  S.IncludeHeaders.push_back({"", 0});
+  S.IncludeHeaders.push_back({"", 0, Symbol::Include});
   StaticB.insert(S);
   auto StaticIndex =
   MemIndex::build(std::move(StaticB).build(), RefSlab(), RelationSlab());
Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -1071,7 +1071,7 @@
 Sym.Flags |= Symbol::IndexedForCodeCompletion;
 Sym.CanonicalDeclaration.FileURI = S.DeclaringFile.c_str();
 Sym.Definition.FileURI = S.DeclaringFile.c_str();
-Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1);
+Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1, Symbol::Include);
 Slab.insert(Sym);
   }
   return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab());
@@ -1129,7 +1129,7 @@
   Symbol Sym = 

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-11-10 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 474571.
dgoldman marked an inline comment as done.
dgoldman added a comment.

Fix serialization and isSelfContainedHeader

- Keep serialization as a single var uint32
- Keep old imported logic in isSelfContainedHeader in addition to a new check 
for import lines only for main files


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp

Index: clang-tools-extra/clangd/unittests/SerializationTests.cpp
===
--- clang-tools-extra/clangd/unittests/SerializationTests.cpp
+++ clang-tools-extra/clangd/unittests/SerializationTests.cpp
@@ -53,8 +53,16 @@
 IncludeHeaders:
   - Header:'include1'
 References:7
+Directives:  [ Include ]
   - Header:'include2'
 References:3
+Directives:  [ Import ]
+  - Header:'include3'
+References:2
+Directives:  [ Include, Import ]
+  - Header:'include4'
+References:1
+Directives:  [ ]
 ...
 ---
 !Symbol
@@ -114,8 +122,11 @@
 
 MATCHER_P(id, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }
 MATCHER_P(qName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
-MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
-  return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
+MATCHER_P3(IncludeHeaderWithRefAndDirectives, IncludeHeader, References,
+   SupportedDirectives, "") {
+  return (arg.IncludeHeader == IncludeHeader) &&
+ (arg.References == References) &&
+ (arg.SupportedDirectives == SupportedDirectives);
 }
 
 auto readIndexFile(llvm::StringRef Text) {
@@ -148,9 +159,14 @@
   EXPECT_EQ(static_cast(Sym1.Flags), 129);
   EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
   EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
-  EXPECT_THAT(Sym1.IncludeHeaders,
-  UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
-   IncludeHeaderWithRef("include2", 3u)));
+  EXPECT_THAT(
+  Sym1.IncludeHeaders,
+  UnorderedElementsAre(
+  IncludeHeaderWithRefAndDirectives("include1", 7u, Symbol::Include),
+  IncludeHeaderWithRefAndDirectives("include2", 3u, Symbol::Import),
+  IncludeHeaderWithRefAndDirectives(
+  "include3", 2u, Symbol::Include | Symbol::Import),
+  IncludeHeaderWithRefAndDirectives("include4", 1u, Symbol::Invalid)));
 
   EXPECT_THAT(Sym2, qName("clang::Foo2"));
   EXPECT_EQ(Sym2.Signature, "-sig");
Index: clang-tools-extra/clangd/unittests/IndexTests.cpp
===
--- clang-tools-extra/clangd/unittests/IndexTests.cpp
+++ clang-tools-extra/clangd/unittests/IndexTests.cpp
@@ -567,9 +567,9 @@
   L.Name = "left";
   R.Name = "right";
   L.ID = R.ID = SymbolID("hello");
-  L.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("new", 1);
+  L.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("new", 1, Symbol::Include);
 
   // Both have no definition.
   Symbol M = mergeSymbol(L, R);
@@ -615,7 +615,7 @@
 std::move(DynData), DynSize);
 
   SymbolSlab::Builder StaticB;
-  S.IncludeHeaders.push_back({"", 0});
+  S.IncludeHeaders.push_back({"", 0, Symbol::Include});
   StaticB.insert(S);
   auto StaticIndex =
   MemIndex::build(std::move(StaticB).build(), RefSlab(), RelationSlab());
Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -1071,7 +1071,7 @@
 Sym.Flags |= Symbol::IndexedForCodeCompletion;
 Sym.CanonicalDeclaration.FileURI = S.DeclaringFile.c_str();
 Sym.Definition.FileURI = S.DeclaringFile.c_str();
-Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1);
+

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-11-04 Thread David Goldman via Phabricator via cfe-commits
dgoldman marked 4 inline comments as done.
dgoldman added a comment.

Also LMK if you want more in this change (such as a flag to control it, just 
not sure where it should live + what it should be called).




Comment at: clang-tools-extra/clangd/index/Symbol.h:116
+/// this header.
+IncludeTypes IncludeTypes = Invalid;
   };

kadircet wrote:
> the naming here feels a little confusing, can we change the enum name to be 
> `IncludeDirective` and field name to `SupportedDirectives`
Done, although for Serialization I left it as a 32 bit and then 8 bit include 
directives, LMK if I should swap it over to serialize as a 32 bit single 
value... Guess I would need to use a union or manually bit manipulate it to 
store + load it?



Comment at: 
clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp:1689-1690
   auto TU = TestTU::withHeaderCode("int x();");
-  EXPECT_THAT(TU.headerSymbols(), ElementsAre(includeHeader()));
+  // FIXME(davg): This doesn't work since we use a -include to put a sneaky 
#import in.
+  // EXPECT_THAT(TU.headerSymbols(), ElementsAre(includeHeader()));
 

Not sure the best way to fix this, should we also scan the -include files for 
#imports?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-11-04 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 473347.
dgoldman marked an inline comment as done.
dgoldman added a comment.

Fixes for review

- Swap over IncludeType to IncludeDirective and update the protos accordingly


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp

Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1686,7 +1686,8 @@
 
 TEST_F(SymbolCollectorTest, NonModularHeader) {
   auto TU = TestTU::withHeaderCode("int x();");
-  EXPECT_THAT(TU.headerSymbols(), ElementsAre(includeHeader()));
+  // FIXME(davg): This doesn't work since we use a -include to put a sneaky #import in.
+  // EXPECT_THAT(TU.headerSymbols(), ElementsAre(includeHeader()));
 
   // Files missing include guards aren't eligible for insertion.
   TU.ImplicitHeaderGuard = false;
Index: clang-tools-extra/clangd/unittests/SerializationTests.cpp
===
--- clang-tools-extra/clangd/unittests/SerializationTests.cpp
+++ clang-tools-extra/clangd/unittests/SerializationTests.cpp
@@ -53,8 +53,16 @@
 IncludeHeaders:
   - Header:'include1'
 References:7
+Directives:  [ Include ]
   - Header:'include2'
 References:3
+Directives:  [ Import ]
+  - Header:'include3'
+References:2
+Directives:  [ Include, Import ]
+  - Header:'include4'
+References:1
+Directives:  [ ]
 ...
 ---
 !Symbol
@@ -114,8 +122,11 @@
 
 MATCHER_P(id, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }
 MATCHER_P(qName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
-MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
-  return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
+MATCHER_P3(IncludeHeaderWithRefAndDirectives, IncludeHeader, References,
+   SupportedDirectives, "") {
+  return (arg.IncludeHeader == IncludeHeader) &&
+ (arg.References == References) &&
+ (arg.SupportedDirectives == SupportedDirectives);
 }
 
 auto readIndexFile(llvm::StringRef Text) {
@@ -148,9 +159,14 @@
   EXPECT_EQ(static_cast(Sym1.Flags), 129);
   EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
   EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
-  EXPECT_THAT(Sym1.IncludeHeaders,
-  UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
-   IncludeHeaderWithRef("include2", 3u)));
+  EXPECT_THAT(
+  Sym1.IncludeHeaders,
+  UnorderedElementsAre(
+  IncludeHeaderWithRefAndDirectives("include1", 7u, Symbol::Include),
+  IncludeHeaderWithRefAndDirectives("include2", 3u, Symbol::Import),
+  IncludeHeaderWithRefAndDirectives(
+  "include3", 2u, Symbol::Include | Symbol::Import),
+  IncludeHeaderWithRefAndDirectives("include4", 1u, Symbol::Invalid)));
 
   EXPECT_THAT(Sym2, qName("clang::Foo2"));
   EXPECT_EQ(Sym2.Signature, "-sig");
Index: clang-tools-extra/clangd/unittests/IndexTests.cpp
===
--- clang-tools-extra/clangd/unittests/IndexTests.cpp
+++ clang-tools-extra/clangd/unittests/IndexTests.cpp
@@ -567,9 +567,9 @@
   L.Name = "left";
   R.Name = "right";
   L.ID = R.ID = SymbolID("hello");
-  L.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("new", 1);
+  L.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("new", 1, Symbol::Include);
 
   // Both have no definition.
   Symbol M = mergeSymbol(L, R);
@@ -615,7 +615,7 @@
 std::move(DynData), DynSize);
 
   SymbolSlab::Builder StaticB;
-  S.IncludeHeaders.push_back({"", 0});
+  S.IncludeHeaders.push_back({"", 0, 

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-10-26 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 470868.
dgoldman added a comment.

Change IncludeTypes to be a bitset


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128457/new/

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp

Index: clang-tools-extra/clangd/unittests/SerializationTests.cpp
===
--- clang-tools-extra/clangd/unittests/SerializationTests.cpp
+++ clang-tools-extra/clangd/unittests/SerializationTests.cpp
@@ -53,8 +53,10 @@
 IncludeHeaders:
   - Header:'include1'
 References:7
+Type:  [ Include ]
   - Header:'include2'
 References:3
+Type:  [ Import ]
 ...
 ---
 !Symbol
@@ -114,8 +116,10 @@
 
 MATCHER_P(id, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }
 MATCHER_P(qName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
-MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
-  return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
+MATCHER_P3(IncludeHeaderWithRefAndType, IncludeHeader, References, IncludeTypes,
+   "") {
+  return (arg.IncludeHeader == IncludeHeader) &&
+ (arg.References == References) && (arg.IncludeTypes == IncludeTypes);
 }
 
 auto readIndexFile(llvm::StringRef Text) {
@@ -149,8 +153,9 @@
   EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
   EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
   EXPECT_THAT(Sym1.IncludeHeaders,
-  UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
-   IncludeHeaderWithRef("include2", 3u)));
+  UnorderedElementsAre(
+  IncludeHeaderWithRefAndType("include1", 7u, Symbol::Include),
+  IncludeHeaderWithRefAndType("include2", 3u, Symbol::Import)));
 
   EXPECT_THAT(Sym2, qName("clang::Foo2"));
   EXPECT_EQ(Sym2.Signature, "-sig");
Index: clang-tools-extra/clangd/unittests/IndexTests.cpp
===
--- clang-tools-extra/clangd/unittests/IndexTests.cpp
+++ clang-tools-extra/clangd/unittests/IndexTests.cpp
@@ -567,9 +567,9 @@
   L.Name = "left";
   R.Name = "right";
   L.ID = R.ID = SymbolID("hello");
-  L.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("new", 1);
+  L.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("new", 1, Symbol::Include);
 
   // Both have no definition.
   Symbol M = mergeSymbol(L, R);
@@ -615,7 +615,7 @@
 std::move(DynData), DynSize);
 
   SymbolSlab::Builder StaticB;
-  S.IncludeHeaders.push_back({"", 0});
+  S.IncludeHeaders.push_back({"", 0, Symbol::Include});
   StaticB.insert(S);
   auto StaticIndex =
   MemIndex::build(std::move(StaticB).build(), RefSlab(), RelationSlab());
Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -1069,7 +1069,7 @@
 Sym.Flags |= Symbol::IndexedForCodeCompletion;
 Sym.CanonicalDeclaration.FileURI = S.DeclaringFile.c_str();
 Sym.Definition.FileURI = S.DeclaringFile.c_str();
-Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1);
+Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1, Symbol::Include);
 Slab.insert(Sym);
   }
   return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab());
@@ -1127,7 +1127,7 @@
   Symbol Sym = enm("X");
   Sym.Flags |= Symbol::IndexedForCodeCompletion;
   Sym.CanonicalDeclaration.FileURI = Sym.Definition.FileURI = "unittest:///x.h";
-  Sym.IncludeHeaders.emplace_back("\"x.h\"", 1);
+  Sym.IncludeHeaders.emplace_back("\"x.h\"", 1, Symbol::Include);
   SymbolSlab::Builder Slab;
   Slab.insert(Sym);
   auto Index =
@@ -1170,7 +1170,7 @@
   Sym.Flags |= Symbol::IndexedForCodeCompletion;
   Sym.CanonicalDeclaration.FileURI = "unittest:///x.h";
   Sym.Definition.FileURI = "unittest:///x.cc";
-  Sym.IncludeHeaders.emplace_back("\"x.h\"", 1);
+  

[PATCH] D127403: [clangd] Implement semantic token modifier "definition"

2022-09-08 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:863
+  Tok.addModifier(HighlightingModifier::Declaration);
+if (const auto Func = dyn_cast(Decl)) {
+  if (Func->isThisDeclarationADefinition())

Instead of doing it like this, I wonder if would make more sense to call 
getDefinition from 
https://cs.github.com/llvm/llvm-project/blob/ae071a59bc6cc09e0e0043e0ef1d9725853f1681/clang-tools-extra/clangd/XRefs.cpp#L76
 and if it matches Decl, add the Definition modifier?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127403/new/

https://reviews.llvm.org/D127403

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133479: [clangd] Set Incompleteness for spec fuzzyfind requests

2022-09-08 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1716
+  Incomplete |= SpecRes.first;
+  return std::move(SpecRes.second);
 }

dgoldman wrote:
> Can this be safely moved - looks like it wasn't before?
Ah nevermind, missed that this is moving the local copy.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133479/new/

https://reviews.llvm.org/D133479

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133479: [clangd] Set Incompleteness for spec fuzzyfind requests

2022-09-08 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1716
+  Incomplete |= SpecRes.first;
+  return std::move(SpecRes.second);
 }

Can this be safely moved - looks like it wasn't before?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133479/new/

https://reviews.llvm.org/D133479

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132962: [clangd][ObjC] Improve completions for protocols + category names

2022-09-08 Thread David Goldman via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
dgoldman marked an inline comment as done.
Closed by commit rGe09c75049854: [clangd][ObjC] Improve completions for 
protocols + category names (authored by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132962/new/

https://reviews.llvm.org/D132962

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/TestIndex.cpp
  clang-tools-extra/clangd/unittests/TestIndex.h

Index: clang-tools-extra/clangd/unittests/TestIndex.h
===
--- clang-tools-extra/clangd/unittests/TestIndex.h
+++ clang-tools-extra/clangd/unittests/TestIndex.h
@@ -39,6 +39,8 @@
llvm::StringRef USRPrefix);
 // Create an @interface or @implementation.
 Symbol objcClass(llvm::StringRef Name);
+// Create an @interface or @implementation category.
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName);
 // Create an @protocol.
 Symbol objcProtocol(llvm::StringRef Name);
 
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -99,6 +99,11 @@
   return objcSym(Name, index::SymbolKind::Class, "objc(cs)");
 }
 
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName) {
+  std::string USRPrefix = ("objc(cy)" + Name + "@").str();
+  return objcSym(CategoryName, index::SymbolKind::Extension, USRPrefix);
+}
+
 Symbol objcProtocol(llvm::StringRef Name) {
   return objcSym(Name, index::SymbolKind::Protocol, "objc(pl)");
 }
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1493,12 +1493,16 @@
 
 class IndexRequestCollector : public SymbolIndex {
 public:
+  IndexRequestCollector(std::vector Syms = {}) : Symbols(Syms) {}
+
   bool
   fuzzyFind(const FuzzyFindRequest ,
 llvm::function_ref Callback) const override {
 std::unique_lock Lock(Mut);
 Requests.push_back(Req);
 ReceivedRequestCV.notify_one();
+for (const auto  : Symbols)
+  Callback(Sym);
 return true;
   }
 
@@ -1533,6 +1537,7 @@
   }
 
 private:
+  std::vector Symbols;
   // We need a mutex to handle async fuzzy find requests.
   mutable std::condition_variable ReceivedRequestCV;
   mutable std::mutex Mut;
@@ -3208,14 +3213,74 @@
   Symbol FoodClass = objcClass("FoodClass");
   Symbol SymFood = objcProtocol("Food");
   Symbol SymFooey = objcProtocol("Fooey");
+  auto Results = completions("id", {SymFood, FoodClass, SymFooey},
+ /*Opts=*/{}, "Foo.m");
+
+  // Should only give protocols for ObjC protocol completions.
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(
+  AllOf(named("Food"), kind(CompletionItemKind::Interface)),
+  AllOf(named("Fooey"), kind(CompletionItemKind::Interface;
+
+  Results = completions("Fo^", {SymFood, FoodClass, SymFooey},
+/*Opts=*/{}, "Foo.m");
+  // Shouldn't give protocols for non protocol completions.
+  EXPECT_THAT(
+  Results.Completions,
+  ElementsAre(AllOf(named("FoodClass"), kind(CompletionItemKind::Class;
+}
+
+TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {
+  MockFS FS;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
+
+  auto File = testPath("Foo.m");
+  Annotations Test(R"cpp(
+  @protocol Food
+  @end
+  id foo;
+  Foo$2^ bar;
+  )cpp");
+  runAddDocument(Server, File, Test.code());
+  clangd::CodeCompleteOptions Opts = {};
+
+  Symbol FoodClass = objcClass("FoodClass");
+  IndexRequestCollector Requests({FoodClass});
+  Opts.Index = 
+
+  auto CompleteAtPoint = [&](StringRef P) {
+return cantFail(runCodeComplete(Server, File, Test.point(P), Opts))
+.Completions;
+  };
+
+  auto C = CompleteAtPoint("1");
+  auto Reqs1 = Requests.consumeRequests(1);
+  ASSERT_EQ(Reqs1.size(), 1u);
+  EXPECT_THAT(C, ElementsAre(AllOf(named("Food"),
+   kind(CompletionItemKind::Interface;
+
+  C = CompleteAtPoint("2");
+  auto Reqs2 = Requests.consumeRequests(1);
+  // Speculation succeeded. Used speculative index result, but filtering now to
+  // now include FoodClass.
+  ASSERT_EQ(Reqs2.size(), 1u);
+  EXPECT_EQ(Reqs2[0], Reqs1[0]);
+  EXPECT_THAT(C, ElementsAre(AllOf(named("FoodClass"),
+   kind(CompletionItemKind::Class;
+}
+
+TEST(CompletionTest, ObjectiveCCategoryFromIndexIgnored) {
+  Symbol FoodCategory = objcCategory("FoodClass", 

[PATCH] D132962: [clangd][ObjC] Improve completions for protocols + category names

2022-09-08 Thread David Goldman via Phabricator via cfe-commits
dgoldman marked an inline comment as done.
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1731
 SymbolSlab::Builder ResultsBuilder;
-if (Opts.Index->fuzzyFind(Req, [&](const Symbol ) {
-  if (includeSymbolFromIndex(Sym))
-ResultsBuilder.insert(Sym);
-}))
+if (Opts.Index->fuzzyFind(
+Req, [&](const Symbol ) { ResultsBuilder.insert(Sym); }))

kadircet wrote:
> nit: while here can you change this to read as:
> `Incomplete ||= Opts.Index->fuzzyFind(...);`
Done, but there's no ||= and we wouldn't want to short circuit, so used |= 
instead.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132962/new/

https://reviews.llvm.org/D132962

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132962: [clangd][ObjC] Improve completions for protocols + category names

2022-09-08 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 458724.
dgoldman added a comment.

Address comment


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132962/new/

https://reviews.llvm.org/D132962

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/TestIndex.cpp
  clang-tools-extra/clangd/unittests/TestIndex.h

Index: clang-tools-extra/clangd/unittests/TestIndex.h
===
--- clang-tools-extra/clangd/unittests/TestIndex.h
+++ clang-tools-extra/clangd/unittests/TestIndex.h
@@ -39,6 +39,8 @@
llvm::StringRef USRPrefix);
 // Create an @interface or @implementation.
 Symbol objcClass(llvm::StringRef Name);
+// Create an @interface or @implementation category.
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName);
 // Create an @protocol.
 Symbol objcProtocol(llvm::StringRef Name);
 
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -99,6 +99,11 @@
   return objcSym(Name, index::SymbolKind::Class, "objc(cs)");
 }
 
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName) {
+  std::string USRPrefix = ("objc(cy)" + Name + "@").str();
+  return objcSym(CategoryName, index::SymbolKind::Extension, USRPrefix);
+}
+
 Symbol objcProtocol(llvm::StringRef Name) {
   return objcSym(Name, index::SymbolKind::Protocol, "objc(pl)");
 }
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1493,12 +1493,16 @@
 
 class IndexRequestCollector : public SymbolIndex {
 public:
+  IndexRequestCollector(std::vector Syms = {}) : Symbols(Syms) {}
+
   bool
   fuzzyFind(const FuzzyFindRequest ,
 llvm::function_ref Callback) const override {
 std::unique_lock Lock(Mut);
 Requests.push_back(Req);
 ReceivedRequestCV.notify_one();
+for (const auto  : Symbols)
+  Callback(Sym);
 return true;
   }
 
@@ -1533,6 +1537,7 @@
   }
 
 private:
+  std::vector Symbols;
   // We need a mutex to handle async fuzzy find requests.
   mutable std::condition_variable ReceivedRequestCV;
   mutable std::mutex Mut;
@@ -3208,14 +3213,74 @@
   Symbol FoodClass = objcClass("FoodClass");
   Symbol SymFood = objcProtocol("Food");
   Symbol SymFooey = objcProtocol("Fooey");
+  auto Results = completions("id", {SymFood, FoodClass, SymFooey},
+ /*Opts=*/{}, "Foo.m");
+
+  // Should only give protocols for ObjC protocol completions.
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(
+  AllOf(named("Food"), kind(CompletionItemKind::Interface)),
+  AllOf(named("Fooey"), kind(CompletionItemKind::Interface;
+
+  Results = completions("Fo^", {SymFood, FoodClass, SymFooey},
+/*Opts=*/{}, "Foo.m");
+  // Shouldn't give protocols for non protocol completions.
+  EXPECT_THAT(
+  Results.Completions,
+  ElementsAre(AllOf(named("FoodClass"), kind(CompletionItemKind::Class;
+}
+
+TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {
+  MockFS FS;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
+
+  auto File = testPath("Foo.m");
+  Annotations Test(R"cpp(
+  @protocol Food
+  @end
+  id foo;
+  Foo$2^ bar;
+  )cpp");
+  runAddDocument(Server, File, Test.code());
+  clangd::CodeCompleteOptions Opts = {};
+
+  Symbol FoodClass = objcClass("FoodClass");
+  IndexRequestCollector Requests({FoodClass});
+  Opts.Index = 
+
+  auto CompleteAtPoint = [&](StringRef P) {
+return cantFail(runCodeComplete(Server, File, Test.point(P), Opts))
+.Completions;
+  };
+
+  auto C = CompleteAtPoint("1");
+  auto Reqs1 = Requests.consumeRequests(1);
+  ASSERT_EQ(Reqs1.size(), 1u);
+  EXPECT_THAT(C, ElementsAre(AllOf(named("Food"),
+   kind(CompletionItemKind::Interface;
+
+  C = CompleteAtPoint("2");
+  auto Reqs2 = Requests.consumeRequests(1);
+  // Speculation succeeded. Used speculative index result, but filtering now to
+  // now include FoodClass.
+  ASSERT_EQ(Reqs2.size(), 1u);
+  EXPECT_EQ(Reqs2[0], Reqs1[0]);
+  EXPECT_THAT(C, ElementsAre(AllOf(named("FoodClass"),
+   kind(CompletionItemKind::Class;
+}
+
+TEST(CompletionTest, ObjectiveCCategoryFromIndexIgnored) {
+  Symbol FoodCategory = objcCategory("FoodClass", "Extension");
   auto Results = completions(R"objc(
-  id
+  @interface Foo
+  @end
+  @interface Foo (^)
+  @end
 )objc",
-  

[PATCH] D132962: [clangd][ObjC] Improve completions for protocols + category names

2022-09-01 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 457258.
dgoldman added a comment.

Run clang-format again


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132962/new/

https://reviews.llvm.org/D132962

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/TestIndex.cpp
  clang-tools-extra/clangd/unittests/TestIndex.h

Index: clang-tools-extra/clangd/unittests/TestIndex.h
===
--- clang-tools-extra/clangd/unittests/TestIndex.h
+++ clang-tools-extra/clangd/unittests/TestIndex.h
@@ -39,6 +39,8 @@
llvm::StringRef USRPrefix);
 // Create an @interface or @implementation.
 Symbol objcClass(llvm::StringRef Name);
+// Create an @interface or @implementation category.
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName);
 // Create an @protocol.
 Symbol objcProtocol(llvm::StringRef Name);
 
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -99,6 +99,11 @@
   return objcSym(Name, index::SymbolKind::Class, "objc(cs)");
 }
 
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName) {
+  std::string USRPrefix = ("objc(cy)" + Name + "@").str();
+  return objcSym(CategoryName, index::SymbolKind::Extension, USRPrefix);
+}
+
 Symbol objcProtocol(llvm::StringRef Name) {
   return objcSym(Name, index::SymbolKind::Protocol, "objc(pl)");
 }
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1493,12 +1493,16 @@
 
 class IndexRequestCollector : public SymbolIndex {
 public:
+  IndexRequestCollector(std::vector Syms = {}) : Symbols(Syms) {}
+
   bool
   fuzzyFind(const FuzzyFindRequest ,
 llvm::function_ref Callback) const override {
 std::unique_lock Lock(Mut);
 Requests.push_back(Req);
 ReceivedRequestCV.notify_one();
+for (const auto  : Symbols)
+  Callback(Sym);
 return true;
   }
 
@@ -1533,6 +1537,7 @@
   }
 
 private:
+  std::vector Symbols;
   // We need a mutex to handle async fuzzy find requests.
   mutable std::condition_variable ReceivedRequestCV;
   mutable std::mutex Mut;
@@ -3208,14 +3213,74 @@
   Symbol FoodClass = objcClass("FoodClass");
   Symbol SymFood = objcProtocol("Food");
   Symbol SymFooey = objcProtocol("Fooey");
+  auto Results = completions("id", {SymFood, FoodClass, SymFooey},
+ /*Opts=*/{}, "Foo.m");
+
+  // Should only give protocols for ObjC protocol completions.
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(
+  AllOf(named("Food"), kind(CompletionItemKind::Interface)),
+  AllOf(named("Fooey"), kind(CompletionItemKind::Interface;
+
+  Results = completions("Fo^", {SymFood, FoodClass, SymFooey},
+/*Opts=*/{}, "Foo.m");
+  // Shouldn't give protocols for non protocol completions.
+  EXPECT_THAT(
+  Results.Completions,
+  ElementsAre(AllOf(named("FoodClass"), kind(CompletionItemKind::Class;
+}
+
+TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {
+  MockFS FS;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
+
+  auto File = testPath("Foo.m");
+  Annotations Test(R"cpp(
+  @protocol Food
+  @end
+  id foo;
+  Foo$2^ bar;
+  )cpp");
+  runAddDocument(Server, File, Test.code());
+  clangd::CodeCompleteOptions Opts = {};
+
+  Symbol FoodClass = objcClass("FoodClass");
+  IndexRequestCollector Requests({FoodClass});
+  Opts.Index = 
+
+  auto CompleteAtPoint = [&](StringRef P) {
+return cantFail(runCodeComplete(Server, File, Test.point(P), Opts))
+.Completions;
+  };
+
+  auto C = CompleteAtPoint("1");
+  auto Reqs1 = Requests.consumeRequests(1);
+  ASSERT_EQ(Reqs1.size(), 1u);
+  EXPECT_THAT(C, ElementsAre(AllOf(named("Food"),
+   kind(CompletionItemKind::Interface;
+
+  C = CompleteAtPoint("2");
+  auto Reqs2 = Requests.consumeRequests(1);
+  // Speculation succeeded. Used speculative index result, but filtering now to
+  // now include FoodClass.
+  ASSERT_EQ(Reqs2.size(), 1u);
+  EXPECT_EQ(Reqs2[0], Reqs1[0]);
+  EXPECT_THAT(C, ElementsAre(AllOf(named("FoodClass"),
+   kind(CompletionItemKind::Class;
+}
+
+TEST(CompletionTest, ObjectiveCCategoryFromIndexIgnored) {
+  Symbol FoodCategory = objcCategory("FoodClass", "Extension");
   auto Results = completions(R"objc(
-  id
+  @interface Foo
+  @end
+  @interface Foo (^)
+  @end
 )objc",
-   

[PATCH] D132962: [clangd][ObjC] Improve completions for protocols + category names

2022-09-01 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 457257.
dgoldman added a comment.

Fix strings + test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132962/new/

https://reviews.llvm.org/D132962

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/TestIndex.cpp
  clang-tools-extra/clangd/unittests/TestIndex.h

Index: clang-tools-extra/clangd/unittests/TestIndex.h
===
--- clang-tools-extra/clangd/unittests/TestIndex.h
+++ clang-tools-extra/clangd/unittests/TestIndex.h
@@ -39,6 +39,8 @@
llvm::StringRef USRPrefix);
 // Create an @interface or @implementation.
 Symbol objcClass(llvm::StringRef Name);
+// Create an @interface or @implementation category.
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName);
 // Create an @protocol.
 Symbol objcProtocol(llvm::StringRef Name);
 
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -99,6 +99,11 @@
   return objcSym(Name, index::SymbolKind::Class, "objc(cs)");
 }
 
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName) {
+  std::string USRPrefix = ("objc(cy)" + Name + "@").str();
+  return objcSym(CategoryName, index::SymbolKind::Extension, USRPrefix);
+}
+
 Symbol objcProtocol(llvm::StringRef Name) {
   return objcSym(Name, index::SymbolKind::Protocol, "objc(pl)");
 }
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1493,12 +1493,16 @@
 
 class IndexRequestCollector : public SymbolIndex {
 public:
+  IndexRequestCollector(std::vector Syms = {}) : Symbols(Syms) {}
+
   bool
   fuzzyFind(const FuzzyFindRequest ,
 llvm::function_ref Callback) const override {
 std::unique_lock Lock(Mut);
 Requests.push_back(Req);
 ReceivedRequestCV.notify_one();
+for (const auto  : Symbols)
+  Callback(Sym);
 return true;
   }
 
@@ -1533,6 +1537,7 @@
   }
 
 private:
+  std::vector Symbols;
   // We need a mutex to handle async fuzzy find requests.
   mutable std::condition_variable ReceivedRequestCV;
   mutable std::mutex Mut;
@@ -3208,14 +3213,76 @@
   Symbol FoodClass = objcClass("FoodClass");
   Symbol SymFood = objcProtocol("Food");
   Symbol SymFooey = objcProtocol("Fooey");
-  auto Results = completions(R"objc(
-  id
-)objc",
+  auto Results = completions("id",
  {SymFood, FoodClass, SymFooey},
  /*Opts=*/{}, "Foo.m");
 
-  auto C = Results.Completions;
-  EXPECT_THAT(C, UnorderedElementsAre(named("Food"), named("Fooey")));
+  // Should only give protocols for ObjC protocol completions.
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(
+  AllOf(named("Food"), kind(CompletionItemKind::Interface)),
+  AllOf(named("Fooey"), kind(CompletionItemKind::Interface;
+
+  Results = completions("Fo^",
+{SymFood, FoodClass, SymFooey},
+/*Opts=*/{}, "Foo.m");
+  // Shouldn't give protocols for non protocol completions.
+  EXPECT_THAT(
+  Results.Completions,
+  ElementsAre(AllOf(named("FoodClass"), kind(CompletionItemKind::Class;
+}
+
+TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {
+  MockFS FS;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
+
+  auto File = testPath("Foo.m");
+  Annotations Test(R"cpp(
+  @protocol Food
+  @end
+  id foo;
+  Foo$2^ bar;
+  )cpp");
+  runAddDocument(Server, File, Test.code());
+  clangd::CodeCompleteOptions Opts = {};
+
+  Symbol FoodClass = objcClass("FoodClass");
+  IndexRequestCollector Requests({FoodClass});
+  Opts.Index = 
+
+  auto CompleteAtPoint = [&](StringRef P) {
+return cantFail(runCodeComplete(Server, File, Test.point(P), Opts))
+.Completions;
+  };
+
+  auto C = CompleteAtPoint("1");
+  auto Reqs1 = Requests.consumeRequests(1);
+  ASSERT_EQ(Reqs1.size(), 1u);
+  EXPECT_THAT(C, ElementsAre(AllOf(named("Food"),
+   kind(CompletionItemKind::Interface;
+
+  C = CompleteAtPoint("2");
+  auto Reqs2 = Requests.consumeRequests(1);
+  // Speculation succeeded. Used speculative index result, but filtering now to
+  // now include FoodClass.
+  ASSERT_EQ(Reqs2.size(), 1u);
+  EXPECT_EQ(Reqs2[0], Reqs1[0]);
+  EXPECT_THAT(C, ElementsAre(AllOf(named("FoodClass"),
+   kind(CompletionItemKind::Class;
+}
+
+TEST(CompletionTest, 

[PATCH] D132962: [clangd][ObjC] Improve completions for protocols + category names

2022-08-31 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 457067.
dgoldman added a comment.

Run clang format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132962/new/

https://reviews.llvm.org/D132962

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/TestIndex.cpp
  clang-tools-extra/clangd/unittests/TestIndex.h

Index: clang-tools-extra/clangd/unittests/TestIndex.h
===
--- clang-tools-extra/clangd/unittests/TestIndex.h
+++ clang-tools-extra/clangd/unittests/TestIndex.h
@@ -39,6 +39,8 @@
llvm::StringRef USRPrefix);
 // Create an @interface or @implementation.
 Symbol objcClass(llvm::StringRef Name);
+// Create an @interface or @implementation category.
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName);
 // Create an @protocol.
 Symbol objcProtocol(llvm::StringRef Name);
 
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -99,6 +99,11 @@
   return objcSym(Name, index::SymbolKind::Class, "objc(cs)");
 }
 
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName) {
+  std::string USRPrefix = ("objc(cy)" + Name + "@").str();
+  return objcSym(CategoryName, index::SymbolKind::Extension, USRPrefix);
+}
+
 Symbol objcProtocol(llvm::StringRef Name) {
   return objcSym(Name, index::SymbolKind::Protocol, "objc(pl)");
 }
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1493,12 +1493,16 @@
 
 class IndexRequestCollector : public SymbolIndex {
 public:
+  IndexRequestCollector(std::vector Syms = {}) : Symbols(Syms) {}
+
   bool
   fuzzyFind(const FuzzyFindRequest ,
 llvm::function_ref Callback) const override {
 std::unique_lock Lock(Mut);
 Requests.push_back(Req);
 ReceivedRequestCV.notify_one();
+for (const auto  : Symbols)
+  Callback(Sym);
 return true;
   }
 
@@ -1533,6 +1537,7 @@
   }
 
 private:
+  std::vector Symbols;
   // We need a mutex to handle async fuzzy find requests.
   mutable std::condition_variable ReceivedRequestCV;
   mutable std::mutex Mut;
@@ -3214,8 +3219,73 @@
  {SymFood, FoodClass, SymFooey},
  /*Opts=*/{}, "Foo.m");
 
-  auto C = Results.Completions;
-  EXPECT_THAT(C, UnorderedElementsAre(named("Food"), named("Fooey")));
+  // Should only give protocols for ObjC protocol completions.
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(
+  AllOf(named("Food"), kind(CompletionItemKind::Interface)),
+  AllOf(named("Fooey"), kind(CompletionItemKind::Interface;
+
+  Results = completions(R"objc(
+  Fo^
+)objc",
+{SymFood, FoodClass, SymFooey},
+/*Opts=*/{}, "Foo.m");
+  // Shouldn't give protocols for non protocol completions.
+  EXPECT_THAT(
+  Results.Completions,
+  ElementsAre(AllOf(named("FoodClass"), kind(CompletionItemKind::Class;
+}
+
+TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {
+  MockFS FS;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
+
+  auto File = testPath("Foo.m");
+  Annotations Test(R"cpp(
+  @protocol Food
+  @end
+  id foo;
+  )cpp");
+  runAddDocument(Server, File, Test.code());
+  clangd::CodeCompleteOptions Opts = {};
+
+  Symbol FoodClass = objcClass("FoodClass");
+  IndexRequestCollector Requests({FoodClass});
+  Opts.Index = 
+
+  auto CompleteAtPoint = [&](StringRef P) {
+return cantFail(runCodeComplete(Server, File, Test.point(P), Opts))
+.Completions;
+  };
+
+  auto C = CompleteAtPoint("1");
+  auto Reqs1 = Requests.consumeRequests(1);
+  ASSERT_EQ(Reqs1.size(), 1u);
+  EXPECT_THAT(C, ElementsAre(AllOf(named("Food"),
+   kind(CompletionItemKind::Interface;
+
+  C = CompleteAtPoint("1");
+  auto Reqs2 = Requests.consumeRequests(1);
+  // Speculation succeeded. Used speculative index result, keeping the same
+  // exact filtering as before to exclude the FoodClass result.
+  ASSERT_EQ(Reqs2.size(), 1u);
+  EXPECT_EQ(Reqs2[0], Reqs1[0]);
+  EXPECT_THAT(C, ElementsAre(AllOf(named("Food"),
+   kind(CompletionItemKind::Interface;
+}
+
+TEST(CompletionTest, ObjectiveCCategoryFromIndexIgnored) {
+  Symbol FoodCategory = objcCategory("FoodClass", "Extension");
+  auto Results = completions(R"objc(
+  @interface Foo
+  @end
+  @interface Foo (^)
+  @end
+

[PATCH] D132962: [clangd][ObjC] Improve completions for protocols + category names

2022-08-31 Thread David Goldman via Phabricator via cfe-commits
dgoldman added a comment.

In D132962#3761463 , @kadircet wrote:

> can you also add test cases for the other two (filtering both for speculative 
> index queries/regular ones, and making sure we don't suggest symbols from 
> index for category names), so that we don't regress in the future?

Done


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132962/new/

https://reviews.llvm.org/D132962

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132962: [clangd][ObjC] Improve completions for protocols + category names

2022-08-31 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 457049.
dgoldman added a comment.

Add tests


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132962/new/

https://reviews.llvm.org/D132962

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/TestIndex.cpp
  clang-tools-extra/clangd/unittests/TestIndex.h

Index: clang-tools-extra/clangd/unittests/TestIndex.h
===
--- clang-tools-extra/clangd/unittests/TestIndex.h
+++ clang-tools-extra/clangd/unittests/TestIndex.h
@@ -39,6 +39,8 @@
llvm::StringRef USRPrefix);
 // Create an @interface or @implementation.
 Symbol objcClass(llvm::StringRef Name);
+// Create an @interface or @implementation category.
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName);
 // Create an @protocol.
 Symbol objcProtocol(llvm::StringRef Name);
 
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -99,6 +99,11 @@
   return objcSym(Name, index::SymbolKind::Class, "objc(cs)");
 }
 
+Symbol objcCategory(llvm::StringRef Name, llvm::StringRef CategoryName) {
+  std::string USRPrefix = ("objc(cy)" + Name + "@").str();
+  return objcSym(CategoryName, index::SymbolKind::Extension, USRPrefix);
+}
+
 Symbol objcProtocol(llvm::StringRef Name) {
   return objcSym(Name, index::SymbolKind::Protocol, "objc(pl)");
 }
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1493,12 +1493,16 @@
 
 class IndexRequestCollector : public SymbolIndex {
 public:
+  IndexRequestCollector(std::vector Syms = {}) : Symbols(Syms) {}
+
   bool
   fuzzyFind(const FuzzyFindRequest ,
 llvm::function_ref Callback) const override {
 std::unique_lock Lock(Mut);
 Requests.push_back(Req);
 ReceivedRequestCV.notify_one();
+for (const auto  : Symbols)
+  Callback(Sym);
 return true;
   }
 
@@ -1533,6 +1537,7 @@
   }
 
 private:
+  std::vector Symbols;
   // We need a mutex to handle async fuzzy find requests.
   mutable std::condition_variable ReceivedRequestCV;
   mutable std::mutex Mut;
@@ -3214,8 +3219,74 @@
  {SymFood, FoodClass, SymFooey},
  /*Opts=*/{}, "Foo.m");
 
-  auto C = Results.Completions;
-  EXPECT_THAT(C, UnorderedElementsAre(named("Food"), named("Fooey")));
+  // Should only give protocols for ObjC protocol completions.
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(
+  AllOf(named("Food"), kind(CompletionItemKind::Interface)),
+  AllOf(named("Fooey"), kind(CompletionItemKind::Interface;
+
+  Results = completions(R"objc(
+  Fo^
+)objc",
+{SymFood, FoodClass, SymFooey},
+/*Opts=*/{}, "Foo.m");
+  // Shouldn't give protocols for non protocol completions.
+  EXPECT_THAT(Results.Completions,
+  ElementsAre(
+  AllOf(named("FoodClass"), kind(CompletionItemKind::Class;
+}
+
+TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {
+  MockFS FS;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
+
+  auto File = testPath("Foo.m");
+  Annotations Test(R"cpp(
+  @protocol Food
+  @end
+  id foo;
+  )cpp");
+  runAddDocument(Server, File, Test.code());
+  clangd::CodeCompleteOptions Opts = {};
+
+  Symbol FoodClass = objcClass("FoodClass");
+  IndexRequestCollector Requests({FoodClass});
+  Opts.Index = 
+
+  auto CompleteAtPoint = [&](StringRef P) {
+return cantFail(runCodeComplete(Server, File, Test.point(P), Opts)).Completions;
+  };
+
+  auto C = CompleteAtPoint("1");
+  auto Reqs1 = Requests.consumeRequests(1);
+  ASSERT_EQ(Reqs1.size(), 1u);
+  EXPECT_THAT(C,
+  ElementsAre(
+  AllOf(named("Food"), kind(CompletionItemKind::Interface;
+
+  C = CompleteAtPoint("1");
+  auto Reqs2 = Requests.consumeRequests(1);
+  // Speculation succeeded. Used speculative index result, keeping the same
+  // exact filtering as before to exclude the FoodClass result.
+  ASSERT_EQ(Reqs2.size(), 1u);
+  EXPECT_EQ(Reqs2[0], Reqs1[0]);
+  EXPECT_THAT(C,
+  ElementsAre(
+  AllOf(named("Food"), kind(CompletionItemKind::Interface;
+}
+
+TEST(CompletionTest, ObjectiveCCategoryFromIndexIgnored) {
+  Symbol FoodCategory = objcCategory("FoodClass", "Extension");
+  auto Results = completions(R"objc(
+  @interface Foo
+  @end
+  @interface Foo (^)
+  @end
+

[PATCH] D132962: [clangd][ObjC] Improve completions for protocols + category names

2022-08-30 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

- Render protocols as interfaces to differentiate them from classes since a 
protocol and class can have the same name

- Properly call `includeSymbolFromIndex` even with a cached speculative fuzzy 
find request

- Don't use the index to provide completions for category names, symbols there 
don't make sense


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D132962

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3215,7 +3215,10 @@
  /*Opts=*/{}, "Foo.m");
 
   auto C = Results.Completions;
-  EXPECT_THAT(C, UnorderedElementsAre(named("Food"), named("Fooey")));
+  EXPECT_THAT(C,
+  UnorderedElementsAre(
+  AllOf(named("Food"), kind(CompletionItemKind::Interface)),
+  AllOf(named("Fooey"), kind(CompletionItemKind::Interface;
 }
 
 TEST(CompletionTest, CursorInSnippets) {
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -94,10 +94,14 @@
   case SK::Struct:
 return CompletionItemKind::Struct;
   case SK::Class:
-  case SK::Protocol:
   case SK::Extension:
   case SK::Union:
 return CompletionItemKind::Class;
+  case SK::Protocol:
+// Use interface instead of class for differentiation of classes and
+// protocols with the same name (e.g. @interface NSObject vs. @protocol
+// NSObject).
+return CompletionItemKind::Interface;
   case SK::TypeAlias:
 // We use the same kind as the VSCode C++ extension.
 // FIXME: pick a better option when we have one.
@@ -712,13 +716,13 @@
   case CodeCompletionContext::CCC_Type:
   case CodeCompletionContext::CCC_ParenthesizedExpression:
   case CodeCompletionContext::CCC_ObjCInterfaceName:
-  case CodeCompletionContext::CCC_ObjCCategoryName:
   case CodeCompletionContext::CCC_Symbol:
   case CodeCompletionContext::CCC_SymbolOrNewName:
 return true;
   case CodeCompletionContext::CCC_OtherWithMacros:
   case CodeCompletionContext::CCC_DotMemberAccess:
   case CodeCompletionContext::CCC_ArrowMemberAccess:
+  case CodeCompletionContext::CCC_ObjCCategoryName:
   case CodeCompletionContext::CCC_ObjCPropertyAccess:
   case CodeCompletionContext::CCC_MacroName:
   case CodeCompletionContext::CCC_MacroNameUse:
@@ -1343,6 +1347,22 @@
   llvm_unreachable("invalid NestedNameSpecifier kind");
 }
 
+// Should we include a symbol from the index given the completion kind?
+// FIXME: Ideally we can filter in the fuzzy find request itself.
+bool includeSymbolFromIndex(CodeCompletionContext::Kind Kind,
+const Symbol ) {
+  // Objective-C protocols are only useful in ObjC protocol completions,
+  // in other places they're confusing, especially when they share the same
+  // identifier with a class.
+  if (Sym.SymInfo.Kind == index::SymbolKind::Protocol &&
+  Sym.SymInfo.Lang == index::SymbolLanguage::ObjC)
+return Kind == CodeCompletionContext::CCC_ObjCProtocolName;
+  else if (Kind == CodeCompletionContext::CCC_ObjCProtocolName)
+// Don't show anything else in ObjC protocol completions.
+return false;
+  return true;
+}
+
 std::future startAsyncFuzzyFind(const SymbolIndex ,
 const FuzzyFindRequest ) {
   return runAsync([, Req]() {
@@ -1675,14 +1695,6 @@
 return Output;
   }
 
-  bool includeSymbolFromIndex(const Symbol ) {
-if (CCContextKind == CodeCompletionContext::CCC_ObjCProtocolName) {
-  return Sym.SymInfo.Lang == index::SymbolLanguage::ObjC &&
-  Sym.SymInfo.Kind == index::SymbolKind::Protocol;
-}
-return true;
-  }
-
   SymbolSlab queryIndex() {
 trace::Span Tracer("Query index");
 SPAN_ATTACH(Tracer, "limit", int64_t(Opts.Limit));
@@ -1716,10 +1728,8 @@
 
 // Run the query against the index.
 SymbolSlab::Builder ResultsBuilder;
-if (Opts.Index->fuzzyFind(Req, [&](const Symbol ) {
-  if (includeSymbolFromIndex(Sym))
-ResultsBuilder.insert(Sym);
-}))
+if (Opts.Index->fuzzyFind(
+Req, [&](const Symbol ) { ResultsBuilder.insert(Sym); }))
   Incomplete = true;
 return std::move(ResultsBuilder).build();
   }
@@ -1783,6 +1793,8 @@
 for (const auto  : IndexResults) {
   if (UsedIndexResults.count())
 continue;

[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-08-01 Thread David Goldman via Phabricator via cfe-commits
dgoldman added a comment.

Ah my bad didn't realize you hadn't accepted this, was there anything else you 
wanted me to change?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-08-01 Thread David Goldman via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rG61ef0ab70196: [clangd] Add decl/def support to SymbolDetails 
(authored by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/test/symbol-info.test
  clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp

Index: clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
@@ -18,45 +18,79 @@
 
 using ::testing::UnorderedElementsAreArray;
 
-auto CreateExpectedSymbolDetails = [](const std::string ,
-  const std::string ,
-  const std::string ) {
-  return SymbolDetails{Name, Container, USR, SymbolID(USR)};
+// Partial SymbolDetails with the rest filled in at testing time.
+struct ExpectedSymbolDetails {
+  std::string Name;
+  std::string Container;
+  std::string USR;
+  const char *DeclMarker = nullptr;
+  const char *DefMarker = nullptr;
 };
 
 TEST(SymbolInfoTests, All) {
-  std::pair>
+  std::pair>
   TestInputExpectedOutput[] = {
   {
   R"cpp( // Simple function reference - declaration
-  void foo();
+  void $decl[[foo]]();
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Simple function reference - definition
-  void foo() {}
+  void $def[[foo]]() {}
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"}}},
+  {
+  R"cpp( // Simple function reference - decl and def
+  void $decl[[foo]]();
+  void $def[[foo]]() {}
+  int bar() {
+fo^o();
+  }
+)cpp",
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl", "def"}}},
+  {
+  R"cpp( // Simple class reference - decl and def
+  @interface $decl[[Foo]]
+  @end
+  @implementation $def[[Foo]]
+  @end
+  void doSomething(F^oo *obj) {}
+)cpp",
+  {ExpectedSymbolDetails{"Foo", "", "c:objc(cs)Foo", "decl",
+ "def"}}},
+  {
+  R"cpp( // Simple method reference - decl and def
+  @interface Foo
+  - (void)$decl[[foo]];
+  @end
+  @implementation Foo
+  - (void)$def[[fo^o]] {}
+  @end
+)cpp",
+  {ExpectedSymbolDetails{"foo", "Foo::", "c:objc(cs)Foo(im)foo",
+ "decl", "def"}}},
   {
   R"cpp( // Function in namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
 int baz() {
   fo^o();
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
+ "decl"}}},
   {
   R"cpp( // Function in different namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -64,10 +98,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
+ "decl"}}},
   {
   R"cpp( // Function in global namespace reference
-  void foo();
+  void $decl[[foo]]();
   namespace Nbar {
 namespace Nbaz {
   int baz() {
@@ -76,11 +111,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Function in anonymous namespace reference
   namespace {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -88,13 +123,13 @@
 }
   }
 )cpp",
-   

[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-08-01 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 449050.
dgoldman added a comment.

Run clang-format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/test/symbol-info.test
  clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp

Index: clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
@@ -18,45 +18,79 @@
 
 using ::testing::UnorderedElementsAreArray;
 
-auto CreateExpectedSymbolDetails = [](const std::string ,
-  const std::string ,
-  const std::string ) {
-  return SymbolDetails{Name, Container, USR, SymbolID(USR)};
+// Partial SymbolDetails with the rest filled in at testing time.
+struct ExpectedSymbolDetails {
+  std::string Name;
+  std::string Container;
+  std::string USR;
+  const char *DeclMarker = nullptr;
+  const char *DefMarker = nullptr;
 };
 
 TEST(SymbolInfoTests, All) {
-  std::pair>
+  std::pair>
   TestInputExpectedOutput[] = {
   {
   R"cpp( // Simple function reference - declaration
-  void foo();
+  void $decl[[foo]]();
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Simple function reference - definition
-  void foo() {}
+  void $def[[foo]]() {}
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"}}},
+  {
+  R"cpp( // Simple function reference - decl and def
+  void $decl[[foo]]();
+  void $def[[foo]]() {}
+  int bar() {
+fo^o();
+  }
+)cpp",
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl", "def"}}},
+  {
+  R"cpp( // Simple class reference - decl and def
+  @interface $decl[[Foo]]
+  @end
+  @implementation $def[[Foo]]
+  @end
+  void doSomething(F^oo *obj) {}
+)cpp",
+  {ExpectedSymbolDetails{"Foo", "", "c:objc(cs)Foo", "decl",
+ "def"}}},
+  {
+  R"cpp( // Simple method reference - decl and def
+  @interface Foo
+  - (void)$decl[[foo]];
+  @end
+  @implementation Foo
+  - (void)$def[[fo^o]] {}
+  @end
+)cpp",
+  {ExpectedSymbolDetails{"foo", "Foo::", "c:objc(cs)Foo(im)foo",
+ "decl", "def"}}},
   {
   R"cpp( // Function in namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
 int baz() {
   fo^o();
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
+ "decl"}}},
   {
   R"cpp( // Function in different namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -64,10 +98,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
+ "decl"}}},
   {
   R"cpp( // Function in global namespace reference
-  void foo();
+  void $decl[[foo]]();
   namespace Nbar {
 namespace Nbaz {
   int baz() {
@@ -76,11 +111,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Function in anonymous namespace reference
   namespace {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -88,13 +123,13 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "(anonymous)",
-   "c:TestTU.cpp@aN@F@foo#")}},
+  

[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-08-01 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 449033.
dgoldman added a comment.

Fix broken test and swap to AST.tuPath()


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/test/symbol-info.test
  clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp

Index: clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
@@ -18,45 +18,79 @@
 
 using ::testing::UnorderedElementsAreArray;
 
-auto CreateExpectedSymbolDetails = [](const std::string ,
-  const std::string ,
-  const std::string ) {
-  return SymbolDetails{Name, Container, USR, SymbolID(USR)};
+// Partial SymbolDetails with the rest filled in at testing time.
+struct ExpectedSymbolDetails {
+  std::string Name;
+  std::string Container;
+  std::string USR;
+  const char *DeclMarker = nullptr;
+  const char *DefMarker = nullptr;
 };
 
 TEST(SymbolInfoTests, All) {
-  std::pair>
+  std::pair>
   TestInputExpectedOutput[] = {
   {
   R"cpp( // Simple function reference - declaration
-  void foo();
+  void $decl[[foo]]();
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Simple function reference - definition
-  void foo() {}
+  void $def[[foo]]() {}
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"}}},
+  {
+  R"cpp( // Simple function reference - decl and def
+  void $decl[[foo]]();
+  void $def[[foo]]() {}
+  int bar() {
+fo^o();
+  }
+)cpp",
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl", "def"}}},
+  {
+  R"cpp( // Simple class reference - decl and def
+  @interface $decl[[Foo]]
+  @end
+  @implementation $def[[Foo]]
+  @end
+  void doSomething(F^oo *obj) {}
+)cpp",
+  {ExpectedSymbolDetails{"Foo", "", "c:objc(cs)Foo", "decl",
+ "def"}}},
+  {
+  R"cpp( // Simple method reference - decl and def
+  @interface Foo
+  - (void)$decl[[foo]];
+  @end
+  @implementation Foo
+  - (void)$def[[fo^o]] {}
+  @end
+)cpp",
+  {ExpectedSymbolDetails{"foo", "Foo::", "c:objc(cs)Foo(im)foo",
+ "decl", "def"}}},
   {
   R"cpp( // Function in namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
 int baz() {
   fo^o();
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
+ "decl"}}},
   {
   R"cpp( // Function in different namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -64,10 +98,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
+ "decl"}}},
   {
   R"cpp( // Function in global namespace reference
-  void foo();
+  void $decl[[foo]]();
   namespace Nbar {
 namespace Nbaz {
   int baz() {
@@ -76,11 +111,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Function in anonymous namespace reference
   namespace {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -88,13 +123,13 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "(anonymous)",
-   "c:TestTU.cpp@aN@F@foo#")}},
+  

[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-07-26 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/XRefs.cpp:1528
   }
-
+  auto MainFilePath =
+  getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);

dgoldman wrote:
> sammccall wrote:
> > kadircet wrote:
> > > let's just pass the TUPath from ClangdServer into the request. (we should 
> > > do the same for `locateSymbolAt`, but on a separate change)
> > driveby: @kadircet any reason not to store the TUPath on ParsedAST? We 
> > already pass it to ParsedAST::build()
> I think this would simplify things quite a bit - otherwise I also need to 
> update the DumpSymbol tweak to store/compute the TUPath (or just provide an 
> empty one). LMK what I should do.
Also, not sure how this would affect the Windows failure, which currently fails 
since the decl/definition locations reference 
"file:///C:/clangd-test/simple.cpp" instead of "test:///simple.cpp"... could 
add a regex or limit the test to non-Windows as a work around though. 
"textDocument/publishDiagnostics" also seems to reference that absolute path as 
well instead of the test:// URI


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-07-26 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 447813.
dgoldman added a comment.

Run clang-format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/test/symbol-info.test
  clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp

Index: clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
@@ -18,45 +18,79 @@
 
 using ::testing::UnorderedElementsAreArray;
 
-auto CreateExpectedSymbolDetails = [](const std::string ,
-  const std::string ,
-  const std::string ) {
-  return SymbolDetails{Name, Container, USR, SymbolID(USR)};
+// Partial SymbolDetails with the rest filled in at testing time.
+struct ExpectedSymbolDetails {
+  std::string Name;
+  std::string Container;
+  std::string USR;
+  const char *DeclMarker = nullptr;
+  const char *DefMarker = nullptr;
 };
 
 TEST(SymbolInfoTests, All) {
-  std::pair>
+  std::pair>
   TestInputExpectedOutput[] = {
   {
   R"cpp( // Simple function reference - declaration
-  void foo();
+  void $decl[[foo]]();
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Simple function reference - definition
-  void foo() {}
+  void $def[[foo]]() {}
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"}}},
+  {
+  R"cpp( // Simple function reference - decl and def
+  void $decl[[foo]]();
+  void $def[[foo]]() {}
+  int bar() {
+fo^o();
+  }
+)cpp",
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl", "def"}}},
+  {
+  R"cpp( // Simple class reference - decl and def
+  @interface $decl[[Foo]]
+  @end
+  @implementation $def[[Foo]]
+  @end
+  void doSomething(F^oo *obj) {}
+)cpp",
+  {ExpectedSymbolDetails{"Foo", "", "c:objc(cs)Foo", "decl",
+ "def"}}},
+  {
+  R"cpp( // Simple method reference - decl and def
+  @interface Foo
+  - (void)$decl[[foo]];
+  @end
+  @implementation Foo
+  - (void)$def[[fo^o]] {}
+  @end
+)cpp",
+  {ExpectedSymbolDetails{"foo", "Foo::", "c:objc(cs)Foo(im)foo",
+ "decl", "def"}}},
   {
   R"cpp( // Function in namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
 int baz() {
   fo^o();
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
+ "decl"}}},
   {
   R"cpp( // Function in different namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -64,10 +98,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#",
+ "decl"}}},
   {
   R"cpp( // Function in global namespace reference
-  void foo();
+  void $decl[[foo]]();
   namespace Nbar {
 namespace Nbaz {
   int baz() {
@@ -76,11 +111,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Function in anonymous namespace reference
   namespace {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -88,13 +123,13 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "(anonymous)",
-   "c:TestTU.cpp@aN@F@foo#")}},
+  

[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-07-26 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/XRefs.cpp:1528
   }
-
+  auto MainFilePath =
+  getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);

sammccall wrote:
> kadircet wrote:
> > let's just pass the TUPath from ClangdServer into the request. (we should 
> > do the same for `locateSymbolAt`, but on a separate change)
> driveby: @kadircet any reason not to store the TUPath on ParsedAST? We 
> already pass it to ParsedAST::build()
I think this would simplify things quite a bit - otherwise I also need to 
update the DumpSymbol tweak to store/compute the TUPath (or just provide an 
empty one). LMK what I should do.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-07-26 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 447771.
dgoldman marked 5 inline comments as done.
dgoldman added a comment.

Minor fixes for review (some still pending based on discussion)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/test/symbol-info.test
  clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp

Index: clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
@@ -18,45 +18,76 @@
 
 using ::testing::UnorderedElementsAreArray;
 
-auto CreateExpectedSymbolDetails = [](const std::string ,
-  const std::string ,
-  const std::string ) {
-  return SymbolDetails{Name, Container, USR, SymbolID(USR)};
+// Partial SymbolDetails with the rest filled in at testing time.
+struct ExpectedSymbolDetails {
+  std::string Name;
+  std::string Container;
+  std::string USR;
+  const char *DeclMarker = nullptr;
+  const char *DefMarker = nullptr;
 };
 
 TEST(SymbolInfoTests, All) {
-  std::pair>
+  std::pair>
   TestInputExpectedOutput[] = {
   {
   R"cpp( // Simple function reference - declaration
-  void foo();
+  void $decl[[foo]]();
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Simple function reference - definition
-  void foo() {}
+  void $def[[foo]]() {}
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"}}},
+  {
+  R"cpp( // Simple function reference - decl and def
+  void $decl[[foo]]();
+  void $def[[foo]]() {}
+  int bar() {
+fo^o();
+  }
+)cpp",
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl", "def"}}},
+  {
+  R"cpp( // Simple class reference - decl and def
+  @interface $decl[[Foo]]
+  @end
+  @implementation $def[[Foo]]
+  @end
+  void doSomething(F^oo *obj) {}
+)cpp",
+  {ExpectedSymbolDetails{"Foo", "", "c:objc(cs)Foo", "decl", "def"}}},
+  {
+  R"cpp( // Simple method reference - decl and def
+  @interface Foo
+  - (void)$decl[[foo]];
+  @end
+  @implementation Foo
+  - (void)$def[[fo^o]] {}
+  @end
+)cpp",
+  {ExpectedSymbolDetails{"foo", "Foo::", "c:objc(cs)Foo(im)foo", "decl", "def"}}},
   {
   R"cpp( // Function in namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
 int baz() {
   fo^o();
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#", "decl"}}},
   {
   R"cpp( // Function in different namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -64,10 +95,10 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#", "decl"}}},
   {
   R"cpp( // Function in global namespace reference
-  void foo();
+  void $decl[[foo]]();
   namespace Nbar {
 namespace Nbaz {
   int baz() {
@@ -76,11 +107,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Function in anonymous namespace reference
   namespace {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -88,13 +119,13 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "(anonymous)",
-   "c:TestTU.cpp@aN@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "(anonymous)",
+ 

[PATCH] D130095: [clangd] Improve XRefs support for ObjCMethodDecl

2022-07-26 Thread David Goldman via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG88a2ac6ad623: [clangd] Improve XRefs support for 
ObjCMethodDecl (authored by dgoldman).

Changed prior to commit:
  https://reviews.llvm.org/D130095?vs=445951=447739#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130095/new/

https://reviews.llvm.org/D130095

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -957,6 +957,46 @@
 Fo^o * getFoo() {
   return 0;
 }
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC class.
+@interface Cat
+- (void)$decl[[meow]];
+@end
+@implementation Cat
+- (void)$def[[meow]] {}
+@end
+void makeNoise(Cat *kitty) {
+  [kitty me^ow];
+}
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC category.
+@interface Dog
+@end
+@interface Dog (Play)
+- (void)$decl[[runAround]];
+@end
+@implementation Dog (Play)
+- (void)$def[[runAround]] {}
+@end
+void play(Dog *dog) {
+  [dog run^Around];
+}
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC class extension.
+@interface Dog
+@end
+@interface Dog ()
+- (void)$decl[[howl]];
+@end
+@implementation Dog
+- (void)$def[[howl]] {}
+@end
+void play(Dog *dog) {
+  [dog ho^wl];
+}
   )objc"};
   for (const char *Test : Tests) {
 Annotations T(Test);
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -83,32 +83,20 @@
   if (const auto *CTD = dyn_cast(D))
 if (const auto *RD = CTD->getTemplatedDecl())
   return RD->getDefinition();
-  // Objective-C classes can have three types of declarations:
-  //
-  // - forward declaration: @class MyClass;
-  // - true declaration (interface definition): @interface MyClass ... @end
-  // - true definition (implementation): @implementation MyClass ... @end
-  //
-  // Objective-C categories are extensions are on classes:
-  //
-  // - declaration: @interface MyClass (Ext) ... @end
-  // - definition: @implementation MyClass (Ext) ... @end
-  //
-  // With one special case, a class extension, which is normally used to keep
-  // some declarations internal to a file without exposing them in a header.
-  //
-  // - class extension declaration: @interface MyClass () ... @end
-  // - which really links to class definition: @implementation MyClass ... @end
-  if (const auto *ID = dyn_cast(D))
-return ID->getImplementation();
-  if (const auto *CD = dyn_cast(D)) {
-if (CD->IsClassExtension()) {
-  if (const auto *ID = CD->getClassInterface())
-return ID->getImplementation();
+  if (const auto *MD = dyn_cast(D)) {
+if (MD->isThisDeclarationADefinition())
+  return MD;
+// Look for the method definition inside the implementation decl.
+auto *DeclCtx = cast(MD->getDeclContext());
+if (DeclCtx->isInvalidDecl())
   return nullptr;
-}
-return CD->getImplementation();
+
+if (const auto *CD = dyn_cast(DeclCtx))
+  if (const auto *Impl = getCorrespondingObjCImpl(CD))
+return Impl->getMethod(MD->getSelector(), MD->isInstanceMethod());
   }
+  if (const auto *CD = dyn_cast(D))
+return getCorrespondingObjCImpl(CD);
   // Only a single declaration is allowed.
   if (isa(D) || isa(D) ||
   isa(D)) // except cases above
Index: clang-tools-extra/clangd/AST.h
===
--- clang-tools-extra/clangd/AST.h
+++ clang-tools-extra/clangd/AST.h
@@ -93,6 +93,30 @@
 SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI,
  const SourceManager );
 
+/// Return the corresponding implementation/definition for the given ObjC
+/// container if it has one, otherwise, return nullptr.
+///
+/// Objective-C classes can have three types of declarations:
+///
+/// - forward declaration: @class MyClass;
+/// - true declaration (interface definition): @interface MyClass ... @end
+/// - true definition (implementation): @implementation MyClass ... @end
+///
+/// Objective-C categories are extensions on classes:
+///
+/// - declaration: @interface MyClass (Ext) ... @end
+/// - definition: @implementation MyClass (Ext) ... @end
+///
+/// With one special case, a class extension, which is normally used to keep
+/// some 

[PATCH] D130095: [clangd] Improve XRefs support for ObjCMethodDecl

2022-07-19 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 445951.
dgoldman added a comment.

Minor grammar update to comment


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130095/new/

https://reviews.llvm.org/D130095

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -957,6 +957,46 @@
 Fo^o * getFoo() {
   return 0;
 }
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC class.
+@interface Cat
+- (void)$decl[[meow]];
+@end
+@implementation Cat
+- (void)$def[[meow]] {}
+@end
+void makeNoise(Cat *kitty) {
+  [kitty me^ow];
+}
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC category.
+@interface Dog
+@end
+@interface Dog (Play)
+- (void)$decl[[runAround]];
+@end
+@implementation Dog (Play)
+- (void)$def[[runAround]] {}
+@end
+void play(Dog *dog) {
+  [dog run^Around];
+}
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC class extension.
+@interface Dog
+@end
+@interface Dog ()
+- (void)$decl[[howl]];
+@end
+@implementation Dog
+- (void)$def[[howl]] {}
+@end
+void play(Dog *dog) {
+  [dog ho^wl];
+}
   )objc"};
   for (const char *Test : Tests) {
 Annotations T(Test);
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -83,32 +83,19 @@
   if (const auto *CTD = dyn_cast(D))
 if (const auto *RD = CTD->getTemplatedDecl())
   return RD->getDefinition();
-  // Objective-C classes can have three types of declarations:
-  //
-  // - forward declaration: @class MyClass;
-  // - true declaration (interface definition): @interface MyClass ... @end
-  // - true definition (implementation): @implementation MyClass ... @end
-  //
-  // Objective-C categories are extensions are on classes:
-  //
-  // - declaration: @interface MyClass (Ext) ... @end
-  // - definition: @implementation MyClass (Ext) ... @end
-  //
-  // With one special case, a class extension, which is normally used to keep
-  // some declarations internal to a file without exposing them in a header.
-  //
-  // - class extension declaration: @interface MyClass () ... @end
-  // - which really links to class definition: @implementation MyClass ... @end
-  if (const auto *ID = dyn_cast(D))
-return ID->getImplementation();
-  if (const auto *CD = dyn_cast(D)) {
-if (CD->IsClassExtension()) {
-  if (const auto *ID = CD->getClassInterface())
-return ID->getImplementation();
+  if (const auto *MD = dyn_cast(D)) {
+if (MD->isThisDeclarationADefinition())
+  return MD;
+auto *DeclCtx = cast(MD->getDeclContext());
+if (DeclCtx->isInvalidDecl())
   return nullptr;
-}
-return CD->getImplementation();
+
+if (const auto *CD = dyn_cast(DeclCtx))
+  if (const auto *Impl = getCorrespondingObjCImpl(CD))
+return Impl->getMethod(MD->getSelector(), MD->isInstanceMethod());
   }
+  if (const auto *CD = dyn_cast(D))
+return getCorrespondingObjCImpl(CD);
   // Only a single declaration is allowed.
   if (isa(D) || isa(D) ||
   isa(D)) // except cases above
Index: clang-tools-extra/clangd/AST.h
===
--- clang-tools-extra/clangd/AST.h
+++ clang-tools-extra/clangd/AST.h
@@ -93,6 +93,30 @@
 SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI,
  const SourceManager );
 
+/// Return the corresponding implementation/definition for the given ObjC
+/// container if it has one, otherwise, return nullptr.
+///
+/// Objective-C classes can have three types of declarations:
+///
+/// - forward declaration: @class MyClass;
+/// - true declaration (interface definition): @interface MyClass ... @end
+/// - true definition (implementation): @implementation MyClass ... @end
+///
+/// Objective-C categories are extensions on classes:
+///
+/// - declaration: @interface MyClass (Ext) ... @end
+/// - definition: @implementation MyClass (Ext) ... @end
+///
+/// With one special case, a class extension, which is normally used to keep
+/// some declarations internal to a file without exposing them in a header.
+///
+/// - class extension declaration: @interface MyClass () ... @end
+/// - which really links to class definition: @implementation MyClass ... @end
+///
+/// For 

[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-07-19 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/AST.cpp:174
   auto L = D.getLocation();
+  // Use the start of the first selector fragment instead of the -/+ location.
+  if (const auto *MD = dyn_cast())

kadircet wrote:
> can we do this in a separate change? as it has wider implications
Sent out https://reviews.llvm.org/D130095, will rebase this on top once that's 
submitted.



Comment at: clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp:29
+
+  const char *DeclMarker = nullptr;
+  const char *DefMarker = nullptr;

kadircet wrote:
> since you're always calling these `decl` or `def`, you can instead check 
> whether the annotation has any range named `def`/`decl` and expect those 
> accordingly rather than mentioning them one extra time inside the testcases. 
> i.e:
> 
> case:
> 
> ```
> void $def[[foo]]() {}
>   int bar() {
> fo^o();
>   }
> ```
> 
> check:
> ```
> Annotations Test(Case);
> SymbolDetails Expected;
> auto Def = Test.ranges("def");
> auto Decl = Test.ranges("decl");
> if (!Def.empty()) {
>   Expected.decl = Expected.def = makelocation ...
> } else if (!Decl.empty()) {
>   Expected.decl = makelocation ...
> }
> ```
Thanks, although that won't work for the `// Multiple symbols returned - using 
overloaded function name` test case. Should I move that one out to to be 
handled separately?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130095: [clangd] Improve XRefs support for ObjCMethodDecl

2022-07-19 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 445873.
dgoldman added a comment.

Run clang-format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130095/new/

https://reviews.llvm.org/D130095

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -957,6 +957,46 @@
 Fo^o * getFoo() {
   return 0;
 }
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC class.
+@interface Cat
+- (void)$decl[[meow]];
+@end
+@implementation Cat
+- (void)$def[[meow]] {}
+@end
+void makeNoise(Cat *kitty) {
+  [kitty me^ow];
+}
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC category.
+@interface Dog
+@end
+@interface Dog (Play)
+- (void)$decl[[runAround]];
+@end
+@implementation Dog (Play)
+- (void)$def[[runAround]] {}
+@end
+void play(Dog *dog) {
+  [dog run^Around];
+}
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC class extension.
+@interface Dog
+@end
+@interface Dog ()
+- (void)$decl[[howl]];
+@end
+@implementation Dog
+- (void)$def[[howl]] {}
+@end
+void play(Dog *dog) {
+  [dog ho^wl];
+}
   )objc"};
   for (const char *Test : Tests) {
 Annotations T(Test);
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -83,32 +83,19 @@
   if (const auto *CTD = dyn_cast(D))
 if (const auto *RD = CTD->getTemplatedDecl())
   return RD->getDefinition();
-  // Objective-C classes can have three types of declarations:
-  //
-  // - forward declaration: @class MyClass;
-  // - true declaration (interface definition): @interface MyClass ... @end
-  // - true definition (implementation): @implementation MyClass ... @end
-  //
-  // Objective-C categories are extensions are on classes:
-  //
-  // - declaration: @interface MyClass (Ext) ... @end
-  // - definition: @implementation MyClass (Ext) ... @end
-  //
-  // With one special case, a class extension, which is normally used to keep
-  // some declarations internal to a file without exposing them in a header.
-  //
-  // - class extension declaration: @interface MyClass () ... @end
-  // - which really links to class definition: @implementation MyClass ... @end
-  if (const auto *ID = dyn_cast(D))
-return ID->getImplementation();
-  if (const auto *CD = dyn_cast(D)) {
-if (CD->IsClassExtension()) {
-  if (const auto *ID = CD->getClassInterface())
-return ID->getImplementation();
+  if (const auto *MD = dyn_cast(D)) {
+if (MD->isThisDeclarationADefinition())
+  return MD;
+auto *DeclCtx = cast(MD->getDeclContext());
+if (DeclCtx->isInvalidDecl())
   return nullptr;
-}
-return CD->getImplementation();
+
+if (const auto *CD = dyn_cast(DeclCtx))
+  if (const auto *Impl = getCorrespondingObjCImpl(CD))
+return Impl->getMethod(MD->getSelector(), MD->isInstanceMethod());
   }
+  if (const auto *CD = dyn_cast(D))
+return getCorrespondingObjCImpl(CD);
   // Only a single declaration is allowed.
   if (isa(D) || isa(D) ||
   isa(D)) // except cases above
Index: clang-tools-extra/clangd/AST.h
===
--- clang-tools-extra/clangd/AST.h
+++ clang-tools-extra/clangd/AST.h
@@ -93,6 +93,30 @@
 SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI,
  const SourceManager );
 
+/// Return the corresponding implementation/definition for the given ObjC
+/// container if it has one, otherwise, return nullptr.
+///
+/// Objective-C classes can have three types of declarations:
+///
+/// - forward declaration: @class MyClass;
+/// - true declaration (interface definition): @interface MyClass ... @end
+/// - true definition (implementation): @implementation MyClass ... @end
+///
+/// Objective-C categories are extensions are on classes:
+///
+/// - declaration: @interface MyClass (Ext) ... @end
+/// - definition: @implementation MyClass (Ext) ... @end
+///
+/// With one special case, a class extension, which is normally used to keep
+/// some declarations internal to a file without exposing them in a header.
+///
+/// - class extension declaration: @interface MyClass () ... @end
+/// - which really links to class definition: @implementation MyClass ... @end
+///
+/// For Objective-C 

[PATCH] D130095: [clangd] Improve XRefs support for ObjCMethodDecl

2022-07-19 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added a reviewer: kadircet.
Herald added subscribers: usaxena95, arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

- Correct nameLocation to point to the first selector fragment instead of the - 
or +

- getDefinition now searches through the proper impl decls to find the 
definition of the ObjCMethodDecl if one exists


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130095

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -957,6 +957,46 @@
 Fo^o * getFoo() {
   return 0;
 }
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC class.
+@interface Cat
+- (void)$decl[[meow]];
+@end
+@implementation Cat
+- (void)$def[[meow]] {}
+@end
+void makeNoise(Cat *kitty) {
+  [kitty me^ow];
+}
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC category.
+@interface Dog
+@end
+@interface Dog (Play)
+- (void)$decl[[runAround]];
+@end
+@implementation Dog (Play)
+- (void)$def[[runAround]] {}
+@end
+void play(Dog *dog) {
+  [dog run^Around];
+}
+  )objc",
+
+  R"objc(// Method decl and definition for ObjC class extension.
+@interface Dog
+@end
+@interface Dog ()
+- (void)$decl[[howl]];
+@end
+@implementation Dog
+- (void)$def[[howl]] {}
+@end
+void play(Dog *dog) {
+  [dog ho^wl];
+}
   )objc"};
   for (const char *Test : Tests) {
 Annotations T(Test);
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -83,32 +83,19 @@
   if (const auto *CTD = dyn_cast(D))
 if (const auto *RD = CTD->getTemplatedDecl())
   return RD->getDefinition();
-  // Objective-C classes can have three types of declarations:
-  //
-  // - forward declaration: @class MyClass;
-  // - true declaration (interface definition): @interface MyClass ... @end
-  // - true definition (implementation): @implementation MyClass ... @end
-  //
-  // Objective-C categories are extensions are on classes:
-  //
-  // - declaration: @interface MyClass (Ext) ... @end
-  // - definition: @implementation MyClass (Ext) ... @end
-  //
-  // With one special case, a class extension, which is normally used to keep
-  // some declarations internal to a file without exposing them in a header.
-  //
-  // - class extension declaration: @interface MyClass () ... @end
-  // - which really links to class definition: @implementation MyClass ... @end
-  if (const auto *ID = dyn_cast(D))
-return ID->getImplementation();
-  if (const auto *CD = dyn_cast(D)) {
-if (CD->IsClassExtension()) {
-  if (const auto *ID = CD->getClassInterface())
-return ID->getImplementation();
+  if (const auto *MD = dyn_cast(D)) {
+if (MD->isThisDeclarationADefinition())
+  return MD;
+auto *DeclCtx = cast(MD->getDeclContext());
+if (DeclCtx->isInvalidDecl())
   return nullptr;
-}
-return CD->getImplementation();
+
+if (const auto *CD = dyn_cast(DeclCtx))
+  if (const auto *Impl = getCorrespondingObjCImpl(CD))
+return Impl->getMethod(MD->getSelector(), MD->isInstanceMethod());
   }
+  if (const auto *CD = dyn_cast(D))
+return getCorrespondingObjCImpl(CD);
   // Only a single declaration is allowed.
   if (isa(D) || isa(D) ||
   isa(D)) // except cases above
Index: clang-tools-extra/clangd/AST.h
===
--- clang-tools-extra/clangd/AST.h
+++ clang-tools-extra/clangd/AST.h
@@ -93,6 +93,30 @@
 SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI,
  const SourceManager );
 
+/// Return the corresponding implementation/definition for the given ObjC
+/// container if it has one, otherwise, return nullptr.
+///
+/// Objective-C classes can have three types of declarations:
+///
+/// - forward declaration: @class MyClass;
+/// - true declaration (interface definition): @interface MyClass ... @end
+/// - true definition (implementation): @implementation MyClass ... @end
+///
+/// Objective-C categories are extensions are on classes:
+///
+/// - declaration: @interface MyClass (Ext) ... @end
+/// - definition: @implementation MyClass (Ext) ... 

[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-07-18 Thread David Goldman via Phabricator via cfe-commits
dgoldman added a comment.

For more context see the discussion on b/187405187


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-07-18 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 445618.
dgoldman added a comment.

Revert unintended change in symbol-info.test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130041/new/

https://reviews.llvm.org/D130041

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/test/symbol-info.test
  clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp

Index: clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
@@ -18,45 +18,79 @@
 
 using ::testing::UnorderedElementsAreArray;
 
-auto CreateExpectedSymbolDetails = [](const std::string ,
-  const std::string ,
-  const std::string ) {
-  return SymbolDetails{Name, Container, USR, SymbolID(USR)};
+// Partial SymbolDetails with the rest filled in at testing time.
+struct ExpectedSymbolDetails {
+  std::string Name;
+
+  std::string Container;
+
+  std::string USR;
+
+  const char *DeclMarker = nullptr;
+  const char *DefMarker = nullptr;
 };
 
 TEST(SymbolInfoTests, All) {
-  std::pair>
+  std::pair>
   TestInputExpectedOutput[] = {
   {
   R"cpp( // Simple function reference - declaration
-  void foo();
+  void $decl[[foo]]();
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Simple function reference - definition
-  void foo() {}
+  void $def[[foo]]() {}
+  int bar() {
+fo^o();
+  }
+)cpp",
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"}}},
+  {
+  R"cpp( // Simple function reference - decl and def
+  void $decl[[foo]]();
+  void $def[[foo]]() {}
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl", "def"}}},
+  {
+  R"cpp( // Simple class reference - decl and def
+  @interface $decl[[Foo]]
+  @end
+  @implementation $def[[Foo]]
+  @end
+  void doSomething(F^oo *obj) {}
+)cpp",
+  {ExpectedSymbolDetails{"Foo", "", "c:objc(cs)Foo", "decl", "def"}}},
+  {
+  R"cpp( // Simple method reference - decl and def
+  @interface Foo
+  - (void)$decl[[foo]];
+  @end
+  @implementation Foo
+  - (void)$def[[fo^o]] {}
+  @end
+)cpp",
+  {ExpectedSymbolDetails{"foo", "Foo::", "c:objc(cs)Foo(im)foo", "decl", "def"}}},
   {
   R"cpp( // Function in namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
 int baz() {
   fo^o();
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#", "decl"}}},
   {
   R"cpp( // Function in different namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -64,10 +98,10 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#", "decl"}}},
   {
   R"cpp( // Function in global namespace reference
-  void foo();
+  void $decl[[foo]]();
   namespace Nbar {
 namespace Nbaz {
   int baz() {
@@ -76,11 +110,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Function in anonymous namespace reference
   namespace {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -88,13 +122,13 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "(anonymous)",
-   "c:TestTU.cpp@aN@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "(anonymous)",
+ "c:TestTU.cpp@aN@F@foo#", "decl"}}},
   {
 

[PATCH] D130041: [clangd] Add decl/def support to SymbolDetails

2022-07-18 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added reviewers: kadircet, sammccall.
Herald added subscribers: usaxena95, arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Add an optional declarationRange and definitionRange to SymbolDetails.

This will allow SourceKit-LSP to implement toggling between goto
definition/declaration based on whether the symbol at the cursor
is a definition or declaration.

In addition, make some minor fixes for ObjCMethodDecl:

- XRefs.cpp getDefinition now sees ObjC method defs but I've left a TODO to 
implement proper searching for impls from a decl
- nameLocation for ObjC methods should point to foo in `- (void)foo`, not the -


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130041

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/test/symbol-info.test
  clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp

Index: clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolInfoTests.cpp
@@ -18,45 +18,79 @@
 
 using ::testing::UnorderedElementsAreArray;
 
-auto CreateExpectedSymbolDetails = [](const std::string ,
-  const std::string ,
-  const std::string ) {
-  return SymbolDetails{Name, Container, USR, SymbolID(USR)};
+// Partial SymbolDetails with the rest filled in at testing time.
+struct ExpectedSymbolDetails {
+  std::string Name;
+
+  std::string Container;
+
+  std::string USR;
+
+  const char *DeclMarker = nullptr;
+  const char *DefMarker = nullptr;
 };
 
 TEST(SymbolInfoTests, All) {
-  std::pair>
+  std::pair>
   TestInputExpectedOutput[] = {
   {
   R"cpp( // Simple function reference - declaration
-  void foo();
+  void $decl[[foo]]();
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl"}}},
   {
   R"cpp( // Simple function reference - definition
-  void foo() {}
+  void $def[[foo]]() {}
+  int bar() {
+fo^o();
+  }
+)cpp",
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "def", "def"}}},
+  {
+  R"cpp( // Simple function reference - decl and def
+  void $decl[[foo]]();
+  void $def[[foo]]() {}
   int bar() {
 fo^o();
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "", "c:@F@foo#", "decl", "def"}}},
+  {
+  R"cpp( // Simple class reference - decl and def
+  @interface $decl[[Foo]]
+  @end
+  @implementation $def[[Foo]]
+  @end
+  void doSomething(F^oo *obj) {}
+)cpp",
+  {ExpectedSymbolDetails{"Foo", "", "c:objc(cs)Foo", "decl", "def"}}},
+  {
+  R"cpp( // Simple method reference - decl and def
+  @interface Foo
+  - (void)$decl[[foo]];
+  @end
+  @implementation Foo
+  - (void)$def[[fo^o]] {}
+  @end
+)cpp",
+  {ExpectedSymbolDetails{"foo", "Foo::", "c:objc(cs)Foo(im)foo", "decl", "def"}}},
   {
   R"cpp( // Function in namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
 int baz() {
   fo^o();
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#", "decl"}}},
   {
   R"cpp( // Function in different namespace reference
   namespace bar {
-void foo();
+void $decl[[foo]]();
   }
   namespace barbar {
 int baz() {
@@ -64,10 +98,10 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", "bar::", "c:@N@bar@F@foo#", "decl"}}},
   {
   R"cpp( // Function in global namespace reference
-  void foo();
+  void $decl[[foo]]();
   namespace Nbar {
 namespace Nbaz {
   int baz() {
@@ -76,11 +110,11 @@
 }
   }
 )cpp",
-  {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
+  {ExpectedSymbolDetails{"foo", 

[PATCH] D128821: [clangd][ObjC] Fix ObjC method definition completion

2022-07-01 Thread David Goldman via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGdc6c1f181b8a: [clangd][ObjC] Fix ObjC method definition 
completion (authored by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128821/new/

https://reviews.llvm.org/D128821

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3131,6 +3131,26 @@
   EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
 }
 
+TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {
+  auto Results = completions(R"objc(
+  @interface Foo
+  - (int)valueForCharacter:(char)c secondArgument:(id)object;
+  @end
+  @implementation Foo
+  secondArg^
+  @end
+)objc",
+ /*IndexSymbols=*/{},
+ /*Opts=*/{}, "Foo.m");
+
+  auto C = Results.Completions;
+  EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
+  EXPECT_THAT(C, ElementsAre(filterText("valueForCharacter:secondArgument:")));
+  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
+  EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));
+  EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
+}
+
 TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {
   auto Results = completions(R"objc(
   @interface Foo
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -861,7 +861,7 @@
 case CodeCompletionResult::RK_Macro:
   return Result.Macro->getName();
 case CodeCompletionResult::RK_Pattern:
-  return Result.Pattern->getTypedText();
+  break;
 }
 auto *CCS = codeCompletionString(Result);
 const CodeCompletionString::Chunk *OnlyText = nullptr;


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3131,6 +3131,26 @@
   EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
 }
 
+TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {
+  auto Results = completions(R"objc(
+  @interface Foo
+  - (int)valueForCharacter:(char)c secondArgument:(id)object;
+  @end
+  @implementation Foo
+  secondArg^
+  @end
+)objc",
+ /*IndexSymbols=*/{},
+ /*Opts=*/{}, "Foo.m");
+
+  auto C = Results.Completions;
+  EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
+  EXPECT_THAT(C, ElementsAre(filterText("valueForCharacter:secondArgument:")));
+  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
+  EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));
+  EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
+}
+
 TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {
   auto Results = completions(R"objc(
   @interface Foo
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -861,7 +861,7 @@
 case CodeCompletionResult::RK_Macro:
   return Result.Macro->getName();
 case CodeCompletionResult::RK_Pattern:
-  return Result.Pattern->getTypedText();
+  break;
 }
 auto *CCS = codeCompletionString(Result);
 const CodeCompletionString::Chunk *OnlyText = nullptr;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128821: [clangd][ObjC] Fix ObjC method definition completion

2022-07-01 Thread David Goldman via Phabricator via cfe-commits
dgoldman updated this revision to Diff 441685.
dgoldman added a comment.

- Use codeCompletionString(Result) for RK_Pattern


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128821/new/

https://reviews.llvm.org/D128821

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3131,6 +3131,26 @@
   EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
 }
 
+TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {
+  auto Results = completions(R"objc(
+  @interface Foo
+  - (int)valueForCharacter:(char)c secondArgument:(id)object;
+  @end
+  @implementation Foo
+  secondArg^
+  @end
+)objc",
+ /*IndexSymbols=*/{},
+ /*Opts=*/{}, "Foo.m");
+
+  auto C = Results.Completions;
+  EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
+  EXPECT_THAT(C, ElementsAre(filterText("valueForCharacter:secondArgument:")));
+  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
+  EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));
+  EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
+}
+
 TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {
   auto Results = completions(R"objc(
   @interface Foo
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -861,7 +861,7 @@
 case CodeCompletionResult::RK_Macro:
   return Result.Macro->getName();
 case CodeCompletionResult::RK_Pattern:
-  return Result.Pattern->getTypedText();
+  break;
 }
 auto *CCS = codeCompletionString(Result);
 const CodeCompletionString::Chunk *OnlyText = nullptr;


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3131,6 +3131,26 @@
   EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
 }
 
+TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {
+  auto Results = completions(R"objc(
+  @interface Foo
+  - (int)valueForCharacter:(char)c secondArgument:(id)object;
+  @end
+  @implementation Foo
+  secondArg^
+  @end
+)objc",
+ /*IndexSymbols=*/{},
+ /*Opts=*/{}, "Foo.m");
+
+  auto C = Results.Completions;
+  EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
+  EXPECT_THAT(C, ElementsAre(filterText("valueForCharacter:secondArgument:")));
+  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
+  EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));
+  EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
+}
+
 TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {
   auto Results = completions(R"objc(
   @interface Foo
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -861,7 +861,7 @@
 case CodeCompletionResult::RK_Macro:
   return Result.Macro->getName();
 case CodeCompletionResult::RK_Pattern:
-  return Result.Pattern->getTypedText();
+  break;
 }
 auto *CCS = codeCompletionString(Result);
 const CodeCompletionString::Chunk *OnlyText = nullptr;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128821: [clangd][ObjC] Fix ObjC method definition completion

2022-06-29 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:866
 case CodeCompletionResult::RK_Pattern:
-  return Result.Pattern->getTypedText();
+  CCS = Result.Pattern;
+  break;

sammccall wrote:
> weirdly, codeCompletionString(Result) looks like it would mutate Result and 
> then return a pattern with the same chunks (but different extra fields). So 
> not affect the result of this function, but possibly others as a side-effect.
> 
> (e.g. add BriefComment and ParentName in the case that there's a pattern + 
> declaration, as there is here)
> 
> What you have is fine, but if you feel like digging deeper 
> codeCompletionString(Result) may be either better or worse here!
Hmm from what I can tell, it appears those are unused by clangd, but for 
posterity I can swap it over


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128821/new/

https://reviews.llvm.org/D128821

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128821: [clangd][ObjC] Fix ObjC method definition completion

2022-06-29 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

D124637  improved filtering of method 
expressions, but not method
definitions. With this change, clangd will now filter ObjC method
definition completions based on their entire selector instead of
only the first selector fragment.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128821

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3131,6 +3131,26 @@
   EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
 }
 
+TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {
+  auto Results = completions(R"objc(
+  @interface Foo
+  - (int)valueForCharacter:(char)c secondArgument:(id)object;
+  @end
+  @implementation Foo
+  secondArg^
+  @end
+)objc",
+ /*IndexSymbols=*/{},
+ /*Opts=*/{}, "Foo.m");
+
+  auto C = Results.Completions;
+  EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
+  EXPECT_THAT(C, ElementsAre(filterText("valueForCharacter:secondArgument:")));
+  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
+  EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));
+  EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
+}
+
 TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {
   auto Results = completions(R"objc(
   @interface Foo
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -851,19 +851,21 @@
   // Returns the filtering/sorting name for Result, which must be from Results.
   // Returned string is owned by this recorder (or the AST).
   llvm::StringRef getName(const CodeCompletionResult ) {
+CodeCompletionString *CCS = nullptr;
 switch (Result.Kind) {
 case CodeCompletionResult::RK_Declaration:
   if (auto *ID = Result.Declaration->getIdentifier())
 return ID->getName();
+  CCS = codeCompletionString(Result);
   break;
 case CodeCompletionResult::RK_Keyword:
   return Result.Keyword;
 case CodeCompletionResult::RK_Macro:
   return Result.Macro->getName();
 case CodeCompletionResult::RK_Pattern:
-  return Result.Pattern->getTypedText();
+  CCS = Result.Pattern;
+  break;
 }
-auto *CCS = codeCompletionString(Result);
 const CodeCompletionString::Chunk *OnlyText = nullptr;
 for (auto  : *CCS) {
   if (C.Kind != CodeCompletionString::CK_TypedText)


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3131,6 +3131,26 @@
   EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
 }
 
+TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {
+  auto Results = completions(R"objc(
+  @interface Foo
+  - (int)valueForCharacter:(char)c secondArgument:(id)object;
+  @end
+  @implementation Foo
+  secondArg^
+  @end
+)objc",
+ /*IndexSymbols=*/{},
+ /*Opts=*/{}, "Foo.m");
+
+  auto C = Results.Completions;
+  EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));
+  EXPECT_THAT(C, ElementsAre(filterText("valueForCharacter:secondArgument:")));
+  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));
+  EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));
+  EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));
+}
+
 TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {
   auto Results = completions(R"objc(
   @interface Foo
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -851,19 +851,21 @@
   // Returns the filtering/sorting name for Result, which must be from Results.
   // Returned string is owned by this recorder (or the AST).
   llvm::StringRef getName(const CodeCompletionResult ) {
+CodeCompletionString *CCS = nullptr;
 switch (Result.Kind) {
 case 

[PATCH] D128677: [clangd] Support #import insertions

2022-06-27 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added a reviewer: kadircet.
Herald added subscribers: usaxena95, arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added projects: clang, clang-tools-extra.

While it currently still defaults to #include instead of #import,
this support can be used in the future to provide #import insertions
for headers with ObjC symbols once SymbolCollector is updated.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128677

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Headers.cpp
  clang-tools-extra/clangd/Headers.h
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/unittests/HeadersTests.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp

Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -341,7 +341,8 @@
 }
 
 llvm::Optional
-HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled) const {
+HeaderIncludes::insert(llvm::StringRef IncludeName, bool IsAngled,
+   bool IsImport) const {
   assert(IncludeName == trimInclude(IncludeName));
   // If a  ("header") already exists in code, "header" () with
   // different quotation will still be inserted.
@@ -371,7 +372,8 @@
   }
   assert(InsertOffset <= Code.size());
   std::string NewInclude =
-  std::string(llvm::formatv("#include {0}\n", QuotedName));
+  IsImport ? std::string(llvm::formatv("#import {0}\n", QuotedName))
+   : std::string(llvm::formatv("#include {0}\n", QuotedName));
   // When inserting headers at end of the code, also append '\n' to the code
   // if it does not end with '\n'.
   // FIXME: when inserting multiple #includes at the end of code, only one
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -51,9 +51,9 @@
   HeaderIncludes(llvm::StringRef FileName, llvm::StringRef Code,
  const IncludeStyle );
 
-  /// Inserts an #include directive of \p Header into the code. If \p IsAngled
-  /// is true, \p Header will be quoted with <> in the directive; otherwise, it
-  /// will be quoted with "".
+  /// Inserts an #include or #import directive of \p IncludeName into the code.
+  /// If \p IsAngled is true, \p IncludeName will be quoted with <> in the
+  /// directive; otherwise, it will be quoted with "".
   ///
   /// When searching for points to insert new header, this ignores #include's
   /// after the #include block(s) in the beginning of a file to avoid inserting
@@ -70,13 +70,13 @@
   /// same category in the code that should be sorted after \p IncludeName. If
   /// \p IncludeName already exists (with exactly the same spelling), this
   /// returns None.
-  llvm::Optional insert(llvm::StringRef Header,
-  bool IsAngled) const;
+  llvm::Optional
+  insert(llvm::StringRef Header, bool IsAngled, bool IsImport = false) const;
 
   /// Removes all existing #includes of \p Header quoted with <> if \p IsAngled
   /// is true or "" if \p IsAngled is false.
-  /// This doesn't resolve the header file path; it only deletes #includes with
-  /// exactly the same spelling.
+  /// This doesn't resolve the header file path; it only deletes #includes and
+  /// #imports with exactly the same spelling.
   tooling::Replacements remove(llvm::StringRef Header, bool IsAngled) const;
 
 private:
Index: clang-tools-extra/clangd/unittests/HeadersTests.cpp
===
--- clang-tools-extra/clangd/unittests/HeadersTests.cpp
+++ clang-tools-extra/clangd/unittests/HeadersTests.cpp
@@ -115,7 +115,8 @@
 return Path.value_or("");
   }
 
-  llvm::Optional insert(llvm::StringRef VerbatimHeader) {
+  llvm::Optional insert(llvm::StringRef VerbatimHeader,
+  bool ViaImport) {
 Clang = setupClang();
 PreprocessOnlyAction Action;
 EXPECT_TRUE(
@@ -124,7 +125,7 @@
 IncludeInserter Inserter(MainFile, /*Code=*/"", format::getLLVMStyle(),
  CDB.getCompileCommand(MainFile)->Directory,
  >getPreprocessor().getHeaderSearchInfo());
-auto Edit = Inserter.insert(VerbatimHeader);
+auto Edit = Inserter.insert(VerbatimHeader, ViaImport);
 Action.EndSourceFile();
 return Edit;
   }
@@ -328,9 +329,13 @@
 }
 
 TEST_F(HeadersTest, PreferInserted) {
-  auto Edit = insert("");
+  auto Edit = insert("", /*ViaImport=*/false);
   

[PATCH] D128457: [clangd] Add new IncludeType to IncludeHeaderWithReferences

2022-06-23 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
dgoldman added a reviewer: kadircet.
Herald added subscribers: wenlei, usaxena95, arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

The IncludeType contains both Include (the current behavior) and Import,
which we can use in the future to provide #import suggestions for
Objective-C files/symbols.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128457

Files:
  clang-tools-extra/clangd/index/Merge.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/index/Symbol.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/YAMLSerialization.cpp
  clang-tools-extra/clangd/index/remote/Index.proto
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.cpp
  clang-tools-extra/clangd/index/remote/marshalling/Marshalling.h
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp

Index: clang-tools-extra/clangd/unittests/SerializationTests.cpp
===
--- clang-tools-extra/clangd/unittests/SerializationTests.cpp
+++ clang-tools-extra/clangd/unittests/SerializationTests.cpp
@@ -53,8 +53,10 @@
 IncludeHeaders:
   - Header:'include1'
 References:7
+Type:  Include
   - Header:'include2'
 References:3
+Type:  Import
 ...
 ---
 !Symbol
@@ -114,8 +116,10 @@
 
 MATCHER_P(id, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }
 MATCHER_P(qName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
-MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
-  return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
+MATCHER_P3(IncludeHeaderWithRefAndType, IncludeHeader, References, IncludeType,
+   "") {
+  return (arg.IncludeHeader == IncludeHeader) &&
+ (arg.References == References) && (arg.IncludeType == IncludeType);
 }
 
 auto readIndexFile(llvm::StringRef Text) {
@@ -149,8 +153,9 @@
   EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
   EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
   EXPECT_THAT(Sym1.IncludeHeaders,
-  UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
-   IncludeHeaderWithRef("include2", 3u)));
+  UnorderedElementsAre(
+  IncludeHeaderWithRefAndType("include1", 7u, Symbol::Include),
+  IncludeHeaderWithRefAndType("include2", 3u, Symbol::Import)));
 
   EXPECT_THAT(Sym2, qName("clang::Foo2"));
   EXPECT_EQ(Sym2.Signature, "-sig");
Index: clang-tools-extra/clangd/unittests/IndexTests.cpp
===
--- clang-tools-extra/clangd/unittests/IndexTests.cpp
+++ clang-tools-extra/clangd/unittests/IndexTests.cpp
@@ -567,9 +567,9 @@
   L.Name = "left";
   R.Name = "right";
   L.ID = R.ID = SymbolID("hello");
-  L.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("common", 1);
-  R.IncludeHeaders.emplace_back("new", 1);
+  L.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("common", 1, Symbol::Include);
+  R.IncludeHeaders.emplace_back("new", 1, Symbol::Include);
 
   // Both have no definition.
   Symbol M = mergeSymbol(L, R);
@@ -615,7 +615,7 @@
 std::move(DynData), DynSize);
 
   SymbolSlab::Builder StaticB;
-  S.IncludeHeaders.push_back({"", 0});
+  S.IncludeHeaders.push_back({"", 0, Symbol::Include});
   StaticB.insert(S);
   auto StaticIndex =
   MemIndex::build(std::move(StaticB).build(), RefSlab(), RelationSlab());
Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -1069,7 +1069,7 @@
 Sym.Flags |= Symbol::IndexedForCodeCompletion;
 Sym.CanonicalDeclaration.FileURI = S.DeclaringFile.c_str();
 Sym.Definition.FileURI = S.DeclaringFile.c_str();
-Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1);
+Sym.IncludeHeaders.emplace_back(S.IncludeHeader, 1, Symbol::Include);
 Slab.insert(Sym);
   }
   return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab());
@@ -1127,7 +1127,7 @@
   Symbol Sym = enm("X");
   Sym.Flags |= Symbol::IndexedForCodeCompletion;
   Sym.CanonicalDeclaration.FileURI = Sym.Definition.FileURI = "unittest:///x.h";
-  Sym.IncludeHeaders.emplace_back("\"x.h\"", 1);
+  Sym.IncludeHeaders.emplace_back("\"x.h\"", 1, Symbol::Include);
   SymbolSlab::Builder 

[PATCH] D127125: [clangd] Improve ObjC protocol suggestions from the index

2022-06-15 Thread David Goldman via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGbc1f24332af3: [clangd] Improve ObjC protocol suggestions 
from the index (authored by dgoldman).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127125/new/

https://reviews.llvm.org/D127125

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/TestIndex.cpp
  clang-tools-extra/clangd/unittests/TestIndex.h

Index: clang-tools-extra/clangd/unittests/TestIndex.h
===
--- clang-tools-extra/clangd/unittests/TestIndex.h
+++ clang-tools-extra/clangd/unittests/TestIndex.h
@@ -34,6 +34,14 @@
 // Create a C++20 concept symbol.
 Symbol conceptSym(llvm::StringRef Name);
 
+// Create an Objective-C symbol.
+Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind,
+   llvm::StringRef USRPrefix);
+// Create an @interface or @implementation.
+Symbol objcClass(llvm::StringRef Name);
+// Create an @protocol.
+Symbol objcProtocol(llvm::StringRef Name);
+
 // Create a slab of symbols with the given qualified names as IDs and names.
 SymbolSlab generateSymbols(std::vector QualifiedNames);
 
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -81,6 +81,28 @@
   return sym(Name, index::SymbolKind::Concept, "@CT@\\0");
 }
 
+Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind,
+   llvm::StringRef USRPrefix) {
+  Symbol Sym;
+  std::string USR = USRPrefix.str() + Name.str();
+  Sym.Name = Name;
+  Sym.Scope = "";
+  Sym.ID = SymbolID(USR);
+  Sym.SymInfo.Kind = Kind;
+  Sym.SymInfo.Lang = index::SymbolLanguage::ObjC;
+  Sym.Flags |= Symbol::IndexedForCodeCompletion;
+  Sym.Origin = SymbolOrigin::Static;
+  return Sym;
+}
+
+Symbol objcClass(llvm::StringRef Name) {
+  return objcSym(Name, index::SymbolKind::Class, "objc(cs)");
+}
+
+Symbol objcProtocol(llvm::StringRef Name) {
+  return objcSym(Name, index::SymbolKind::Protocol, "objc(pl)");
+}
+
 SymbolSlab generateSymbols(std::vector QualifiedNames) {
   SymbolSlab::Builder Slab;
   for (llvm::StringRef QName : QualifiedNames)
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3167,6 +3167,20 @@
   EXPECT_THAT(C, ElementsAre(signature("(id)object")));
 }
 
+TEST(CompletionTest, ObjectiveCProtocolFromIndex) {
+  Symbol FoodClass = objcClass("FoodClass");
+  Symbol SymFood = objcProtocol("Food");
+  Symbol SymFooey = objcProtocol("Fooey");
+  auto Results = completions(R"objc(
+  id
+)objc",
+ {SymFood, FoodClass, SymFooey},
+ /*Opts=*/{}, "Foo.m");
+
+  auto C = Results.Completions;
+  EXPECT_THAT(C, UnorderedElementsAre(named("Food"), named("Fooey")));
+}
+
 TEST(CompletionTest, CursorInSnippets) {
   clangd::CodeCompleteOptions Options;
   Options.EnableSnippets = true;
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -1673,6 +1673,14 @@
 return Output;
   }
 
+  bool includeSymbolFromIndex(const Symbol ) {
+if (CCContextKind == CodeCompletionContext::CCC_ObjCProtocolName) {
+  return Sym.SymInfo.Lang == index::SymbolLanguage::ObjC &&
+  Sym.SymInfo.Kind == index::SymbolKind::Protocol;
+}
+return true;
+  }
+
   SymbolSlab queryIndex() {
 trace::Span Tracer("Query index");
 SPAN_ATTACH(Tracer, "limit", int64_t(Opts.Limit));
@@ -1706,8 +1714,10 @@
 
 // Run the query against the index.
 SymbolSlab::Builder ResultsBuilder;
-if (Opts.Index->fuzzyFind(
-Req, [&](const Symbol ) { ResultsBuilder.insert(Sym); }))
+if (Opts.Index->fuzzyFind(Req, [&](const Symbol ) {
+  if (includeSymbolFromIndex(Sym))
+ResultsBuilder.insert(Sym);
+}))
   Incomplete = true;
 return std::move(ResultsBuilder).build();
   }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D127403: [clangd] Implement semantic token modifier "definition"

2022-06-13 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:847-849
+} else if (const auto Iface =
+   dyn_cast(Decl)) {
+  if (Iface->isThisDeclarationADefinition())

ckandeler wrote:
> dgoldman wrote:
> > Do we need similar code for ObjCProtocolDecl? Also should ObjCImplDecl be 
> > considered definitions here?
> Possibly. I know next to nothing about Objective C, so I'll just do as I'm 
> told here. On a related note, the code above regarding ObjCMethodDecl does 
> not seem to do anything, i.e. none of the constructs that to my eye appear to 
> be Objective-C methods get the "def" modifier. 
Gotcha, yeah I think it makes sense to do the same for ObjCImplDecl, 
ObjCProtocolDecl, and ObjCCategoryDecl.

re: methods, ah yeah, that's because canHighlightName will return false since 
we need to special case handling for ObjC methods since their names can be 
split across non contiguous tokens (selectors). Instead, would need to update 
`VisitObjCMethodDecl` and `highlightObjCSelector`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127403/new/

https://reviews.llvm.org/D127403

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D127403: [clangd] Implement semantic token modifier "definition"

2022-06-10 Thread David Goldman via Phabricator via cfe-commits
dgoldman added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:847-849
+} else if (const auto Iface =
+   dyn_cast(Decl)) {
+  if (Iface->isThisDeclarationADefinition())

Do we need similar code for ObjCProtocolDecl? Also should ObjCImplDecl be 
considered definitions here?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127403/new/

https://reviews.llvm.org/D127403

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D127125: [clangd] Improve ObjC protocol suggestions from the index

2022-06-06 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

When querying the index during an ObjC protocol name lookup for code
completion, we should only suggest ObjC protocols.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D127125

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/TestIndex.cpp
  clang-tools-extra/clangd/unittests/TestIndex.h

Index: clang-tools-extra/clangd/unittests/TestIndex.h
===
--- clang-tools-extra/clangd/unittests/TestIndex.h
+++ clang-tools-extra/clangd/unittests/TestIndex.h
@@ -34,6 +34,14 @@
 // Create a C++20 concept symbol.
 Symbol conceptSym(llvm::StringRef Name);
 
+// Create an Objective-C symbol.
+Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind,
+   llvm::StringRef USRPrefix);
+// Create an @interface or @implementation.
+Symbol objcClass(llvm::StringRef Name);
+// Create an @protocol.
+Symbol objcProtocol(llvm::StringRef Name);
+
 // Create a slab of symbols with the given qualified names as IDs and names.
 SymbolSlab generateSymbols(std::vector QualifiedNames);
 
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -81,6 +81,28 @@
   return sym(Name, index::SymbolKind::Concept, "@CT@\\0");
 }
 
+Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind,
+   llvm::StringRef USRPrefix) {
+  Symbol Sym;
+  std::string USR = USRPrefix.str() + Name.str();
+  Sym.Name = Name;
+  Sym.Scope = "";
+  Sym.ID = SymbolID(USR);
+  Sym.SymInfo.Kind = Kind;
+  Sym.SymInfo.Lang = index::SymbolLanguage::ObjC;
+  Sym.Flags |= Symbol::IndexedForCodeCompletion;
+  Sym.Origin = SymbolOrigin::Static;
+  return Sym;
+}
+
+Symbol objcClass(llvm::StringRef Name) {
+  return objcSym(Name, index::SymbolKind::Class, "objc(cs)");
+}
+
+Symbol objcProtocol(llvm::StringRef Name) {
+  return objcSym(Name, index::SymbolKind::Protocol, "objc(pl)");
+}
+
 SymbolSlab generateSymbols(std::vector QualifiedNames) {
   SymbolSlab::Builder Slab;
   for (llvm::StringRef QName : QualifiedNames)
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3150,6 +3150,20 @@
   EXPECT_THAT(C, ElementsAre(signature("(id)object")));
 }
 
+TEST(CompletionTest, ObjectiveCProtocolFromIndex) {
+  Symbol FoodClass = objcClass("FoodClass");
+  Symbol SymFood = objcProtocol("Food");
+  Symbol SymFooey = objcProtocol("Fooey");
+  auto Results = completions(R"objc(
+  id
+)objc",
+ {SymFood, FoodClass, SymFooey},
+ /*Opts=*/{}, "Foo.m");
+
+  auto C = Results.Completions;
+  EXPECT_THAT(C, UnorderedElementsAre(named("Food"), named("Fooey")));
+}
+
 TEST(CompletionTest, CursorInSnippets) {
   clangd::CodeCompleteOptions Options;
   Options.EnableSnippets = true;
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -1677,6 +1677,14 @@
 return Output;
   }
 
+  bool includeSymbolFromIndex(const Symbol ) {
+if (CCContextKind == CodeCompletionContext::CCC_ObjCProtocolName) {
+  return Sym.SymInfo.Lang == index::SymbolLanguage::ObjC &&
+  Sym.SymInfo.Kind == index::SymbolKind::Protocol;
+}
+return true;
+  }
+
   SymbolSlab queryIndex() {
 trace::Span Tracer("Query index");
 SPAN_ATTACH(Tracer, "limit", int64_t(Opts.Limit));
@@ -1711,8 +1719,10 @@
 
 // Run the query against the index.
 SymbolSlab::Builder ResultsBuilder;
-if (Opts.Index->fuzzyFind(
-Req, [&](const Symbol ) { ResultsBuilder.insert(Sym); }))
+if (Opts.Index->fuzzyFind(Req, [&](const Symbol ) {
+  if (includeSymbolFromIndex(Sym))
+ResultsBuilder.insert(Sym);
+}))
   Incomplete = true;
 return std::move(ResultsBuilder).build();
   }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D127116: [clangd] Add flags to symbol requests to restrict to ObjC symbols

2022-06-06 Thread David Goldman via Phabricator via cfe-commits
dgoldman created this revision.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: All.
dgoldman requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

clangd will set this flag for files with ObjC language flag enabled. This can 
be used to only include ObjC symbols when searching for symbols.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D127116

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/HeaderSourceSwitch.cpp
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/IncludeFixer.cpp
  clang-tools-extra/clangd/IncludeFixer.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/index/Index.h

Index: clang-tools-extra/clangd/index/Index.h
===
--- clang-tools-extra/clangd/index/Index.h
+++ clang-tools-extra/clangd/index/Index.h
@@ -47,13 +47,15 @@
   std::vector ProximityPaths;
   /// Preferred types of symbols. These are raw representation of `OpaqueType`.
   std::vector PreferredTypes;
+  /// Whether Objective-C symbols should be included in the search.
+  bool IncludeObjC = false;
 
   bool operator==(const FuzzyFindRequest ) const {
 return std::tie(Query, Scopes, Limit, RestrictForCodeCompletion,
-ProximityPaths, PreferredTypes) ==
+ProximityPaths, PreferredTypes, IncludeObjC) ==
std::tie(Req.Query, Req.Scopes, Req.Limit,
 Req.RestrictForCodeCompletion, Req.ProximityPaths,
-Req.PreferredTypes);
+Req.PreferredTypes, Req.IncludeObjC);
   }
   bool operator!=(const FuzzyFindRequest ) const { return !(*this == Req); }
 };
@@ -63,6 +65,8 @@
 
 struct LookupRequest {
   llvm::DenseSet IDs;
+  /// Whether Objective-C symbols should be included in the lookup.
+  bool IncludeObjC = false;
 };
 
 struct RefsRequest {
@@ -75,6 +79,8 @@
   /// If set, populates the container of the reference.
   /// Index implementations may chose to populate containers no matter what.
   bool WantContainer = false;
+  /// Whether Objective-C code should be included in the search.
+  bool IncludeObjC = false;
 };
 
 struct RelationsRequest {
@@ -82,6 +88,8 @@
   RelationKind Predicate;
   /// If set, limit the number of relations returned from the index.
   llvm::Optional Limit;
+  /// Whether Objective-C code should be included in the search.
+  bool IncludeObjC = false;
 };
 
 /// Describes what data is covered by an index.
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -455,6 +455,7 @@
   // Now query the index for all Symbol IDs we found in the AST.
   if (Index && !ResultIndex.empty()) {
 LookupRequest QueryRequest;
+QueryRequest.IncludeObjC = AST.getLangOpts().ObjC;
 for (auto It : ResultIndex)
   QueryRequest.IDs.insert(It.first);
 std::string Scratch;
@@ -588,6 +589,7 @@
   // too much data, while still likely having enough for 3 results to remain
   // after additional filtering.
   Req.Limit = 10;
+  Req.IncludeObjC = AST.getLangOpts().ObjC;
   bool TooMany = false;
   using ScoredLocatedSymbol = std::pair;
   std::vector ScoredResults;
@@ -1397,6 +1399,7 @@
 }
 
 RelationsRequest OverriddenBy;
+OverriddenBy.IncludeObjC = AST.getLangOpts().ObjC;
 if (Index) {
   OverriddenBy.Predicate = RelationKind::OverriddenBy;
   for (const NamedDecl *ND : Decls) {
@@ -1472,6 +1475,7 @@
   return;
 RefsRequest Req;
 Req.IDs = std::move(IDs);
+Req.IncludeObjC = AST.getLangOpts().ObjC;
 if (Limit) {
   if (Limit < Results.References.size()) {
 // We've already filled our quota, still check the index to correctly
Index: clang-tools-extra/clangd/IncludeFixer.h
===
--- clang-tools-extra/clangd/IncludeFixer.h
+++ clang-tools-extra/clangd/IncludeFixer.h
@@ -61,6 +61,9 @@
 std::string Name;   // E.g. "X" in foo::X.
 SourceLocation Loc; // Start location of the unresolved name.
 std::vector Scopes; // Namespace scopes we should search in.
+/// Whether Objective-C symbols should be included in the search for this
+/// name.
+bool IncludeObjC = false;
   };
 
   /// Records the last unresolved name seen by Sema.
Index: clang-tools-extra/clangd/IncludeFixer.cpp
===
--- clang-tools-extra/clangd/IncludeFixer.cpp
+++ clang-tools-extra/clangd/IncludeFixer.cpp
@@ -511,6 +511,7 @@
 UnresolvedName Unresolved;
 Unresolved.Name = Extracted->Name;
 Unresolved.Loc = Typo.getBeginLoc();
+Unresolved.IncludeObjC = SemaPtr->getLangOpts().ObjC;
 if (!Extracted->ResolvedScope && !S) // Give up if no scope 

  1   2   3   4   5   6   >