[PATCH] D132797: [clangd] Support renaming virtual methods

2022-08-27 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Fixes https://github.com/clangd/clangd/issues/706


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D132797

Files:
  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
@@ -886,12 +886,6 @@
  @end
)cpp",
"not a supported kind", HeaderFile},
-  {R"cpp(// FIXME: rename virtual/override methods is not supported yet.
- struct A {
-  virtual void f^oo() {}
- };
-  )cpp",
-   "not a supported kind", !HeaderFile},
   {R"cpp(
  void foo(int);
  void foo(char);
@@ -1490,6 +1484,37 @@
 }
   )cpp",
   },
+  {
+  // virtual methods.
+  R"cpp(
+class Base {
+  virtual void [[foo]]();
+};
+class Derived1 : public Base {
+  void [[f^oo]]() override;
+};
+class NotDerived {
+  void foo() {};
+}
+  )cpp",
+  R"cpp(
+#include "foo.h"
+void Base::[[foo]]() {}
+void Derived1::[[foo]]() {}
+
+class Derived2 : public Derived1 {
+  void [[foo]]() override {};
+};
+
+void func(Base* b, Derived1* d1, 
+  Derived2* d2, NotDerived* nd) {
+  b->[[foo]]();
+  d1->[[foo]]();
+  d2->[[foo]]();
+  nd->foo();
+}
+  )cpp",
+  },
   {
   // rename on constructor and destructor.
   R"cpp(
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -214,13 +214,6 @@
   IsMainFileOnly))
 return ReasonToReject::NonIndexable;
 
-
-  // FIXME: Renaming virtual methods requires to rename all overridens in
-  // subclasses, our index doesn't have this information.
-  if (const auto *S = llvm::dyn_cast(&RenameDecl)) {
-if (S->isVirtual())
-  return ReasonToReject::UnsupportedSymbol;
-  }
   return None;
 }
 
@@ -551,6 +544,20 @@
   return R;
 }
 
+namespace {
+void recursivelyInsertOverrides(const SymbolID &Base,
+llvm::DenseSet &IDs,
+const SymbolIndex &Index) {
+  RelationsRequest Req;
+  Req.Predicate = RelationKind::OverriddenBy;
+  Req.Subjects = {Base};
+  Index.relations(Req, [&](const SymbolID &, const Symbol &Override) {
+IDs.insert(Override.ID);
+recursivelyInsertOverrides(Override.ID, IDs, Index);
+  });
+}
+} // namespace
+
 // Return all rename occurrences (using the index) outside of the main file,
 // grouped by the absolute file path.
 llvm::Expected>>
@@ -561,6 +568,10 @@
   RefsRequest RQuest;
   RQuest.IDs.insert(getSymbolID(&RenameDecl));
 
+  if (const auto *MethodDecl = llvm::dyn_cast(&RenameDecl))
+if (MethodDecl->isVirtual())
+  recursivelyInsertOverrides(*RQuest.IDs.begin(), RQuest.IDs, Index);
+
   // Absolute file path => rename occurrences in that file.
   llvm::StringMap> AffectedFiles;
   bool HasMore = Index.refs(RQuest, [&](const Ref &R) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132797: [clangd] Support renaming virtual methods

2022-09-06 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 458221.
tom-anders added a comment.

Add test case that triggers assertion, limit recursion


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132797

Files:
  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
@@ -886,12 +886,6 @@
  @end
)cpp",
"not a supported kind", HeaderFile},
-  {R"cpp(// FIXME: rename virtual/override methods is not supported yet.
- struct A {
-  virtual void f^oo() {}
- };
-  )cpp",
-   "not a supported kind", !HeaderFile},
   {R"cpp(
  void foo(int);
  void foo(char);
@@ -1490,6 +1484,44 @@
 }
   )cpp",
   },
+  {
+  // virtual methods.
+  R"cpp(
+class Base {
+  virtual void [[foo]]();
+};
+class Derived1 : public Base {
+  void [[f^oo]]() override;
+};
+class NotDerived {
+  void foo() {};
+}
+  )cpp",
+  R"cpp(
+#include "foo.h"
+void Base::[[foo]]() {}
+void Derived1::[[foo]]() {}
+
+class Derived2 : public Derived1 {
+  void [[foo]]() override {};
+};
+
+void func(Base* b, Derived1* d1, 
+  Derived2* d2, NotDerived* nd) {
+  b->[[foo]]();
+  d1->[[foo]]();
+  d2->[[foo]]();
+  nd->foo();
+}
+  )cpp",
+  },
+  {
+  // virtual templated method
+  R"cpp(
+template  class Foo { virtual void [[m]](); };
+class Bar : Foo { void [[^m]]() override; };
+  )cpp", ""
+  },
   {
   // rename on constructor and destructor.
   R"cpp(
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -214,13 +214,6 @@
   IsMainFileOnly))
 return ReasonToReject::NonIndexable;
 
-
-  // FIXME: Renaming virtual methods requires to rename all overridens in
-  // subclasses, our index doesn't have this information.
-  if (const auto *S = llvm::dyn_cast(&RenameDecl)) {
-if (S->isVirtual())
-  return ReasonToReject::UnsupportedSymbol;
-  }
   return None;
 }
 
@@ -551,6 +544,35 @@
   return R;
 }
 
+// Walk down from a virtual method to overriding methods, we rename them as a
+// group. Note that canonicalRenameDecl() ensures we're starting from the base
+// method.
+void recursivelyInsertOverrides(SymbolID Base, llvm::DenseSet &IDs,
+const SymbolIndex &Index,
+llvm::DenseSet &Pending) {
+  // By keeping track of symbols we've already visited (Pending), the number of
+  // requests is bounded by the length of the shortest chain to the most
+  // distance SymbolID
+  while (!Pending.empty()) {
+RelationsRequest Req;
+Req.Predicate = RelationKind::OverriddenBy;
+Req.Subjects = Pending;
+Pending.clear();
+
+Index.relations(Req, [&](const SymbolID &, const Symbol &Override) {
+  IDs.insert(Override.ID);
+  Pending.insert(Override.ID);
+  recursivelyInsertOverrides(Override.ID, IDs, Index, Pending);
+});
+  }
+}
+
+void recursivelyInsertOverrides(SymbolID Base, llvm::DenseSet &IDs,
+const SymbolIndex &Index) {
+  llvm::DenseSet Pending = {Base};
+  recursivelyInsertOverrides(Base, IDs, Index, Pending);
+}
+
 // Return all rename occurrences (using the index) outside of the main file,
 // grouped by the absolute file path.
 llvm::Expected>>
@@ -561,6 +583,10 @@
   RefsRequest RQuest;
   RQuest.IDs.insert(getSymbolID(&RenameDecl));
 
+  if (const auto *MethodDecl = llvm::dyn_cast(&RenameDecl))
+if (MethodDecl->isVirtual())
+  recursivelyInsertOverrides(*RQuest.IDs.begin(), RQuest.IDs, Index);
+
   // Absolute file path => rename occurrences in that file.
   llvm::StringMap> AffectedFiles;
   bool HasMore = Index.refs(RQuest, [&](const Ref &R) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132797: [clangd] Support renaming virtual methods

2022-09-06 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders marked 6 inline comments as done.
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:245
   trace::Span Tracer("FindOccurrencesWithinFile");
   assert(canonicalRenameDecl(&ND) == &ND &&
  "ND should be already canonicalized.");

sammccall wrote:
> Unfortunately we've uncovered a bug: this assertion fires (after this patch) 
> on the following code:
> 
> ```
> template  class Foo { virtual void m(); };
> class Bar : Foo { void ^m() override; };
> ```
> 
> `canonicalRenameDecl` is supposed to be idempotent. 
> However:`canonicalRenameDecl(Bar::m)` is `Foo::m`, but 
> `canonicalRenameDecl(Foo::m)` is `Foo::m`.
> 
> I think this is because the `getInstantiatedFromMemberFunction` check comes 
> before the `overridden_methods` check, so if the override points to a member 
> of an instantiation then it's too late to map it back to the member of the 
> template.
> 
> Probably the best fix is to change line 103 to a recursive `return 
> canonicalRenameDecl(...)`, as is done elsewhere in the function.
> 
> (Can you please add this case to the tests?)
I added the test case for this. However, your suggested fix doesn't seem to 
stop the assertion from being triggered. I'd be grateful if you can take a 
closer look at this in a separate review - Should I leave the test case in 
anyway? Is it okay if the test fails for a while until you found the fix?



Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:554
+  Req.Subjects = {Base};
+  Index.relations(Req, [&](const SymbolID &, const Symbol &Override) {
+IDs.insert(Override.ID);

ilya-biryukov wrote:
> sammccall wrote:
> > ilya-biryukov wrote:
> > > Should we put a limit on the number of requests we send during recursion 
> > > here?
> > > 
> > > I see a few obvious failure modes:
> > > - infinite recursion in the relations due to parts of index being stale, 
> > > corrupted input data or other reasons,
> > > - exponential blow up in hierarchies with multiple inheritance,
> > > - sending a lot of network requests in case of deep inheritance 
> > > hierarchies for remote index implementations. Since all requests are 
> > > sequential, the network latency might add up to substantial numbers.
> > > 
> > > We could address these in some other manner, this just seems to be the 
> > > simplest option to protect against catastrophic outcomes (running the 
> > > request indefinitely, crashing due to infinite recursion, etc).
> > > exponential blow up in hierarchies with multiple inheritance,
> > 
> > It seems with little loss of readability we could provide some useful 
> > bounds:
> > 
> > ```
> > DenseSet Pending = {Base};
> > while (!Pending.empty()) {
> >   Req = {.Subjects = Pending};
> >   Pending.clear();
> >   Index.relations(Req, { IDs.insert(ID); Pending.insert(ID) });
> > }
> > ```
> > in this case the #requests is clearly bounded by the length of the shortest 
> > chain to the most distant SymbolID, and is IMO safe with no numeric cap.
> > 
> > whereas the current version could potentially get the same ID in multiple 
> > branches and so the bound on #requests is harder to determine.
> This looks good! Also avoids infinite recursion.
> Having a potentially large number of sequential network requests still looks 
> unfortunate, but I doubt this will bite us in practice (at least not for 
> remote indicies for LLVM and Chrome).
> 
> To solve it, we could allow recursive requests and implement the recursion 
> inside the index, but this could be done with a follow-up when we actually 
> hit this issue.
Done, hope I interpreted your sketch correctly


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132797

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


[PATCH] D132797: [clangd] Support renaming virtual methods

2022-09-06 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 458270.
tom-anders marked an inline comment as done.
tom-anders added a comment.

Fix recursivelyInsertRenames()


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132797

Files:
  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
@@ -886,12 +886,6 @@
  @end
)cpp",
"not a supported kind", HeaderFile},
-  {R"cpp(// FIXME: rename virtual/override methods is not supported yet.
- struct A {
-  virtual void f^oo() {}
- };
-  )cpp",
-   "not a supported kind", !HeaderFile},
   {R"cpp(
  void foo(int);
  void foo(char);
@@ -1490,6 +1484,44 @@
 }
   )cpp",
   },
+  {
+  // virtual methods.
+  R"cpp(
+class Base {
+  virtual void [[foo]]();
+};
+class Derived1 : public Base {
+  void [[f^oo]]() override;
+};
+class NotDerived {
+  void foo() {};
+}
+  )cpp",
+  R"cpp(
+#include "foo.h"
+void Base::[[foo]]() {}
+void Derived1::[[foo]]() {}
+
+class Derived2 : public Derived1 {
+  void [[foo]]() override {};
+};
+
+void func(Base* b, Derived1* d1, 
+  Derived2* d2, NotDerived* nd) {
+  b->[[foo]]();
+  d1->[[foo]]();
+  d2->[[foo]]();
+  nd->foo();
+}
+  )cpp",
+  },
+  {
+  // virtual templated method
+  R"cpp(
+template  class Foo { virtual void [[m]](); };
+class Bar : Foo { void [[^m]]() override; };
+  )cpp", ""
+  },
   {
   // rename on constructor and destructor.
   R"cpp(
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -214,13 +214,6 @@
   IsMainFileOnly))
 return ReasonToReject::NonIndexable;
 
-
-  // FIXME: Renaming virtual methods requires to rename all overridens in
-  // subclasses, our index doesn't have this information.
-  if (const auto *S = llvm::dyn_cast(&RenameDecl)) {
-if (S->isVirtual())
-  return ReasonToReject::UnsupportedSymbol;
-  }
   return None;
 }
 
@@ -551,6 +544,26 @@
   return R;
 }
 
+// Walk down from a virtual method to overriding methods, we rename them as a
+// group. Note that canonicalRenameDecl() ensures we're starting from the base
+// method.
+void recursivelyInsertOverrides(SymbolID Base, llvm::DenseSet &IDs,
+const SymbolIndex &Index) {
+  RelationsRequest Req;
+  Req.Predicate = RelationKind::OverriddenBy;
+
+  llvm::DenseSet Pending = {Base};
+  while (!Pending.empty()) {
+Req.Subjects = Pending;
+Pending.clear();
+
+Index.relations(Req, [&](const SymbolID &, const Symbol &Override) {
+  IDs.insert(Override.ID);
+  Pending.insert(Override.ID);
+});
+  }
+}
+
 // Return all rename occurrences (using the index) outside of the main file,
 // grouped by the absolute file path.
 llvm::Expected>>
@@ -561,6 +574,10 @@
   RefsRequest RQuest;
   RQuest.IDs.insert(getSymbolID(&RenameDecl));
 
+  if (const auto *MethodDecl = llvm::dyn_cast(&RenameDecl))
+if (MethodDecl->isVirtual())
+  recursivelyInsertOverrides(*RQuest.IDs.begin(), RQuest.IDs, Index);
+
   // Absolute file path => rename occurrences in that file.
   llvm::StringMap> AffectedFiles;
   bool HasMore = Index.refs(RQuest, [&](const Ref &R) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132797: [clangd] Support renaming virtual methods

2022-09-06 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:554
+  Req.Subjects = {Base};
+  Index.relations(Req, [&](const SymbolID &, const Symbol &Override) {
+IDs.insert(Override.ID);

tom-anders wrote:
> ilya-biryukov wrote:
> > sammccall wrote:
> > > ilya-biryukov wrote:
> > > > Should we put a limit on the number of requests we send during 
> > > > recursion here?
> > > > 
> > > > I see a few obvious failure modes:
> > > > - infinite recursion in the relations due to parts of index being 
> > > > stale, corrupted input data or other reasons,
> > > > - exponential blow up in hierarchies with multiple inheritance,
> > > > - sending a lot of network requests in case of deep inheritance 
> > > > hierarchies for remote index implementations. Since all requests are 
> > > > sequential, the network latency might add up to substantial numbers.
> > > > 
> > > > We could address these in some other manner, this just seems to be the 
> > > > simplest option to protect against catastrophic outcomes (running the 
> > > > request indefinitely, crashing due to infinite recursion, etc).
> > > > exponential blow up in hierarchies with multiple inheritance,
> > > 
> > > It seems with little loss of readability we could provide some useful 
> > > bounds:
> > > 
> > > ```
> > > DenseSet Pending = {Base};
> > > while (!Pending.empty()) {
> > >   Req = {.Subjects = Pending};
> > >   Pending.clear();
> > >   Index.relations(Req, { IDs.insert(ID); Pending.insert(ID) });
> > > }
> > > ```
> > > in this case the #requests is clearly bounded by the length of the 
> > > shortest chain to the most distant SymbolID, and is IMO safe with no 
> > > numeric cap.
> > > 
> > > whereas the current version could potentially get the same ID in multiple 
> > > branches and so the bound on #requests is harder to determine.
> > This looks good! Also avoids infinite recursion.
> > Having a potentially large number of sequential network requests still 
> > looks unfortunate, but I doubt this will bite us in practice (at least not 
> > for remote indicies for LLVM and Chrome).
> > 
> > To solve it, we could allow recursive requests and implement the recursion 
> > inside the index, but this could be done with a follow-up when we actually 
> > hit this issue.
> Done, hope I interpreted your sketch correctly
Nope, I totally misunderstood, should be better now


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132797

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


[PATCH] D132797: [clangd] Support renaming virtual methods

2022-09-07 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

In D132797#3774138 , @sammccall wrote:

> LG
>
> IIRC Tom doesn't have commit access, so I'll apply the last trivial changes 
> and commit to avoid another round trip.
> (Please LMK if i'm wrong about this!)

I actually have commit access now, but thanks :) looking forward to your 
follow-up


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132797

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


[PATCH] D133664: [clangd] Fix hover on symbol introduced by using declaration

2022-09-11 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

This fixes https://github.com/clangd/clangd/issues/1284. The example
there was C++20's "using enum", but I noticed that we had the same issue
for other using-declarations.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133664

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -1630,6 +1630,26 @@
 HI.Type = "int";
 HI.Definition = "int foo";
   }},
+  {
+  R"cpp(// Function definition via using declaration
+namespace ns { 
+  void foo(); 
+}
+int main() {
+  using ns::foo;
+  ^[[foo]]();
+}
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "foo";
+HI.Kind = index::SymbolKind::Function;
+HI.NamespaceScope = "ns::";
+HI.Type = "void ()";
+HI.Definition = "void foo()";
+HI.Documentation = "";
+HI.ReturnType = "void";
+HI.Parameters = std::vector{};
+  }},
   {
   R"cpp(// Macro
 #define MACRO 0
@@ -1734,6 +1754,25 @@
 HI.Definition = "ONE";
 HI.Value = "0";
   }},
+  {
+  R"cpp(// C++20's using enum
+enum class Hello {
+  ONE, TWO, THREE,
+};
+void foo() {
+  using enum Hello;
+  Hello hello = [[O^NE]];
+}
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "ONE";
+HI.Kind = index::SymbolKind::EnumConstant;
+HI.NamespaceScope = "";
+HI.LocalScope = "Hello::";
+HI.Type = "enum Hello";
+HI.Definition = "ONE";
+HI.Value = "0";
+  }},
   {
   R"cpp(// Enumerator in anonymous enum
 enum {
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1082,10 +1082,22 @@
   auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Alias,
 AST.getHeuristicResolver());
   if (!Decls.empty()) {
-HI = getHoverContents(Decls.front(), PP, Index, TB);
+// For using-declarations, e.g.
+// namespace ns { void foo(); }
+// void bar() { using ns::foo; f^oo(); }
+// The first declaration in Decls will refer to the using declaration,
+// which isn't really useful for Hover. So check if we have something
+// better, which in this example would be the actual declaration of 
foo.
+auto *DeclToUse = Decls.begin();
+while (llvm::isa(*DeclToUse) &&
+   std::next(DeclToUse) != Decls.end()) {
+  ++DeclToUse;
+}
+
+HI = getHoverContents(*DeclToUse, PP, Index, TB);
 // Layout info only shown when hovering on the field/class itself.
-if (Decls.front() == N->ASTNode.get())
-  addLayoutInfo(*Decls.front(), *HI);
+if (*DeclToUse == N->ASTNode.get())
+  addLayoutInfo(**DeclToUse, *HI);
 // Look for a close enclosing expression to show the value of.
 if (!HI->Value)
   HI->Value = printExprValue(N, AST.getASTContext());


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -1630,6 +1630,26 @@
 HI.Type = "int";
 HI.Definition = "int foo";
   }},
+  {
+  R"cpp(// Function definition via using declaration
+namespace ns { 
+  void foo(); 
+}
+int main() {
+  using ns::foo;
+  ^[[foo]]();
+}
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "foo";
+HI.Kind = index::SymbolKind::Function;
+HI.NamespaceScope = "ns::";
+HI.Type = "void ()";
+HI.Definition = "void foo()";
+HI.Documentation = "";
+HI.ReturnType = "void";
+HI.Parameters = std::vector{};
+  }},
   {
   R"cpp(// Macro
 #define MACRO 0
@@ -1734,6 +1754,25 @@
 HI.Definition = "ONE";
 HI.Value = "0";
  

[PATCH] D133756: [clangd] Introduce CompileCommandsAdjuster

2022-09-13 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/indexer/IndexerMain.cpp:150-151
   clang::tooling::ArgumentsAdjuster(
-  clang::clangd::CommandMangler::detect()));
+  [Mangler = std::shared_ptr(
+   clang::clangd::CommandMangler::detect().release())](
+  const std::vector &Args, llvm::StringRef File) {

Just wondering, why do you need to convert to a shared_ptr here? Couldn't the 
lambda just take ownership of the unique_ptr?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133756

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


[PATCH] D133664: [clangd] Fix hover on symbol introduced by using declaration

2022-09-13 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 459864.
tom-anders added a comment.

Move logic to pickDeclToUse


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133664

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp

Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -1630,6 +1630,26 @@
 HI.Type = "int";
 HI.Definition = "int foo";
   }},
+  {
+  R"cpp(// Function definition via using declaration
+namespace ns { 
+  void foo(); 
+}
+int main() {
+  using ns::foo;
+  ^[[foo]]();
+}
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "foo";
+HI.Kind = index::SymbolKind::Function;
+HI.NamespaceScope = "ns::";
+HI.Type = "void ()";
+HI.Definition = "void foo()";
+HI.Documentation = "";
+HI.ReturnType = "void";
+HI.Parameters = std::vector{};
+  }},
   {
   R"cpp(// Macro
 #define MACRO 0
@@ -1734,6 +1754,25 @@
 HI.Definition = "ONE";
 HI.Value = "0";
   }},
+  {
+  R"cpp(// C++20's using enum
+enum class Hello {
+  ONE, TWO, THREE,
+};
+void foo() {
+  using enum Hello;
+  Hello hello = [[O^NE]];
+}
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "ONE";
+HI.Kind = index::SymbolKind::EnumConstant;
+HI.NamespaceScope = "";
+HI.LocalScope = "Hello::";
+HI.Type = "enum Hello";
+HI.Definition = "ONE";
+HI.Value = "0";
+  }},
   {
   R"cpp(// Enumerator in anonymous enum
 enum {
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1006,6 +1006,42 @@
   HI.CallPassType.emplace(PassType);
 }
 
+template 
+const NamedDecl *
+pickDeclToUse(const llvm::SmallVector &Candidates) {
+  if (Candidates.empty())
+return nullptr;
+  if (Candidates.size() == 1)
+return Candidates.front();
+
+  // This is e.g the case for
+  // namespace ns { void foo(); }
+  // void bar() { using ns::foo; f^oo(); }
+  // One declaration in Candidates will refer to the using declaration,
+  // which isn't really useful for Hover. So use the other one,
+  // which in this example would be the actual declaration of foo.
+  if (Candidates.size() == 2) {
+if (llvm::isa(Candidates.front()))
+  return Candidates.back();
+if (llvm::isa(Candidates.back()))
+  return Candidates.front();
+  }
+
+  // For something like
+  // namespace ns { void foo(int); void foo(char) }
+  // using ns::fo
+  // template  void bar() { fo^o(T{}); }
+  // we actually want to show the using declaration,
+  // it's not clear which declaration to pick otherwise.
+  auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) {
+return llvm::isa(D);
+  });
+  if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1)
+return *BaseDecls.begin();
+
+  return Candidates.front();
+}
+
 } // namespace
 
 llvm::Optional getHover(ParsedAST &AST, Position Pos,
@@ -1081,11 +1117,11 @@
   // FIXME: Fill in HighlightRange with range coming from N->ASTNode.
   auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Alias,
 AST.getHeuristicResolver());
-  if (!Decls.empty()) {
-HI = getHoverContents(Decls.front(), PP, Index, TB);
+  if (const auto *DeclToUse = pickDeclToUse(Decls)) {
+HI = getHoverContents(DeclToUse, PP, Index, TB);
 // Layout info only shown when hovering on the field/class itself.
-if (Decls.front() == N->ASTNode.get())
-  addLayoutInfo(*Decls.front(), *HI);
+if (DeclToUse == N->ASTNode.get())
+  addLayoutInfo(*DeclToUse, *HI);
 // Look for a close enclosing expression to show the value of.
 if (!HI->Value)
   HI->Value = printExprValue(N, AST.getASTContext());
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133664: [clangd] Fix hover on symbol introduced by using declaration

2022-09-14 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 460058.
tom-anders marked 5 inline comments as done.
tom-anders added a comment.

Add additional test, tidy up logic in pickDeclToUse()


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133664

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp

Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -1630,6 +1630,38 @@
 HI.Type = "int";
 HI.Definition = "int foo";
   }},
+  {
+  R"cpp(// Function definition via using declaration
+namespace ns { 
+  void foo(); 
+}
+int main() {
+  using ns::foo;
+  ^[[foo]]();
+}
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "foo";
+HI.Kind = index::SymbolKind::Function;
+HI.NamespaceScope = "ns::";
+HI.Type = "void ()";
+HI.Definition = "void foo()";
+HI.Documentation = "";
+HI.ReturnType = "void";
+HI.Parameters = std::vector{};
+  }},
+  {
+  R"cpp( // using declaration and two possible function declarations
+namespace ns { void foo(int); void foo(char); }
+using ns::foo;
+template  void bar() { [[f^oo]](T{}); }
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "foo";
+HI.Kind = index::SymbolKind::Using;
+HI.NamespaceScope = "";
+HI.Definition = "using ns::foo";
+  }},
   {
   R"cpp(// Macro
 #define MACRO 0
@@ -1734,6 +1766,25 @@
 HI.Definition = "ONE";
 HI.Value = "0";
   }},
+  {
+  R"cpp(// C++20's using enum
+enum class Hello {
+  ONE, TWO, THREE,
+};
+void foo() {
+  using enum Hello;
+  Hello hello = [[O^NE]];
+}
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "ONE";
+HI.Kind = index::SymbolKind::EnumConstant;
+HI.NamespaceScope = "";
+HI.LocalScope = "Hello::";
+HI.Type = "enum Hello";
+HI.Definition = "ONE";
+HI.Value = "0";
+  }},
   {
   R"cpp(// Enumerator in anonymous enum
 enum {
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1006,6 +1006,38 @@
   HI.CallPassType.emplace(PassType);
 }
 
+const NamedDecl *pickDeclToUse(llvm::ArrayRef Candidates) {
+  if (Candidates.empty())
+return nullptr;
+
+  // This is e.g the case for
+  // namespace ns { void foo(); }
+  // void bar() { using ns::foo; f^oo(); }
+  // One declaration in Candidates will refer to the using declaration,
+  // which isn't really useful for Hover. So use the other one,
+  // which in this example would be the actual declaration of foo.
+  if (Candidates.size() <= 2) {
+if (llvm::isa(Candidates.front()))
+  return Candidates.back();
+
+return Candidates.front();
+  }
+
+  // For something like
+  // namespace ns { void foo(int); void foo(char); }
+  // using ns::foo;
+  // template  void bar() { fo^o(T{}); }
+  // we actually want to show the using declaration,
+  // it's not clear which declaration to pick otherwise.
+  auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) {
+return llvm::isa(D);
+  });
+  if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1)
+return *BaseDecls.begin();
+
+  return Candidates.front();
+}
+
 } // namespace
 
 llvm::Optional getHover(ParsedAST &AST, Position Pos,
@@ -1081,11 +1113,11 @@
   // FIXME: Fill in HighlightRange with range coming from N->ASTNode.
   auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Alias,
 AST.getHeuristicResolver());
-  if (!Decls.empty()) {
-HI = getHoverContents(Decls.front(), PP, Index, TB);
+  if (const auto *DeclToUse = pickDeclToUse(Decls)) {
+HI = getHoverContents(DeclToUse, PP, Index, TB);
 // Layout info only shown when hovering on the field/class itself.
-if (Decls.front() == N->ASTNode.get())
-  addLayoutInfo(*Decls.front(), *HI);
+if (DeclToUse == N->ASTNode.get())
+  addLayoutInfo(*DeclToUse, *HI);
 // Look for a close enclosing expression to show the value of.
 if (!HI->Value)
   HI->Value = printExprValue(N, AST.getASTContext());
___
cfe-

[PATCH] D133664: [clangd] Fix hover on symbol introduced by using declaration

2022-09-14 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/Hover.cpp:1011
+const NamedDecl *
+pickDeclToUse(const llvm::SmallVector &Candidates) {
+  if (Candidates.empty())

kadircet wrote:
> you can just pass in ArrayRef instead.
Ah of course, forgot about that nice class


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133664

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


[PATCH] D133664: [clangd] Fix hover on symbol introduced by using declaration

2022-09-14 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

Yeah I do have commit access now, so I'll land this by myself.

I don't think I have the permissions to close the corresponding issue on Github 
though, so someone else would need to do that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133664

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


[PATCH] D133664: [clangd] Fix hover on symbol introduced by using declaration

2022-09-15 Thread Tom Praschan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG220d85082349: [clangd] Fix hover on symbol introduced by 
using declaration (authored by tom-anders).

Changed prior to commit:
  https://reviews.llvm.org/D133664?vs=460058&id=460328#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133664

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp

Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -1630,6 +1630,38 @@
 HI.Type = "int";
 HI.Definition = "int foo";
   }},
+  {
+  R"cpp(// Function definition via using declaration
+namespace ns { 
+  void foo(); 
+}
+int main() {
+  using ns::foo;
+  ^[[foo]]();
+}
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "foo";
+HI.Kind = index::SymbolKind::Function;
+HI.NamespaceScope = "ns::";
+HI.Type = "void ()";
+HI.Definition = "void foo()";
+HI.Documentation = "";
+HI.ReturnType = "void";
+HI.Parameters = std::vector{};
+  }},
+  {
+  R"cpp( // using declaration and two possible function declarations
+namespace ns { void foo(int); void foo(char); }
+using ns::foo;
+template  void bar() { [[f^oo]](T{}); }
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "foo";
+HI.Kind = index::SymbolKind::Using;
+HI.NamespaceScope = "";
+HI.Definition = "using ns::foo";
+  }},
   {
   R"cpp(// Macro
 #define MACRO 0
@@ -1734,6 +1766,25 @@
 HI.Definition = "ONE";
 HI.Value = "0";
   }},
+  {
+  R"cpp(// C++20's using enum
+enum class Hello {
+  ONE, TWO, THREE,
+};
+void foo() {
+  using enum Hello;
+  Hello hello = [[O^NE]];
+}
+  )cpp",
+  [](HoverInfo &HI) {
+HI.Name = "ONE";
+HI.Kind = index::SymbolKind::EnumConstant;
+HI.NamespaceScope = "";
+HI.LocalScope = "Hello::";
+HI.Type = "enum Hello";
+HI.Definition = "ONE";
+HI.Value = "0";
+  }},
   {
   R"cpp(// Enumerator in anonymous enum
 enum {
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1006,6 +1006,37 @@
   HI.CallPassType.emplace(PassType);
 }
 
+const NamedDecl *pickDeclToUse(llvm::ArrayRef Candidates) {
+  if (Candidates.empty())
+return nullptr;
+
+  // This is e.g the case for
+  // namespace ns { void foo(); }
+  // void bar() { using ns::foo; f^oo(); }
+  // One declaration in Candidates will refer to the using declaration,
+  // which isn't really useful for Hover. So use the other one,
+  // which in this example would be the actual declaration of foo.
+  if (Candidates.size() <= 2) {
+if (llvm::isa(Candidates.front()))
+  return Candidates.back();
+return Candidates.front();
+  }
+
+  // For something like
+  // namespace ns { void foo(int); void foo(char); }
+  // using ns::foo;
+  // template  void bar() { fo^o(T{}); }
+  // we actually want to show the using declaration,
+  // it's not clear which declaration to pick otherwise.
+  auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) {
+return llvm::isa(D);
+  });
+  if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1)
+return *BaseDecls.begin();
+
+  return Candidates.front();
+}
+
 } // namespace
 
 llvm::Optional getHover(ParsedAST &AST, Position Pos,
@@ -1081,11 +1112,11 @@
   // FIXME: Fill in HighlightRange with range coming from N->ASTNode.
   auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Alias,
 AST.getHeuristicResolver());
-  if (!Decls.empty()) {
-HI = getHoverContents(Decls.front(), PP, Index, TB);
+  if (const auto *DeclToUse = pickDeclToUse(Decls)) {
+HI = getHoverContents(DeclToUse, PP, Index, TB);
 // Layout info only shown when hovering on the field/class itself.
-if (Decls.front() == N->ASTNode.get())
-  addLayoutInfo(*Decls.front(), *HI);
+if (DeclToUse == N->ASTNode.get())
+  addLayoutInfo(*DeclToUse, *HI);
 // Look for a close enclosing expression to show the value of.
 if (!HI->Value)
   HI->

[PATCH] D133664: [clangd] Fix hover on symbol introduced by using declaration

2022-09-15 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

Hmm, Github noticed that I referenced the issue with this commit, but didn't 
close it. 
According to https://github.blog/2013-03-18-closing-issues-across-repositories/ 
closing issues across repos should work, but only if you have push permissions 
in the repo that has the issue


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133664

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


[PATCH] D128202: [clangd] Include "final" when printing class declaration

2022-06-28 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 440676.
tom-anders added a comment.

Check for FinalAttr instead of using isEffectivelyFinal()


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128202

Files:
  clang-tools-extra/clangd/unittests/HoverTests.cpp
  clang/lib/AST/DeclPrinter.cpp


Index: clang/lib/AST/DeclPrinter.cpp
===
--- clang/lib/AST/DeclPrinter.cpp
+++ clang/lib/AST/DeclPrinter.cpp
@@ -1007,6 +1007,12 @@
 }
   }
 
+  if (auto *Def = D->getDefinition()) {
+  if (D->hasAttr()) {
+  Out << " final";
+  }
+  }
+
   if (D->isCompleteDefinition()) {
 // Print the base classes
 if (D->getNumBases()) {
Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -198,7 +198,7 @@
 typename = char,
 int = 0,
 bool Q = false,
-class... Ts> class Foo {};
+class... Ts> class Foo final {};
   template  class T>
   [[F^oo]] foo;
   )cpp",
@@ -209,7 +209,7 @@
  HI.Definition =
  R"cpp(template  class C, typename = 
char, int = 0,
   bool Q = false, class... Ts>
-class Foo {})cpp";
+class Foo final {})cpp";
  HI.TemplateParameters = {
  {{"template  class"},
   std::string("C"),


Index: clang/lib/AST/DeclPrinter.cpp
===
--- clang/lib/AST/DeclPrinter.cpp
+++ clang/lib/AST/DeclPrinter.cpp
@@ -1007,6 +1007,12 @@
 }
   }
 
+  if (auto *Def = D->getDefinition()) {
+  if (D->hasAttr()) {
+  Out << " final";
+  }
+  }
+
   if (D->isCompleteDefinition()) {
 // Print the base classes
 if (D->getNumBases()) {
Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -198,7 +198,7 @@
 typename = char,
 int = 0,
 bool Q = false,
-class... Ts> class Foo {};
+class... Ts> class Foo final {};
   template  class T>
   [[F^oo]] foo;
   )cpp",
@@ -209,7 +209,7 @@
  HI.Definition =
  R"cpp(template  class C, typename = char, int = 0,
   bool Q = false, class... Ts>
-class Foo {})cpp";
+class Foo final {})cpp";
  HI.TemplateParameters = {
  {{"template  class"},
   std::string("C"),
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128826: Go-to-type on smart_ptr now also shows Foo

2022-06-29 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
Herald added a project: clang-tools-extra.

Fixes clangd/clangd#1026


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128826

Files:
  clang-tools-extra/clangd/HeuristicResolver.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
@@ -1786,11 +1786,11 @@
 
 TEST(FindType, All) {
   Annotations HeaderA(R"cpp(
-struct [[Target]] { operator int() const; };
+struct $Target[[Target]] { operator int() const; };
 struct Aggregate { Target a, b; };
 Target t;
 
-template  class smart_ptr {
+template  class $smart_ptr[[smart_ptr]] {
   T& operator*();
   T* operator->();
   T* get();
@@ -1829,11 +1829,11 @@
 ASSERT_GT(A.points().size(), 0u) << Case;
 for (auto Pos : A.points())
   EXPECT_THAT(findType(AST, Pos),
-  ElementsAre(sym("Target", HeaderA.range(), HeaderA.range(
+  ElementsAre(
+sym("Target", HeaderA.range("Target"), HeaderA.range("Target"
   << Case;
   }
 
-  // FIXME: We'd like these cases to work. Fix them and move above.
   for (const llvm::StringRef Case : {
"smart_ptr ^tsmart;",
}) {
@@ -1842,7 +1842,10 @@
 ParsedAST AST = TU.build();
 
 EXPECT_THAT(findType(AST, A.point()),
-Not(Contains(sym("Target", HeaderA.range(), HeaderA.range()
+UnorderedElementsAre(
+  sym("Target", HeaderA.range("Target"), HeaderA.range("Target")),
+  sym("smart_ptr", HeaderA.range("smart_ptr"), HeaderA.range("smart_ptr"))
+))
 << Case;
   }
 }
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -9,6 +9,7 @@
 #include "AST.h"
 #include "FindSymbols.h"
 #include "FindTarget.h"
+#include "HeuristicResolver.h"
 #include "ParsedAST.h"
 #include "Protocol.h"
 #include "Quality.h"
@@ -1907,36 +1908,43 @@
   return QualType();
 }
 
-// Given a type targeted by the cursor, return a type that's more interesting
+// Given a type targeted by the cursor, return one or more types that are more interesting
 // to target.
-static QualType unwrapFindType(QualType T) {
+static llvm::SmallVector unwrapFindType(
+QualType T, const HeuristicResolver* H) {
   if (T.isNull())
-return T;
+return {T};
 
   // If there's a specific type alias, point at that rather than unwrapping.
   if (const auto* TDT = T->getAs())
-return QualType(TDT, 0);
+return {QualType(TDT, 0)};
 
   // Pointers etc => pointee type.
   if (const auto *PT = T->getAs())
-return unwrapFindType(PT->getPointeeType());
+return {unwrapFindType(PT->getPointeeType(), H)};
   if (const auto *RT = T->getAs())
-return unwrapFindType(RT->getPointeeType());
+return {unwrapFindType(RT->getPointeeType(), H)};
   if (const auto *AT = T->getAsArrayTypeUnsafe())
-return unwrapFindType(AT->getElementType());
+return {unwrapFindType(AT->getElementType(), H)};
   // FIXME: use HeuristicResolver to unwrap smart pointers?
 
   // Function type => return type.
   if (auto *FT = T->getAs())
-return unwrapFindType(FT->getReturnType());
+return {unwrapFindType(FT->getReturnType(), H)};
   if (auto *CRD = T->getAsCXXRecordDecl()) {
 if (CRD->isLambda())
-  return unwrapFindType(CRD->getLambdaCallOperator()->getReturnType());
+  return {unwrapFindType(CRD->getLambdaCallOperator()->getReturnType(), H)};
 // FIXME: more cases we'd prefer the return type of the call operator?
 //std::function etc?
   }
 
-  return T;
+  // For smart pointer types, add the underlying type
+  llvm::SmallVector Result = {T};
+  if (H)
+if (const auto* PointeeType = H->getPointeeType(T.getNonReferenceType().getTypePtr()))
+  Result.append(unwrapFindType(QualType(PointeeType, 0), H));
+
+  return Result;
 }
 
 std::vector findType(ParsedAST &AST, Position Pos) {
@@ -1951,10 +1959,14 @@
   // The general scheme is: position -> AST node -> type -> declaration.
   auto SymbolsFromNode =
   [&AST](const SelectionTree::Node *N) -> std::vector {
-QualType Type = unwrapFindType(typeForNode(N));
-if (Type.isNull())
-  return {};
-return locateSymbolForType(AST, Type);
+std::vector LocatedSymbols;
+
+for (const QualType& Type : unwrapFindType(typeForNode(N), AST.getHeuristicResolver()))
+  if (!Type.isNull()) {
+llvm::copy(locateSymbolForType

[PATCH] D128826: Go-to-type on smart_ptr now also shows Foo

2022-06-29 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/HeuristicResolver.h:75
+  // could look up the name appearing on the RHS.
+  const Type *getPointeeType(const Type *T) const;
+

Not sure if it's the right call to make this public? The documentation needs to 
be adapted at least I think


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128826

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


[PATCH] D128826: Go-to-type on smart_ptr now also shows Foo

2022-06-29 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

In D128826#3619167 , @sammccall wrote:

> Thanks! I just have a question if this behavior should be even "stronger":
>
> In most editors, if you return one result you go straight there, if you 
> return two results you get a menu.
> A menu is significantly worse than going straight to the right result - the 
> UI is clunkier and the choice interrupts your workflow.
>
> So my question is, do you think that we should *only* return the pointee in 
> these cases?
>
> (It's possible to change this later, but I'd like to take a reasonable guess 
> as this is forcing an API change from Type -> vector)
> cc @kadircet

I'm using this with neovim's builtin LSP, where when there are multiple results 
it takes me to the first one, and also opens the quickfix window that shows all 
results. But I can see how the current implementation could be annoying with 
other editors.

So here's what I thought: Say you have a variable that's a smart pointer and 
trigger textDocument/typeDefinition on it and there's only a single result that 
takes you straight to the type. In this case, you might not even know that the 
type is actually wrapped inside a smart pointer and might make wrong 
assumptions about the code. Of course you could've done a Hover beforehand, but 
in the case where there are 2 results, you don't need that extra step.

Maybe it would be best to make this configurable via the config file? Since 
most people are using "most editors", I think taking you straight to the type 
would be better, but I'm really not sure.

Btw, I think it would be useful to extend this feature to not only smart 
pointers, but also containers like std::vector. Then there'd also be the 
question what would happen for std::vector>: should there be 
1, 2 or 3 results?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128826

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


[PATCH] D128826: Go-to-type on smart_ptr now also shows Foo

2022-06-29 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

> In D128826#3619339 , @tom-anders 
> wrote:
>
>> I'm using this with neovim's builtin LSP, where when there are multiple 
>> results it takes me to the first one, and also opens the quickfix window 
>> that shows all results. But I can see how the current implementation could 
>> be annoying with other editors.
>
> (Interesting, I'm using the same and find it annoying: it focuses the 
> quickfix window and that's disruptive enough that I never noticed the cursor 
> also moved. But https://github.com/neovim/neovim/pull/14878 lists some 
> workarounds)

(Ah, I also forgot that I'm not actually using quickfix, but rather 
https://github.com/folke/trouble.nvim, which also gets focused but has a 
preview feature)

>> So here's what I thought: Say you have a variable that's a smart pointer and 
>> trigger textDocument/typeDefinition on it and there's only a single result 
>> that takes you straight to the type. In this case, you might not even know 
>> that the type is actually wrapped inside a smart pointer and might make 
>> wrong assumptions about the code. Of course you could've done a Hover 
>> beforehand, but in the case where there are 2 results, you don't need that 
>> extra step.
>
> Yeah. There's no guarantee the type in question is well-represented by a 
> decl, but this is a bit confusing.
> I think it might still be worth it for specific types like `unique_ptr`, 
> but for `vector` it's too surprising even if you want Foo 99% of the 
> time.

Right, maybe it would make sense to go straight to `T` for declarations, but 
include `smart_ptr` when it's used in an expression? But that's something for a 
follow-up patch.

>> Maybe it would be best to make this configurable via the config file? Since 
>> most people are using "most editors", I think taking you straight to the 
>> type would be better, but I'm really not sure.
>
> Making it configurable doesn't actually solve the problem: we still need to 
> think hard about what the best default is, because relatively few users ever 
> configure anything.
> So let's not rule it out, but there's not much point doing it in this patch.
>
>> Btw, I think it would be useful to extend this feature to not only smart 
>> pointers, but also containers like std::vector. Then there'd also be the 
>> question what would happen for std::vector>: should there 
>> be 1, 2 or 3 results?
>
> Yeah I find this pretty compelling. I think we should start with the approach 
> in this patch, returning {pointer, pointee}, and iterate from there (add 
> containers, or templates in general, or omit the pointer type in certain 
> special cases...).

Agreed. The heuristic there would be "template class with at least 1 type 
parameter, where all other parameters except the first have a default value", 
right? 
But maybe it even makes sense for stuff like `std::map`, so it's more like 
"template class, with `n>0` type template parameters, followed by `m>=0` 
defaulted template parameters"
Do we already have an issue for this? If not, I'd open a new one.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128826

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


[PATCH] D128826: Go-to-type on smart_ptr now also shows Foo

2022-06-29 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/HeuristicResolver.h:75
+  // could look up the name appearing on the RHS.
+  const Type *getPointeeType(const Type *T) const;
+

sammccall wrote:
> tom-anders wrote:
> > Not sure if it's the right call to make this public? The documentation 
> > needs to be adapted at least I think
> It's a bit unfortunate that it doesn't fit the usual pattern of "resolve the 
> target of this AST node", but it's fairly closely related, it needs to use 
> the Ctx in the same way, and it's already implemented here... I think it's OK 
> (at least I can't see a better alternative).
> 
> We should probably have a unit test for it though.
Not really sure where to put the unit test, probably FindTargetTests.cpp? It 
looks like it tests `HeuristicResolver` implicitly. Couldn't find anything that 
tests `HeuristicResolver` directly.



Comment at: clang-tools-extra/clangd/XRefs.cpp:1913
 // to target.
-static QualType unwrapFindType(QualType T) {
+static llvm::SmallVector unwrapFindType(
+QualType T, const HeuristicResolver* H) {

sammccall wrote:
> Ergonomically I might prefer `void unwrapFindType(QualType, ..., 
> vector& Out)` or so.
> This tends to compose a bit better IMO by making all the cases look similar 
> whether you're adding one type or several or combining lists.
> 
> You can still `return Out.push_back(T)` etc on a single line.
Ah yes that makes sense. Didn't think about the `return Out.push_back(T)` trick 
to keep using early returns, thought I'd have to add a ton of `else if`s 
instead.



Comment at: clang-tools-extra/clangd/XRefs.cpp:1966
+  if (!Type.isNull()) {
+llvm::copy(locateSymbolForType(AST, Type), 
std::back_inserter(LocatedSymbols));
+  }

sammccall wrote:
> we now have the potential for duplicates (already in this patch in fact: 
> unique_ptr>.
> 
> Deduplicating types isn't that useful (unique_ptr> != 
> unique_ptr), I guess it's either deduplicate locations or allow the 
> duplicates.
> If you choose to allow them, probably worth a comment why.
Not sure about this either. I'll go with not deduplicating and adding a comment 
for now.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128826

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


[PATCH] D128826: Go-to-type on smart_ptr now also shows Foo

2022-06-29 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/XRefs.cpp:1913
 // to target.
-static QualType unwrapFindType(QualType T) {
+static llvm::SmallVector unwrapFindType(
+QualType T, const HeuristicResolver* H) {

tom-anders wrote:
> sammccall wrote:
> > Ergonomically I might prefer `void unwrapFindType(QualType, ..., 
> > vector& Out)` or so.
> > This tends to compose a bit better IMO by making all the cases look similar 
> > whether you're adding one type or several or combining lists.
> > 
> > You can still `return Out.push_back(T)` etc on a single line.
> Ah yes that makes sense. Didn't think about the `return Out.push_back(T)` 
> trick to keep using early returns, thought I'd have to add a ton of `else 
> if`s instead.
It makes the call side a bit uglier though - Is it okay to add a convenience 
wrapper `vector unwrapFindType(QualType, HeuristicResolver*)` that 
forwards to the overload that uses the out-parameter?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128826

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


[PATCH] D128826: Go-to-type on smart_ptr now also shows Foo

2022-06-29 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders marked 6 inline comments as done.
tom-anders added a comment.

> In D128826#3619956 , @tom-anders 
> wrote:
>
 So here's what I thought: Say you have a variable that's a smart pointer 
 and trigger textDocument/typeDefinition on it and there's only a single 
 result that takes you straight to the type. In this case, you might not 
 even know that the type is actually wrapped inside a smart pointer and 
 might make wrong assumptions about the code. Of course you could've done a 
 Hover beforehand, but in the case where there are 2 results, you don't 
 need that extra step.
>>>
>>> Yeah. There's no guarantee the type in question is well-represented by a 
>>> decl, but this is a bit confusing.
>>> I think it might still be worth it for specific types like 
>>> `unique_ptr`, but for `vector` it's too surprising even if you 
>>> want Foo 99% of the time.
>>
>> Right, maybe it would make sense to go straight to `T` for declarations, but 
>> include `smart_ptr` when it's used in an expression? But that's something 
>> for a follow-up patch.
>
> Hmm, is the distinction that the type is written in the declaration (not 
> `auto`)? I'm not sure it's worth specializing behavior for that scenario too 
> much, when it's not too hard to go-to-definition on the specific token you 
> want.
> The chance of guessing right has to be weighed against keeping the behavior 
> predictable and comprehensible...

Yes that's what I meant, but I agree with you here.




Comment at: clang-tools-extra/clangd/XRefs.cpp:1913
 // to target.
-static QualType unwrapFindType(QualType T) {
+static llvm::SmallVector unwrapFindType(
+QualType T, const HeuristicResolver* H) {

sammccall wrote:
> tom-anders wrote:
> > tom-anders wrote:
> > > sammccall wrote:
> > > > Ergonomically I might prefer `void unwrapFindType(QualType, ..., 
> > > > vector& Out)` or so.
> > > > This tends to compose a bit better IMO by making all the cases look 
> > > > similar whether you're adding one type or several or combining lists.
> > > > 
> > > > You can still `return Out.push_back(T)` etc on a single line.
> > > Ah yes that makes sense. Didn't think about the `return Out.push_back(T)` 
> > > trick to keep using early returns, thought I'd have to add a ton of `else 
> > > if`s instead.
> > It makes the call side a bit uglier though - Is it okay to add a 
> > convenience wrapper `vector unwrapFindType(QualType, 
> > HeuristicResolver*)` that forwards to the overload that uses the 
> > out-parameter?
> Just the final call, not the recursive calls, right? They can be `return 
> unwrapFindType(...);` too.
> 
> It doesn't look ugly to me (2 extra lines at one callsite) but up to you.
Yeah just the final call. I just don't like adding (non-const) helper variables 
on the call site.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128826

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


[PATCH] D128826: Go-to-type on smart_ptr now also shows Foo

2022-06-29 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 441147.
tom-anders marked an inline comment as done.
tom-anders added a comment.

- Remove obsolete comment
- Return empty vector when type isNull()
- Add comment about why we don't deduplicate results
- Use out-parameter in unwrapFindType to make structure more consistent


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128826

Files:
  clang-tools-extra/clangd/HeuristicResolver.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
@@ -1786,11 +1786,11 @@
 
 TEST(FindType, All) {
   Annotations HeaderA(R"cpp(
-struct [[Target]] { operator int() const; };
+struct $Target[[Target]] { operator int() const; };
 struct Aggregate { Target a, b; };
 Target t;
 
-template  class smart_ptr {
+template  class $smart_ptr[[smart_ptr]] {
   T& operator*();
   T* operator->();
   T* get();
@@ -1829,11 +1829,11 @@
 ASSERT_GT(A.points().size(), 0u) << Case;
 for (auto Pos : A.points())
   EXPECT_THAT(findType(AST, Pos),
-  ElementsAre(sym("Target", HeaderA.range(), HeaderA.range(
+  ElementsAre(
+sym("Target", HeaderA.range("Target"), HeaderA.range("Target"
   << Case;
   }
 
-  // FIXME: We'd like these cases to work. Fix them and move above.
   for (const llvm::StringRef Case : {
"smart_ptr ^tsmart;",
}) {
@@ -1842,7 +1842,10 @@
 ParsedAST AST = TU.build();
 
 EXPECT_THAT(findType(AST, A.point()),
-Not(Contains(sym("Target", HeaderA.range(), HeaderA.range()
+UnorderedElementsAre(
+  sym("Target", HeaderA.range("Target"), HeaderA.range("Target")),
+  sym("smart_ptr", HeaderA.range("smart_ptr"), HeaderA.range("smart_ptr"))
+))
 << Case;
   }
 }
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -9,6 +9,7 @@
 #include "AST.h"
 #include "FindSymbols.h"
 #include "FindTarget.h"
+#include "HeuristicResolver.h"
 #include "ParsedAST.h"
 #include "Protocol.h"
 #include "Quality.h"
@@ -1907,38 +1908,54 @@
   return QualType();
 }
 
-// Given a type targeted by the cursor, return a type that's more interesting
+// Given a type targeted by the cursor, return one or more types that are more interesting
 // to target.
-static QualType unwrapFindType(QualType T) {
+static void unwrapFindType(
+QualType T, const HeuristicResolver* H, llvm::SmallVector& Out) {
   if (T.isNull())
-return T;
+return;
 
   // If there's a specific type alias, point at that rather than unwrapping.
   if (const auto* TDT = T->getAs())
-return QualType(TDT, 0);
+return Out.push_back(QualType(TDT, 0));
 
   // Pointers etc => pointee type.
   if (const auto *PT = T->getAs())
-return unwrapFindType(PT->getPointeeType());
+return unwrapFindType(PT->getPointeeType(), H, Out);
   if (const auto *RT = T->getAs())
-return unwrapFindType(RT->getPointeeType());
+return unwrapFindType(RT->getPointeeType(), H, Out);
   if (const auto *AT = T->getAsArrayTypeUnsafe())
-return unwrapFindType(AT->getElementType());
-  // FIXME: use HeuristicResolver to unwrap smart pointers?
+return unwrapFindType(AT->getElementType(), H, Out);
 
   // Function type => return type.
   if (auto *FT = T->getAs())
-return unwrapFindType(FT->getReturnType());
+return unwrapFindType(FT->getReturnType(), H, Out);
   if (auto *CRD = T->getAsCXXRecordDecl()) {
 if (CRD->isLambda())
-  return unwrapFindType(CRD->getLambdaCallOperator()->getReturnType());
+  return unwrapFindType(CRD->getLambdaCallOperator()->getReturnType(), H, Out);
 // FIXME: more cases we'd prefer the return type of the call operator?
 //std::function etc?
   }
 
-  return T;
+  // For smart pointer types, add the underlying type
+  if (H)
+if (const auto* PointeeType = H->getPointeeType(T.getNonReferenceType().getTypePtr())) {
+unwrapFindType(QualType(PointeeType, 0), H, Out);
+return Out.push_back(T);
+}
+
+  return Out.push_back(T);
 }
 
+// Convenience overload, to allow calling this without the out-parameter
+static llvm::SmallVector unwrapFindType(
+QualType T, const HeuristicResolver* H) {
+llvm::SmallVector Result;
+unwrapFindType(T, H, Result);
+return Result;
+}
+
+
 std::vector findType(ParsedAST &AST, Position Pos) {
   const SourceManager &SM = AST.getSourceManager();
   auto Offset = positionToOffset(SM.getBufferData(SM.getMainFileID()), P

[PATCH] D128826: Go-to-type on smart_ptr now also shows Foo

2022-07-10 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

@sammccall I think you can merge this for me now (and also 
https://reviews.llvm.org/D128202)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128826

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


[PATCH] D129971: [clangd][WIP] Add doxygen parsing for Hover

2022-07-17 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: usaxena95, kadircet, arphaman, mgorny.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, llvm-commits, MaskRay, ilya-biryukov.
Herald added projects: LLVM, clang-tools-extra.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129971

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeCompletionStrings.cpp
  clang-tools-extra/clangd/CodeCompletionStrings.h
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/Hover.h
  clang-tools-extra/clangd/SymbolDocumentation.cpp
  clang-tools-extra/clangd/SymbolDocumentation.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn

Index: llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
===
--- llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
+++ llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
@@ -113,6 +113,7 @@
 "SemanticHighlighting.cpp",
 "SemanticSelection.cpp",
 "SourceCode.cpp",
+"SymbolDocumentation.cpp"
 "TUScheduler.cpp",
 "TidyProvider.cpp",
 "URI.cpp",
Index: clang-tools-extra/clangd/index/SymbolCollector.cpp
===
--- clang-tools-extra/clangd/index/SymbolCollector.cpp
+++ clang-tools-extra/clangd/index/SymbolCollector.cpp
@@ -914,7 +914,8 @@
   /*IncludeBriefComments*/ false);
   std::string Documentation =
   formatDocumentation(*CCS, getDocComment(Ctx, SymbolCompletion,
-  /*CommentsFromHeaders=*/true));
+  /*CommentsFromHeaders=*/true)
+.CommentText);
   if (!(S.Flags & Symbol::IndexedForCodeCompletion)) {
 if (Opts.StoreAllDocumentation)
   S.Documentation = Documentation;
Index: clang-tools-extra/clangd/SymbolDocumentation.h
===
--- /dev/null
+++ clang-tools-extra/clangd/SymbolDocumentation.h
@@ -0,0 +1,71 @@
+//===--- SymbolDocumentation.h ==-*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// Class to parse doxygen comments into a flat structure for consumption
+// in e.g. Hover and Code Completion
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SYMBOLDOCUMENTATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SYMBOLDOCUMENTATION_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Comment.h"
+#include "clang/AST/CommentVisitor.h"
+
+namespace clang {
+namespace clangd {
+
+struct ParameterDocumentation {
+  llvm::StringRef Name;
+  std::string Description;
+  llvm::Optional PassDirection;
+};
+
+struct ExceptionDocumentation {
+  llvm::StringRef Exception;
+  std::string Description;
+};
+
+struct SymbolDocumentation {
+  SymbolDocumentation(const RawComment &RC, const ASTContext &Ctx,
+  const Preprocessor *PP, const Decl *D);
+
+  void visitFullComment(const comments::FullComment *FC);
+  void visitParamCommandComment(const comments::ParamCommandComment *P);
+
+  SymbolDocumentation() = default;
+  SymbolDocumentation(const std::string &Doc) : CommentText(Doc) {}
+
+  bool empty() const { return CommentText.empty(); }
+
+  std::string Brief;
+
+  std::string Returns;
+
+  llvm::SmallVector Notes;
+  llvm::SmallVector Warnings;
+
+  /// \\param commands that match a parameter in the function declaration
+  std::map MatchingParameterDocs;
+
+  llvm::SmallVector UnmatchedParameterDocs;
+
+  llvm::SmallVector Throws;
+
+  /// All the paragraphs we don't have any special handling for, e.g. \details
+  std::string Description;
+
+  /// The full text of the doxygen comment
+  std::string CommentText;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_SYMBOLDOCUMENTATION_H
Index: clang-tools-extra/clangd/SymbolDocumentation.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/SymbolDocumentation.cpp
@@ -0,0 +1,149 @@
+//===--- SymbolDocumentation.cpp ==---*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "SymbolDoc

[PATCH] D129971: [clangd][WIP] Add doxygen parsing for Hover

2022-07-17 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders abandoned this revision.
tom-anders added a comment.

Sorry, meant to make this a draft


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129971

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


[PATCH] D108320: Add semantic token modifier for non-const reference parameter

2021-08-18 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: usaxena95, kadircet, arphaman.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
Herald added a project: clang-tools-extra.

See https://github.com/clangd/clangd/issues/839


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D108320

Files:
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/SemanticHighlighting.h
  clang-tools-extra/clangd/test/initialize-params.test
  clang-tools-extra/clangd/test/semantic-tokens.test
  clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -729,6 +729,28 @@
   }
 };
   )cpp",
+  // Modifier for variables passed as non-const references
+  R"cpp(
+void $Function_decl[[fun]](int $Parameter_decl[[value]], const int& $Parameter_decl_readonly[[constRef]], 
+   int& $Parameter_decl[[ref]], int* $Parameter_decl[[ptr]], 
+   int $Parameter_decl[[defaultParameter]] = 3);
+struct $Class_decl[[S]] {
+  $Class_decl[[S]](int $Parameter_decl[[value]], const int& $Parameter_decl_readonly[[constRef]], 
+int& $Parameter_decl[[ref]], int* $Parameter_decl[[ptr]], 
+int $Parameter_decl[[defaultParameter]] = 3);
+  int $Field_decl[[field]];
+};
+void $Function_decl[[bar]]() {
+  int $LocalVariable_decl[[foo]];
+  $Function[[fun]]($LocalVariable[[foo]], $LocalVariable[[foo]], 
+   $LocalVariable_passedByNonConstRef[[foo]], &$LocalVariable[[foo]]);
+
+  $Class[[S]] $LocalVariable_decl[[s]]($LocalVariable[[foo]], $LocalVariable[[foo]], 
+   $LocalVariable_passedByNonConstRef[[foo]], &$LocalVariable[[foo]]);
+  $Function[[fun]]($LocalVariable[[s]].$Field[[field]], $LocalVariable[[s]].$Field[[field]], 
+   $LocalVariable[[s]].$Field_passedByNonConstRef[[field]], &$LocalVariable[[s]].$Field[[field]]);
+}
+  )cpp",
   };
   for (const auto &TestCase : TestCases)
 // Mask off scope modifiers to keep the tests manageable.
Index: clang-tools-extra/clangd/test/semantic-tokens.test
===
--- clang-tools-extra/clangd/test/semantic-tokens.test
+++ clang-tools-extra/clangd/test/semantic-tokens.test
@@ -23,7 +23,7 @@
 # CHECK-NEXT:  4,
 # CHECK-NEXT:  1,
 # CHECK-NEXT:  0,
-# CHECK-NEXT:  4097
+# CHECK-NEXT:  8193
 # CHECK-NEXT:],
 # CHECK-NEXT:"resultId": "1"
 # CHECK-NEXT:  }
@@ -49,7 +49,7 @@
 # CHECK-NEXT:  4,
 # CHECK-NEXT:  1,
 # CHECK-NEXT:  0,
-# CHECK-NEXT:  4097
+# CHECK-NEXT:  8193
 # CHECK-NEXT:],
 #Inserted at position 1
 # CHECK-NEXT:"deleteCount": 0,
@@ -72,12 +72,12 @@
 # CHECK-NEXT:  4,
 # CHECK-NEXT:  1,
 # CHECK-NEXT:  0,
-# CHECK-NEXT:  4097,
+# CHECK-NEXT:  8193,
 # CHECK-NEXT:  1,
 # CHECK-NEXT:  4,
 # CHECK-NEXT:  1,
 # CHECK-NEXT:  0,
-# CHECK-NEXT:  4097
+# CHECK-NEXT:  8193
 # CHECK-NEXT:],
 # CHECK-NEXT:"resultId": "3"
 # CHECK-NEXT:  }
Index: clang-tools-extra/clangd/test/initialize-params.test
===
--- clang-tools-extra/clangd/test/initialize-params.test
+++ clang-tools-extra/clangd/test/initialize-params.test
@@ -91,6 +91,7 @@
 # CHECK-NEXT:"virtual",
 # CHECK-NEXT:"dependentName",
 # CHECK-NEXT:"defaultLibrary",
+# CHECK-NEXT:"passedByNonConstRef",
 # CHECK-NEXT:"functionScope",
 # CHECK-NEXT:"classScope",
 # CHECK-NEXT:"fileScope",
Index: clang-tools-extra/clangd/SemanticHighlighting.h
===
--- clang-tools-extra/clangd/SemanticHighlighting.h
+++ clang-tools-extra/clangd/SemanticHighlighting.h
@@ -70,6 +70,8 @@
   DependentName,
   DefaultLibrary,
 
+  PassedByNonConstRef,
+
   FunctionScope,
   ClassScope,
   FileScope,
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -290,10 +290,12 @@
 }
 
 unsigned evaluateHighlightPriority(const HighlightingToken &Tok) {
-  enum HighlightPriority { Dependent = 0, Resolved = 1 };
+  enum HighlightPriority { Dependent = 0, ResolvedButUnknown = 1, Res

[PATCH] D108320: Add semantic token modifier for non-const reference parameter

2021-08-19 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders planned changes to this revision.
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:547
+if (isa(Arg)) {
+  Location = Arg->getBeginLoc();
+} else if (auto *M = dyn_cast(Arg)) {

sammccall wrote:
> nridge wrote:
> > For a qualified name (e.g. `A::B`), I think this is going to return the 
> > beginning of the qualifier, whereas we only want to highlight the last name 
> > (otherwise there won't be a matching token from the first pass).
> > 
> > So I think we want `getLocation()` instead.
> > 
> > (Also makes a good test case.)
> And getLocation() will do the right thing for DeclRefExpr, MemberExpr, and 
> others, so this can just be `isa` with no need for 
> dyn_cast.
I'm not sure which getLocation() you're talking about here. There's 
DeclRefExpr::getLocation(), but neither Expr::getLocation() nor 
MemberExpr::getLocation(). Am I missing something?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D108320

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


[PATCH] D108320: Add semantic token modifier for non-const reference parameter

2021-08-19 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:538
+for (size_t I = 0; I < FD->getNumParams(); ++I) {
+  if (const auto *Param = FD->getParamDecl(I)) {
+auto T = Param->getType();

sammccall wrote:
> I feel like you'd be better off using the FunctionProtoType and iterating 
> over argument types, rather than the argument declarations on a particular 
> declaration of the function.
> 
> e.g. this code is legal in C:
> ```
> int x(); // i suspect this is the canonical decl
> int x(int); // but this one provides the type
> ```
> We don't have references in C of course!, but maybe similar issues lurking...
I'm not really sure how to get from the CallExpr to the FunctionProtoType, can 
you give me a hint? 



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:547
+if (isa(Arg)) {
+  Location = Arg->getBeginLoc();
+} else if (auto *M = dyn_cast(Arg)) {

sammccall wrote:
> tom-anders wrote:
> > sammccall wrote:
> > > nridge wrote:
> > > > For a qualified name (e.g. `A::B`), I think this is going to return the 
> > > > beginning of the qualifier, whereas we only want to highlight the last 
> > > > name (otherwise there won't be a matching token from the first pass).
> > > > 
> > > > So I think we want `getLocation()` instead.
> > > > 
> > > > (Also makes a good test case.)
> > > And getLocation() will do the right thing for DeclRefExpr, MemberExpr, 
> > > and others, so this can just be `isa` with no 
> > > need for dyn_cast.
> > I'm not sure which getLocation() you're talking about here. There's 
> > DeclRefExpr::getLocation(), but neither Expr::getLocation() nor 
> > MemberExpr::getLocation(). Am I missing something?
> No, I think I'm just going mad (I was thinking of Decl::getLocation I guess).
> Never mind and sorry!
np :D 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D108320

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


[PATCH] D134137: [clangd] Return earlier when snippet is empty

2022-10-23 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

In D134137#3877726 , @sammccall wrote:

> It's not surprising that we often don't crash here, the "obvious" lowering of 
> `S.front()` is `*S.data()` which is perfectly valid (will be 0 for an empty 
> string).
>
> One way to crash on this is to build with libstdc++'s debug iterators, which 
> assert on this. Fedora seems to be building (some of) their packages in this 
> mode, such that they crash but (sometimes?) do not print the assertion 
> message. This was the cause in 
> https://github.com/clangd/vscode-clangd/issues/400.

Interesting, FYI I was able to reproduce this on Arch Linux.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134137

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


[PATCH] D135536: [clangd] Hover: Only drop UsingDecl instead of BaseUsingDecl

2022-10-26 Thread Tom Praschan 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 rGd2135df4b5fb: [clangd] Hover: Only drop UsingDecl instead of 
BaseUsingDecl (authored by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135536

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


Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1017,7 +1017,7 @@
   // which isn't really useful for Hover. So use the other one,
   // which in this example would be the actual declaration of foo.
   if (Candidates.size() <= 2) {
-if (llvm::isa(Candidates.front()))
+if (llvm::isa(Candidates.front()))
   return Candidates.back();
 return Candidates.front();
   }
@@ -1029,7 +1029,7 @@
   // we actually want to show the using declaration,
   // it's not clear which declaration to pick otherwise.
   auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) {
-return llvm::isa(D);
+return llvm::isa(D);
   });
   if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1)
 return *BaseDecls.begin();


Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1017,7 +1017,7 @@
   // which isn't really useful for Hover. So use the other one,
   // which in this example would be the actual declaration of foo.
   if (Candidates.size() <= 2) {
-if (llvm::isa(Candidates.front()))
+if (llvm::isa(Candidates.front()))
   return Candidates.back();
 return Candidates.front();
   }
@@ -1029,7 +1029,7 @@
   // we actually want to show the using declaration,
   // it's not clear which declaration to pick otherwise.
   auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) {
-return llvm::isa(D);
+return llvm::isa(D);
   });
   if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1)
 return *BaseDecls.begin();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136925: [clangd] Index scoped enums for code completion

2022-10-28 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added a reviewer: nridge.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

As discussed in https://github.com/clangd/clangd/issues/1082:

"Without all-scopes-completion, such nested symbols would indeed be unnecessary 
in the
index, because the only way you could get them as a completion result is if 
you're
invoking the completion in the nested scope (e.g. Foo::^), in which case result 
can be
obtained from the AST."

I tested this on the LLVM codebase and there was no significant increase in 
index size
(less than 1MB). I think this makes sense if we look at the additional data 
that is stored
in SymbolCollector::addDeclaration when IndexedForCodeCompletion is set:

- Signature: Empty string for enum constants
- SnippetSuffix: Empty
- Documentation: Empty most of the time
- ReturnType and Type: Same string for all enum constants within a enum, so 
only two additional strings per indexed enum


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136925

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/index/Serialization.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
@@ -1316,6 +1316,11 @@
   Black
 };
 }
+class Color3 {
+  enum {
+Blue
+  };
+};
   )";
   runSymbolCollector(Header, /*Main=*/"");
   EXPECT_THAT(Symbols,
@@ -1324,7 +1329,9 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
+  AllOf(qName("Color3"), forCodeCompletion(true)),
+  AllOf(qName("Color3::Blue"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
   AllOf(qName("ns::Black"), forCodeCompletion(true;
 }
Index: clang-tools-extra/clangd/index/Serialization.cpp
===
--- clang-tools-extra/clangd/index/Serialization.cpp
+++ clang-tools-extra/clangd/index/Serialization.cpp
@@ -455,7 +455,7 @@
 // The current versioning scheme is simple - non-current versions are rejected.
 // If you make a breaking change, bump this version number to invalidate stored
 // data. Later we may want to support some backward compatibility.
-constexpr static uint32_t Version = 17;
+constexpr static uint32_t Version = 18;
 
 llvm::Expected readRIFF(llvm::StringRef Data,
  SymbolOrigin Origin) {
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -291,7 +291,7 @@
 // For index-based completion, we only consider:
 //   * symbols in namespaces or translation unit scopes (e.g. no class
 // members, no locals)
-//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * enum constants (both scoped and unscoped)
 //   * primary templates (no specializations)
 // For the other cases, we let Clang do the completion because it does not
 // need any non-local information and it will be much better at following
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -2129,8 +2129,10 @@
   if (InTopLevelScope(ND))
 return true;
 
+  // Always index enum constants, even if they're not in the top level scope: 
when
+  // --all-scopes-completion is set, we'll want to complete those as well.
   if (const auto *EnumDecl = dyn_cast(ND.getDeclContext()))
-return InTopLevelScope(*EnumDecl) && !EnumDecl->isScoped();
+return true;
 
   return false;
 }


Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1316,6 +1316,11 @@
   Black
 };
 }
+class Color3 {
+  enum {
+Blue
+  };
+};
   )";
   runSymbolCollector(Header, /*Main=*/"");
   EXPECT_THAT(Symbols,
@@ -1324,7 +1329,9 @@
 

[PATCH] D136925: [clangd] Index scoped enums for code completion

2022-10-30 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:2133
   if (const auto *EnumDecl = dyn_cast(ND.getDeclContext()))
-return InTopLevelScope(*EnumDecl) && !EnumDecl->isScoped();
 

nridge wrote:
> Just to make sure I understand:
> 
> By also removing the `!isScoped()` condition, in addition to changing the 
> behaviour for the scenario described in 
> https://github.com/clangd/clangd/issues/1082 (enum declared at class scope), 
> you are also changing the behaviour for scenarios like this:
> 
> ```
> enum class Foo { Bar };  // at any scope, including global
> ```
> 
> Completing `Bar` will now offer `Foo::Bar` when previously it didn't.
> 
> Is this your intention?
Ah sorry, that is indeed not what I described in the issue - but yeah this 
change is intended here,  IMO it's more consistent from a user perspective: Why 
should **all-scopes**-completion ignore **scoped** enums?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136925

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


[PATCH] D137040: [clangd] Add heuristic for dropping snippet when completing member function pointer

2022-10-30 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

This implements the 1st heuristic mentioned in 
https://github.com/clangd/clangd/issues/968#issuecomment-1002242704:

When completing a function that names a non-static member of a class, and we 
are not inside that class's scope, assume the reference will not be a call (and 
thus don't add the snippetSuffix)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D137040

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
@@ -500,6 +500,63 @@
  snippetSuffix("(${1:int i}, ${2:const float f})")));
 }
 
+TEST(CompletionTest, HeuristicsForMemberFunctionCompletion) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.EnableSnippets = true;
+
+  Annotations Code(R"cpp(
+  struct Foo {
+static int staticMethod();
+int method() const;
+Foo() {
+  this->$keepSnippet^
+  $keepSnippet^
+  Foo::$keepSnippet^
+}
+  };
+
+  struct Derived : Foo {
+Derived() {
+  Foo::$keepSnippet^
+}
+  };
+
+  struct OtherClass {
+OtherClass() {
+  Foo f;
+  f.$keepSnippet^
+  &Foo::$noSnippet^
+}
+  };
+
+  int main() {
+Foo f;
+f.$keepSnippet^
+&Foo::$noSnippet^
+  }
+  )cpp");
+  auto TU = TestTU::withCode(Code.code());
+
+  for (const auto &P : Code.points("noSnippet")) {
+auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
+EXPECT_THAT(Results.Completions,
+Contains(AllOf(named("method"), snippetSuffix("";
+  }
+
+  for (const auto &P : Code.points("keepSnippet")) {
+auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
+EXPECT_THAT(Results.Completions,
+Contains(AllOf(named("method"), snippetSuffix("()";
+  }
+
+  // static method will always keep the snippet
+  for (const auto &P : Code.points()) {
+auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
+EXPECT_THAT(Results.Completions,
+Contains(AllOf(named("staticMethod"), snippetSuffix("()";
+  }
+}
+
 TEST(CompletionTest, NoSnippetsInUsings) {
   clangd::CodeCompleteOptions Opts;
   Opts.EnableSnippets = true;
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -291,7 +291,8 @@
 // computed from the first candidate, in the constructor.
 // Others vary per candidate, so add() must be called for remaining candidates.
 struct CodeCompletionBuilder {
-  CodeCompletionBuilder(ASTContext *ASTCtx, const CompletionCandidate &C,
+  CodeCompletionBuilder(ASTContext *ASTCtx, DeclContext *SemaDeclCtx,
+const CompletionCandidate &C,
 CodeCompletionString *SemaCCS,
 llvm::ArrayRef QueryScopes,
 const IncludeInserter &Includes,
@@ -299,13 +300,15 @@
 CodeCompletionContext::Kind ContextKind,
 const CodeCompleteOptions &Opts,
 bool IsUsingDeclaration, tok::TokenKind NextTokenKind)
-  : ASTCtx(ASTCtx),
+  : ASTCtx(ASTCtx), SemaDeclCtx(SemaDeclCtx),
 EnableFunctionArgSnippets(Opts.EnableFunctionArgSnippets),
-IsUsingDeclaration(IsUsingDeclaration), NextTokenKind(NextTokenKind) {
+ContextKind(ContextKind), IsUsingDeclaration(IsUsingDeclaration),
+NextTokenKind(NextTokenKind) {
 Completion.Deprecated = true; // cleared by any non-deprecated overload.
 add(C, SemaCCS);
 if (C.SemaResult) {
   assert(ASTCtx);
+  assert(SemaDeclCtx);
   Completion.Origin |= SymbolOrigin::AST;
   Completion.Name = std::string(llvm::StringRef(SemaCCS->getTypedText()));
   Completion.FilterText = SemaCCS->getAllTypedText();
@@ -412,6 +415,8 @@
   getSignature(*SemaCCS, &S.Signature, &S.SnippetSuffix,
&Completion.RequiredQualifier, IsPattern);
   S.ReturnType = getReturnType(*SemaCCS);
+  maybeClearSnippetSuffixForMethodFunctionPointer(*C.SemaResult,
+  S.SnippetSuffix);
 } else if (C.IndexResult) {
   S.Signature = std::string(C.IndexResult->Signature);
   S.SnippetSuffix = std::string(C.IndexResult->CompletionSnippetSuffix);
@@ -570,11 +575,57 @@
 retur

[PATCH] D136925: [clangd] Index scoped enums for code completion

2022-10-31 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 472101.
tom-anders marked 3 inline comments as done.
tom-anders added a comment.
Herald added a subscriber: wenlei.

Add test to CodeCompletionTests, only consider unscoped enums in this patch 
(move scoped enums to separate patch)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136925

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.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
@@ -27,6 +27,8 @@
 Symbol cls(llvm::StringRef Name);
 // Creates an enum symbol.
 Symbol enm(llvm::StringRef Name);
+// Creates an enum constant symbol.
+Symbol enmConstant(llvm::StringRef Name);
 // Creates a variable symbol.
 Symbol var(llvm::StringRef Name);
 // Creates a namespace symbol.
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -69,6 +69,10 @@
   return sym(Name, index::SymbolKind::Enum, "@E@\\0");
 }
 
+Symbol enmConstant(llvm::StringRef Name) {
+  return sym(Name, index::SymbolKind::EnumConstant, "@\\0");
+}
+
 Symbol var(llvm::StringRef Name) {
   return sym(Name, index::SymbolKind::Variable, "@\\0");
 }
Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1316,6 +1316,11 @@
   Black
 };
 }
+class Color3 {
+  enum {
+Blue
+  };
+};
   )";
   runSymbolCollector(Header, /*Main=*/"");
   EXPECT_THAT(Symbols,
@@ -1325,6 +1330,8 @@
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
   AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color3"), forCodeCompletion(true)),
+  AllOf(qName("Color3::Blue"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
   AllOf(qName("ns::Black"), forCodeCompletion(true;
 }
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1,4 +1,5 @@
-//===-- CodeCompleteTests.cpp ---*- C++ -*-===//
+//===-- CodeCompleteTests.cpp ---*- C++
+//-*-===//codecom
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -2962,14 +2963,20 @@
 }
   )cpp",
   {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
-   cls("na::nb::Clangd4")},
+   cls("na::nb::Clangd4"), enmConstant("na::C::Clangd5")},
   Opts);
   EXPECT_THAT(
   Results.Completions,
-  UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1")),
-   AllOf(qualifier("ny::"), named("Clangd2")),
-   AllOf(qualifier(""), scope(""), named("Clangd3")),
-   AllOf(qualifier("nb::"), named("Clangd4";
+  UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("ny::"), named("Clangd2"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier(""), scope(""), named("Clangd3"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("nb::"), named("Clangd4"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("C::"), named("Clangd5"),
+ kind(CompletionItemKind::EnumMember;
 }
 
 TEST(CompletionTest, NoQualifierIfShadowed) {
Index: clang-tools-extra/clangd/index/Serialization.cpp
===
--- clang-tools-extra/clangd/index/Serialization.cpp
+++ clang-tools-extra/clangd/index/Serialization.cpp
@@ -455,7 +455,7 @@
 // The current versioni

[PATCH] D137104: [clangd] Add scoped enum constants to all-scopes-completion

2022-10-31 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added a reviewer: nridge.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

This was originally part of https://reviews.llvm.org/D136925, but we decided to 
move it to a separate patch.
In case it turns out to be controversial, it can be reverted more easily.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D137104

Files:
  clang-tools-extra/clangd/CodeComplete.h
  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
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
   AllOf(qName("Color3::Blue"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -291,7 +291,7 @@
 // For index-based completion, we only consider:
 //   * symbols in namespaces or translation unit scopes (e.g. no class
 // members, no locals)
-//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * enum constants (both scoped and unscoped)
 //   * primary templates (no specializations)
 // For the other cases, we let Clang do the completion because it does not
 // need any non-local information and it will be much better at following


Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
   AllOf(qName("Color3::Blue"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -291,7 +291,7 @@
 // For index-based completion, we only consider:
 //   * symbols in namespaces or translation unit scopes (e.g. no class
 // members, no locals)
-//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * enum constants (both scoped and unscoped)
 //   * primary templates (no specializations)
 // For the other cases, we let Clang do the completion because it does not
 // need any non-local information and it will be much better at following
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D137104: [clangd] Add scoped enum constants to all-scopes-completion

2022-10-31 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 472103.
tom-anders added a comment.

Added missing hunk in CodeComplete.cpp


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137104

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  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
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
   AllOf(qName("Color3::Blue"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -291,7 +291,7 @@
 // For index-based completion, we only consider:
 //   * symbols in namespaces or translation unit scopes (e.g. no class
 // members, no locals)
-//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * enum constants (both scoped and unscoped)
 //   * primary templates (no specializations)
 // For the other cases, we let Clang do the completion because it does not
 // need any non-local information and it will be much better at following
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -2114,9 +2114,6 @@
 };
 return false;
   };
-  auto InClassScope = [](const NamedDecl &ND) {
-return ND.getDeclContext()->getDeclKind() == Decl::CXXRecord;
-  };
   // We only complete symbol's name, which is the same as the name of the
   // *primary* template in case of template specializations.
   if (isExplicitTemplateSpecialization(&ND))
@@ -2135,8 +2132,8 @@
   // Always index enum constants, even if they're not in the top level scope:
   // when
   // --all-scopes-completion is set, we'll want to complete those as well.
-  if (const auto *EnumDecl = dyn_cast(ND.getDeclContext()))
-return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl)) && 
!EnumDecl->isScoped();
+  if (llvm::isa(ND.getDeclContext()))
+return true;
 
   return false;
 }


Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
   AllOf(qName("Color3::Blue"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -291,7 +291,7 @@
 // For index-based completion, we only consider:
 //   * symbols in namespaces or translation unit scopes (e.g. no class
 // members, no locals)
-//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * enum constants (both scoped and unscoped)
 //   * primary templates (no specializations)
 // For the other cases, we let Clang do the completion because it does not
 // need any non-local information and it will be much better at following
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -2114,9 +2114,6 @@
 };
 return false;
   };
-  auto InClassScope = [](const NamedDecl &ND) {
-return ND.getDeclContext()->getDeclKind() == Decl::CXXRecord;
-  };
   // We only complete symbol's name, which is the same as the name of the
   // *primary* template in case of template

[PATCH] D131853: [clangd] Add doxygen parsing for Hover

2022-08-14 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: wenlei, usaxena95, kadircet, arphaman, mgorny.
Herald added a project: All.
tom-anders published this revision for review.
Herald added subscribers: cfe-commits, llvm-commits, MaskRay, ilya-biryukov.
Herald added projects: LLVM, clang-tools-extra.

This adds a new class SymbolDocumentation that does basic doxygen
parsing. Currently, it's only consumed by Hover, but in future
patches we'll probably also want to use it in CodeComplete and
SignatureHelp.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131853

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeCompletionStrings.cpp
  clang-tools-extra/clangd/CodeCompletionStrings.h
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/Hover.h
  clang-tools-extra/clangd/SymbolDocumentation.cpp
  clang-tools-extra/clangd/SymbolDocumentation.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/YAMLSerialization.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp
  clang-tools-extra/clangd/unittests/IndexTests.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
  clang-tools-extra/clangd/unittests/SymbolDocumentationMatchers.h
  llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn

Index: llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
===
--- llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
+++ llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
@@ -117,6 +117,7 @@
 "SemanticHighlighting.cpp",
 "SemanticSelection.cpp",
 "SourceCode.cpp",
+"SymbolDocumentation.cpp"
 "TUScheduler.cpp",
 "TidyProvider.cpp",
 "URI.cpp",
Index: clang-tools-extra/clangd/unittests/SymbolDocumentationMatchers.h
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/SymbolDocumentationMatchers.h
@@ -0,0 +1,51 @@
+//===-- SymbolDocumentationMatchers.h ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// GMock matchers for the SymbolDocumentation class
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SYMBOLDOCUMENTATION_MATCHERS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SYMBOLDOCUMENTATION_MATCHERS_H
+#include "SymbolDocumentation.h"
+#include "gmock/gmock.h"
+
+namespace clang {
+namespace clangd {
+
+template 
+testing::Matcher>
+matchesDoc(const SymbolDocumentation &Expected) {
+  using namespace ::testing;
+
+  std::vector>> ParamMatchers;
+  for (const auto &P : Expected.Parameters)
+ParamMatchers.push_back(
+AllOf(Field("Name", &ParameterDocumentation::Name, P.Name),
+  Field("Description", &ParameterDocumentation::Description,
+P.Description)));
+
+  return AllOf(
+  Field("Brief", &SymbolDocumentation::Brief, Expected.Brief),
+  Field("Returns", &SymbolDocumentation::Returns, Expected.Returns),
+  Field("Notes", &SymbolDocumentation::Notes,
+ElementsAreArray(Expected.Notes)),
+  Field("Warnings", &SymbolDocumentation::Warnings,
+ElementsAreArray(Expected.Warnings)),
+  Field("Parameters", &SymbolDocumentation::Parameters,
+ElementsAreArray(ParamMatchers)),
+  Field("Description", &SymbolDocumentation::Description,
+Expected.Description),
+  Field("CommentText", &SymbolDocumentation::CommentText,
+Expected.CommentText));
+}
+
+} // namespace clangd
+} // namespace clang
+
+#endif
Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -50,7 +50,7 @@
   return (arg.Name + arg.Signature).str() == Label;
 }
 MATCHER_P(returnType, D, "") { return arg.ReturnType == D; }
-MATCHER_P(doc, D, "") { return arg.Documentation == D; }
+MATCHER_P(doc, D, "") { return arg.Documentation.CommentText == D; }
 MATCHER_P(snippet, S, "") {
   return (arg.Nam

[PATCH] D131853: [clangd] Add doxygen parsing for Hover

2022-08-22 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added reviewers: sammccall, nridge.
tom-anders added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131853

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


[PATCH] D131853: [clangd] Add doxygen parsing for Hover

2022-09-16 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

In D131853#3793831 , @nridge wrote:

> In D131853#3792985 , @logankaser 
> wrote:
>
>> Is there anything I can do as a random member of the public that wants this 
>> and knows C++?
>
> Maybe apply the patch locally, use it for a bit, and provide feedback?

I'm sure that would help!

> I haven't forgotten about this review and I hope to get to it as time permits.

Would it maybe also help to split this patch into 2 or 3 smaller patches?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131853

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


[PATCH] D134130: [clangd] Add doxygen parsing for Hover [1/3]

2022-09-18 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders added reviewers: nridge, sammccall, kadircet.
tom-anders published this revision for review.
Herald added subscribers: cfe-commits, llvm-commits, MaskRay, ilya-biryukov.
Herald added projects: LLVM, clang-tools-extra.

1/3: Add SymbolDocumentation class to parse Doxygen comments

This commit just adds and tests the a new class for doxygen parsing.
Consumption in Hover and Index will be added in a follow-up commit.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134130

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/SymbolDocumentation.cpp
  clang-tools-extra/clangd/SymbolDocumentation.h
  clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
  clang-tools-extra/clangd/unittests/SymbolDocumentationMatchers.h
  llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn

Index: llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
===
--- llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
+++ llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
@@ -117,6 +117,7 @@
 "SemanticHighlighting.cpp",
 "SemanticSelection.cpp",
 "SourceCode.cpp",
+"SymbolDocumentation.cpp"
 "TUScheduler.cpp",
 "TidyProvider.cpp",
 "URI.cpp",
Index: clang-tools-extra/clangd/unittests/SymbolDocumentationMatchers.h
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/SymbolDocumentationMatchers.h
@@ -0,0 +1,51 @@
+//===-- SymbolDocumentationMatchers.h ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// GMock matchers for the SymbolDocumentation class
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SYMBOLDOCUMENTATION_MATCHERS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SYMBOLDOCUMENTATION_MATCHERS_H
+#include "SymbolDocumentation.h"
+#include "gmock/gmock.h"
+
+namespace clang {
+namespace clangd {
+
+template 
+testing::Matcher>
+matchesDoc(const SymbolDocumentation &Expected) {
+  using namespace ::testing;
+
+  std::vector>> ParamMatchers;
+  for (const auto &P : Expected.Parameters)
+ParamMatchers.push_back(
+AllOf(Field("Name", &ParameterDocumentation::Name, P.Name),
+  Field("Description", &ParameterDocumentation::Description,
+P.Description)));
+
+  return AllOf(
+  Field("Brief", &SymbolDocumentation::Brief, Expected.Brief),
+  Field("Returns", &SymbolDocumentation::Returns, Expected.Returns),
+  Field("Notes", &SymbolDocumentation::Notes,
+ElementsAreArray(Expected.Notes)),
+  Field("Warnings", &SymbolDocumentation::Warnings,
+ElementsAreArray(Expected.Warnings)),
+  Field("Parameters", &SymbolDocumentation::Parameters,
+ElementsAreArray(ParamMatchers)),
+  Field("Description", &SymbolDocumentation::Description,
+Expected.Description),
+  Field("CommentText", &SymbolDocumentation::CommentText,
+Expected.CommentText));
+}
+
+} // namespace clangd
+} // namespace clang
+
+#endif
Index: clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
@@ -7,6 +7,7 @@
 //===--===//
 
 #include "CodeCompletionStrings.h"
+#include "SymbolDocumentationMatchers.h"
 #include "TestTU.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "gmock/gmock.h"
@@ -65,6 +66,90 @@
 getDeclComment(AST.getASTContext(), findDecl(AST, "X")));
 }
 
+TEST_F(CompletionStringTest, DoxygenParsing) {
+  struct {
+const char *const Code;
+const std::function ExpectedBuilder;
+  } Cases[] = {
+  {R"cpp(
+// Hello world
+void foo();
+)cpp",
+   [](SymbolDocumentationOwned &Doc) { Doc.Description = "Hello world"; }},
+  {R"cpp(
+/*! 
+ * \brief brief
+ * \details details
+ */
+void foo();
+)cpp",
+   [](SymbolDocumentationOwned &Doc) {
+ Doc.Brief = "brief";
+ Doc.Description = "\\details details";
+   }},
+  {R"cpp(
+/** 
+ * @brief brief
+ * @details details
+ * @see somewhere else
+ */
+void foo();
+)cpp",
+   [](SymbolDocumentationOwned &Doc) {
+ Doc.Brief = "brief";
+ Doc.Description = "@details detail

[PATCH] D134131: [clangd] Use doxygen parsing for Hover [2/3]

2022-09-18 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders added reviewers: nridge, sammccall, kadircet.
tom-anders published this revision for review.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Only for AST-based results, storage in the index is implemented in [3/3]


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134131

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeCompletionStrings.cpp
  clang-tools-extra/clangd/CodeCompletionStrings.h
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/Hover.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp

Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -10,6 +10,7 @@
 #include "Annotations.h"
 #include "Config.h"
 #include "Hover.h"
+#include "SymbolDocumentationMatchers.h"
 #include "TestIndex.h"
 #include "TestTU.h"
 #include "index/MemIndex.h"
@@ -43,7 +44,8 @@
  HI.NamespaceScope = "";
  HI.Name = "foo";
  HI.Kind = index::SymbolKind::Function;
- HI.Documentation = "Best foo ever.";
+ HI.Documentation =
+ SymbolDocumentationOwned::descriptionOnly("Best foo ever.");
  HI.Definition = "void foo()";
  HI.ReturnType = "void";
  HI.Type = "void ()";
@@ -60,7 +62,8 @@
  HI.NamespaceScope = "ns1::ns2::";
  HI.Name = "foo";
  HI.Kind = index::SymbolKind::Function;
- HI.Documentation = "Best foo ever.";
+ HI.Documentation =
+ SymbolDocumentationOwned::descriptionOnly("Best foo ever.");
  HI.Definition = "void foo()";
  HI.ReturnType = "void";
  HI.Type = "void ()";
@@ -148,8 +151,8 @@
[](HoverInfo &HI) {
  HI.Name = "__func__";
  HI.Kind = index::SymbolKind::Variable;
- HI.Documentation =
- "Name of the current function (predefined variable)";
+ HI.Documentation = SymbolDocumentationOwned::descriptionOnly(
+ "Name of the current function (predefined variable)");
  HI.Value = "\"foo\"";
  HI.Type = "const char[4]";
}},
@@ -162,8 +165,8 @@
[](HoverInfo &HI) {
  HI.Name = "__func__";
  HI.Kind = index::SymbolKind::Variable;
- HI.Documentation =
- "Name of the current function (predefined variable)";
+ HI.Documentation = SymbolDocumentationOwned::descriptionOnly(
+ "Name of the current function (predefined variable)");
  HI.Type = "const char[]";
}},
   // Anon namespace and local scope.
@@ -741,7 +744,8 @@
  HI.Definition = "template <> class Foo";
  // FIXME: Maybe force instantiation to make use of real template
  // pattern.
- HI.Documentation = "comment from primary";
+ HI.Documentation =
+ SymbolDocumentationOwned::descriptionOnly("comment from primary");
}},
   {// Template Type Parameter
R"cpp(
@@ -793,7 +797,8 @@
  HI.NamespaceScope = "";
  HI.Definition = "float y()";
  HI.LocalScope = "X::";
- HI.Documentation = "Trivial accessor for `Y`.";
+ HI.Documentation = SymbolDocumentationOwned::descriptionOnly(
+ "Trivial accessor for `Y`.");
  HI.Type = "float ()";
  HI.ReturnType = "float";
  HI.Parameters.emplace();
@@ -809,7 +814,8 @@
  HI.NamespaceScope = "";
  HI.Definition = "void setY(float v)";
  HI.LocalScope = "X::";
- HI.Documentation = "Trivial setter for `Y`.";
+ HI.Documentation = SymbolDocumentationOwned::descriptionOnly(
+ "Trivial setter for `Y`.");
  HI.Type = "void (float)";
  HI.ReturnType = "void";
  HI.Parameters.emplace();
@@ -828,7 +834,8 @@
  HI.NamespaceScope = "";
  HI.Definition = "X &setY(float v)";
  HI.LocalScope = "X::";
- HI.Documentation = "Trivial setter for `Y`.";
+ HI.Documentation = SymbolDocumentationOwned::descriptionOnly(
+ "Trivial setter for `Y`.");
  HI.Type = "X &(float)";
  HI.ReturnType = "X &";
  HI.Parameters.emplace();
@@ -848,7 +855,8 @@
  HI.NamespaceScope = "";
  HI.Definition = "void setY(float v)";
  HI.LocalScope = "X::";
- HI.Documentation = "Trivial setter for `Y`.";
+ HI.Documentation = SymbolDocumentationOwned::descriptionOnly(
+ "Trivial setter for `Y`.");
  HI.Type = "void (float)";
  HI.ReturnType = "void";
  HI.Parameters.empl

[PATCH] D134132: [clangd] Add doxygen parsing for Hover [3/3]

2022-09-18 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: wenlei, kadircet, arphaman.
Herald added a project: All.
tom-anders added reviewers: nridge, sammccall, kadircet.
tom-anders published this revision for review.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

This stores SymbolDocumentation in the index and uses it in Hover.
CodeCompletion and SignatureHelp still use the unparsed comment for now.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134132

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/Hover.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/YAMLSerialization.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.cpp
  clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/HoverTests.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
@@ -50,7 +50,7 @@
   return (arg.Name + arg.Signature).str() == Label;
 }
 MATCHER_P(returnType, D, "") { return arg.ReturnType == D; }
-MATCHER_P(doc, D, "") { return arg.Documentation == D; }
+MATCHER_P(doc, D, "") { return arg.Documentation.CommentText == D; }
 MATCHER_P(snippet, S, "") {
   return (arg.Name + arg.CompletionSnippetSuffix).str() == S;
 }
Index: clang-tools-extra/clangd/unittests/SerializationTests.cpp
===
--- clang-tools-extra/clangd/unittests/SerializationTests.cpp
+++ clang-tools-extra/clangd/unittests/SerializationTests.cpp
@@ -8,6 +8,7 @@
 
 #include "Headers.h"
 #include "RIFF.h"
+#include "SymbolDocumentationMatchers.h"
 #include "index/Serialization.h"
 #include "support/Logger.h"
 #include "clang/Tooling/CompilationDatabase.h"
@@ -48,7 +49,22 @@
 Line: 1
 Column: 1
 Flags:129
-Documentation:'Foo doc'
+Documentation:
+  Brief:   'Foo brief'
+  Returns: 'Foo returns'
+  Description: 'Foo description'
+  Notes:
+- 'Foo note 1'
+- 'Foo note 2'
+  Warnings:
+- 'Foo warning 1'
+- 'Foo warning 2'
+  Parameters:
+- Name: 'param1'
+  Description: 'Foo param 1'
+- Name: 'param2'
+  Description: 'Foo param 2'
+  CommentText: 'Full text would be here'
 ReturnType:'int'
 IncludeHeaders:
   - Header:'include1'
@@ -141,7 +157,20 @@
 
   EXPECT_THAT(Sym1, qName("clang::Foo1"));
   EXPECT_EQ(Sym1.Signature, "");
-  EXPECT_EQ(Sym1.Documentation, "Foo doc");
+
+  SymbolDocumentationRef ExpectedDocumentation;
+  ExpectedDocumentation.Brief = "Foo brief";
+  ExpectedDocumentation.Returns = "Foo returns";
+  ExpectedDocumentation.Description = "Foo description";
+  ExpectedDocumentation.Notes = {"Foo note 1", "Foo note 2"};
+  ExpectedDocumentation.Warnings = {"Foo warning 1", "Foo warning 2"};
+  ExpectedDocumentation.Parameters = {
+  {"param1", "Foo param 1"},
+  {"param2", "Foo param 2"},
+  };
+  ExpectedDocumentation.CommentText = "Full text would be here";
+  EXPECT_THAT(Sym1.Documentation, matchesDoc(ExpectedDocumentation));
+
   EXPECT_EQ(Sym1.ReturnType, "int");
   EXPECT_EQ(StringRef(Sym1.CanonicalDeclaration.FileURI), "file:///path/foo.h");
   EXPECT_EQ(Sym1.Origin, SymbolOrigin::Static);
Index: clang-tools-extra/clangd/unittests/IndexTests.cpp
===
--- clang-tools-extra/clangd/unittests/IndexTests.cpp
+++ clang-tools-extra/clangd/unittests/IndexTests.cpp
@@ -7,6 +7,7 @@
 //===--===//
 
 #include "Annotations.h"
+#include "SymbolDocumentationMatchers.h"
 #include "SyncAPI.h"
 #include "TestIndex.h"
 #include "TestTU.h"
@@ -391,7 +392,7 @@
   R.References = 2;
   L.Signature = "()";   // present in left only
   R.CompletionSnippetSuffix = "{$1:0}"; // present in right only
-  R.Documentation = "--doc--";
+  R.Documentation = SymbolDocumentationRef::descriptionOnly("--doc--");
   L.Origin = SymbolOrigin::Preamble;
   R.Origin = SymbolOrigin::Static;
   R.Type = "expectedType";
@@ -402,7 +403,8 @@
   EXPECT_EQ(M.References, 3u);
   EXPECT_EQ(M.Signature, "()");
   EXPECT_EQ(M.CompletionSnippetSuffix, "{$1:0}");
-  EXPECT_EQ(M.Documentation, "--doc--");
+  EXPECT_THAT(M.Documentation,
+  matchesDoc(SymbolDocumentationRef::descriptionOnly("--doc--")));
   EXPECT_EQ(M.Type

[PATCH] D131853: [clangd] Add doxygen parsing for Hover

2022-09-18 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders abandoned this revision.
tom-anders added a comment.

Split up into 3 smaller patches: https://reviews.llvm.org/D134130, 
https://reviews.llvm.org/D134131 and https://reviews.llvm.org/D134132


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131853

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


[PATCH] D134137: [clangd] Return earlier when snippet is empty

2022-09-18 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Fixes github.com/clangd/clangd/issues/1216

If the Snippet string is empty, Snippet.front() would trigger a crash.
Move the Snippet->empty() check up a few lines to avoid this. Should not
break any existing behavior.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134137

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
@@ -1014,6 +1014,23 @@
   EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::";
 }
 
+TEST(CompletionTests, EmptySnippetDoesNotCrash) {
+// See https://github.com/clangd/clangd/issues/1216
+auto Results = completions(R"cpp(
+int main() {
+  auto w = [&](auto &&f) { return f(f); };
+  auto f = w([&](auto &&f) {
+return [&](auto &&n) {
+  if (n == 0) {
+return 1;
+  }
+  return n * ^(f)(n - 1);
+};
+  })(10);
+}
+)cpp");
+}
+
 TEST(CompletionTest, BacktrackCrashes) {
   // Sema calls code completion callbacks twice in these cases.
   auto Results = completions(R"cpp(
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -491,6 +491,9 @@
   // we need to complete 'forward<$1>($0)'.
   return "($0)";
 
+if (Snippet->empty())
+  return "";
+
 bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function ||
   Completion.Kind == CompletionItemKind::Method ||
   Completion.Kind == CompletionItemKind::Constructor ||
@@ -529,8 +532,6 @@
   return *Snippet;
 
 // Replace argument snippets with a simplified pattern.
-if (Snippet->empty())
-  return "";
 if (MayHaveArgList) {
   // Functions snippets can be of 2 types:
   // - containing only function arguments, e.g.


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1014,6 +1014,23 @@
   EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::";
 }
 
+TEST(CompletionTests, EmptySnippetDoesNotCrash) {
+// See https://github.com/clangd/clangd/issues/1216
+auto Results = completions(R"cpp(
+int main() {
+  auto w = [&](auto &&f) { return f(f); };
+  auto f = w([&](auto &&f) {
+return [&](auto &&n) {
+  if (n == 0) {
+return 1;
+  }
+  return n * ^(f)(n - 1);
+};
+  })(10);
+}
+)cpp");
+}
+
 TEST(CompletionTest, BacktrackCrashes) {
   // Sema calls code completion callbacks twice in these cases.
   auto Results = completions(R"cpp(
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -491,6 +491,9 @@
   // we need to complete 'forward<$1>($0)'.
   return "($0)";
 
+if (Snippet->empty())
+  return "";
+
 bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function ||
   Completion.Kind == CompletionItemKind::Method ||
   Completion.Kind == CompletionItemKind::Constructor ||
@@ -529,8 +532,6 @@
   return *Snippet;
 
 // Replace argument snippets with a simplified pattern.
-if (Snippet->empty())
-  return "";
 if (MayHaveArgList) {
   // Functions snippets can be of 2 types:
   // - containing only function arguments, e.g.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D134137: [clangd] Return earlier when snippet is empty

2022-09-19 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders marked an inline comment as done.
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp:1017
 
+TEST(CompletionTests, EmptySnippetDoesNotCrash) {
+// See https://github.com/clangd/clangd/issues/1216

nridge wrote:
> Does this test trigger the crash for you when run without the fix?
Yes it does, I double checked. Not sure why it didn't work for you


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134137

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


[PATCH] D134137: [clangd] Return earlier when snippet is empty

2022-09-19 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders marked an inline comment as done.
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp:1017
 
+TEST(CompletionTests, EmptySnippetDoesNotCrash) {
+// See https://github.com/clangd/clangd/issues/1216

kadircet wrote:
> tom-anders wrote:
> > nridge wrote:
> > > Does this test trigger the crash for you when run without the fix?
> > Yes it does, I double checked. Not sure why it didn't work for you
> it doesn't trigger the crash for me either.
Huh, maybe this is a b



Comment at: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp:1017
 
+TEST(CompletionTests, EmptySnippetDoesNotCrash) {
+// See https://github.com/clangd/clangd/issues/1216

tom-anders wrote:
> kadircet wrote:
> > tom-anders wrote:
> > > nridge wrote:
> > > > Does this test trigger the crash for you when run without the fix?
> > > Yes it does, I double checked. Not sure why it didn't work for you
> > it doesn't trigger the crash for me either.
> Huh, maybe this is a b
Hmm could be a build type thing? I ran the tests for a Debug build, maybe it's 
different in Release?

Maybe we could also ask the author of the GitHub issue to check if it fixes the 
crash for them?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134137

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


[PATCH] D134137: [clangd] Return earlier when snippet is empty

2022-09-20 Thread Tom Praschan 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 rG60528c690a4c: [clangd] Return earlier when snippet is empty 
(authored by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134137

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
@@ -1014,6 +1014,23 @@
   EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::";
 }
 
+TEST(CompletionTests, EmptySnippetDoesNotCrash) {
+// See https://github.com/clangd/clangd/issues/1216
+auto Results = completions(R"cpp(
+int main() {
+  auto w = [&](auto &&f) { return f(f); };
+  auto f = w([&](auto &&f) {
+return [&](auto &&n) {
+  if (n == 0) {
+return 1;
+  }
+  return n * ^(f)(n - 1);
+};
+  })(10);
+}
+)cpp");
+}
+
 TEST(CompletionTest, BacktrackCrashes) {
   // Sema calls code completion callbacks twice in these cases.
   auto Results = completions(R"cpp(
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -491,6 +491,9 @@
   // we need to complete 'forward<$1>($0)'.
   return "($0)";
 
+if (Snippet->empty())
+  return "";
+
 bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function ||
   Completion.Kind == CompletionItemKind::Method ||
   Completion.Kind == CompletionItemKind::Constructor ||
@@ -529,8 +532,6 @@
   return *Snippet;
 
 // Replace argument snippets with a simplified pattern.
-if (Snippet->empty())
-  return "";
 if (MayHaveArgList) {
   // Functions snippets can be of 2 types:
   // - containing only function arguments, e.g.


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1014,6 +1014,23 @@
   EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::";
 }
 
+TEST(CompletionTests, EmptySnippetDoesNotCrash) {
+// See https://github.com/clangd/clangd/issues/1216
+auto Results = completions(R"cpp(
+int main() {
+  auto w = [&](auto &&f) { return f(f); };
+  auto f = w([&](auto &&f) {
+return [&](auto &&n) {
+  if (n == 0) {
+return 1;
+  }
+  return n * ^(f)(n - 1);
+};
+  })(10);
+}
+)cpp");
+}
+
 TEST(CompletionTest, BacktrackCrashes) {
   // Sema calls code completion callbacks twice in these cases.
   auto Results = completions(R"cpp(
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -491,6 +491,9 @@
   // we need to complete 'forward<$1>($0)'.
   return "($0)";
 
+if (Snippet->empty())
+  return "";
+
 bool MayHaveArgList = Completion.Kind == CompletionItemKind::Function ||
   Completion.Kind == CompletionItemKind::Method ||
   Completion.Kind == CompletionItemKind::Constructor ||
@@ -529,8 +532,6 @@
   return *Snippet;
 
 // Replace argument snippets with a simplified pattern.
-if (Snippet->empty())
-  return "";
 if (MayHaveArgList) {
   // Functions snippets can be of 2 types:
   // - containing only function arguments, e.g.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D134137: [clangd] Return earlier when snippet is empty

2022-09-20 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp:1017
 
+TEST(CompletionTests, EmptySnippetDoesNotCrash) {
+// See https://github.com/clangd/clangd/issues/1216

nridge wrote:
> tom-anders wrote:
> > tom-anders wrote:
> > > kadircet wrote:
> > > > tom-anders wrote:
> > > > > nridge wrote:
> > > > > > Does this test trigger the crash for you when run without the fix?
> > > > > Yes it does, I double checked. Not sure why it didn't work for you
> > > > it doesn't trigger the crash for me either.
> > > Huh, maybe this is a b
> > Hmm could be a build type thing? I ran the tests for a Debug build, maybe 
> > it's different in Release?
> > 
> > Maybe we could also ask the author of the GitHub issue to check if it fixes 
> > the crash for them?
> Ok, I verified that the test case does produce completion proposals with 
> empty snippets, i.e. it does trigger the problematic code path, it just 
> happens not to crash for me. I think that's fine.
> 
> Thank you for tracking this down and fixing!
np, thanks for the review :)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134137

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


[PATCH] D135489: [clangd] Fix rename for symbol introduced by UsingDecl

2022-10-07 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Fixes https://github.com/clangd/clangd/issues/170

This patch actually consists of 2 fixes:

1. Add handling for UsingShadowDecl to canonicalRenameDecl(). This fixes the 
issue described in https://github.com/clangd/clangd/issues/170.

2. Avoid the "there are multiple symbols under the cursor error" by applying 
similar logic as in https://reviews.llvm.org/D133664. This also partly fixes 
https://github.com/clangd/clangd/issues/586.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135489

Files:
  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
@@ -817,6 +817,18 @@
   char [[da^ta]];
 } @end
   )cpp",
+
+  // Issue 170: Rename symbol introduced by UsingDecl
+  R"cpp(
+namespace ns { void [[f^oo]](); } 
+
+using ns::[[f^oo]];
+
+void f() {
+[[f^oo]]();
+auto p = &[[f^oo]];
+}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -133,6 +133,10 @@
 if (const VarDecl *OriginalVD = VD->getInstantiatedFromStaticDataMember())
   return canonicalRenameDecl(OriginalVD);
   }
+  if (const auto *UD = dyn_cast(D)) {
+if (const auto* TargetDecl = UD->getTargetDecl()) 
+  return canonicalRenameDecl(TargetDecl);
+  }
   return dyn_cast(D->getCanonicalDecl());
 }
 
@@ -157,6 +161,23 @@
   return Result;
 }
 
+// For something like 
+// namespace ns { void foo(); }
+// void bar() { using ns::foo; f^oo(); }
+// locateDeclAt() will return a BaseUsingDecl and foo's actual declaration.
+// For renaming, we're only interested in foo's declaration, so drop the other 
one
+void filterBaseUsingDecl(llvm::DenseSet& Decls) {
+  if (Decls.size() == 2) {
+auto FirstDecl = Decls.begin();
+auto SecondDecl = std::next(Decls.begin());
+
+if (llvm::isa(*FirstDecl)) 
+  Decls.erase(FirstDecl);
+else if (llvm::isa(*SecondDecl)) 
+  Decls.erase(SecondDecl);
+  }
+}
+
 // By default, we exclude symbols from system headers and protobuf symbols as
 // renaming these symbols would change system/generated files which are 
unlikely
 // to be good candidates for modification.
@@ -737,6 +758,7 @@
 return makeError(ReasonToReject::UnsupportedSymbol);
 
   auto DeclsUnderCursor = locateDeclAt(AST, IdentifierToken->location());
+  filterBaseUsingDecl(DeclsUnderCursor);
   if (DeclsUnderCursor.empty())
 return makeError(ReasonToReject::NoSymbolFound);
   if (DeclsUnderCursor.size() > 1)


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -817,6 +817,18 @@
   char [[da^ta]];
 } @end
   )cpp",
+
+  // Issue 170: Rename symbol introduced by UsingDecl
+  R"cpp(
+namespace ns { void [[f^oo]](); } 
+
+using ns::[[f^oo]];
+
+void f() {
+[[f^oo]]();
+auto p = &[[f^oo]];
+}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -133,6 +133,10 @@
 if (const VarDecl *OriginalVD = VD->getInstantiatedFromStaticDataMember())
   return canonicalRenameDecl(OriginalVD);
   }
+  if (const auto *UD = dyn_cast(D)) {
+if (const auto* TargetDecl = UD->getTargetDecl()) 
+  return canonicalRenameDecl(TargetDecl);
+  }
   return dyn_cast(D->getCanonicalDecl());
 }
 
@@ -157,6 +161,23 @@
   return Result;
 }
 
+// For something like 
+// namespace ns { void foo(); }
+// void bar() { using ns::foo; f^oo(); }
+// locateDeclAt() will return a BaseUsingDecl and foo's actual declaration.
+// For renaming, we're only interested in foo's declaration, so drop the other one
+void filterBaseUsingDecl(llvm::DenseSet& Decls) {
+  if (Decls.size() == 2) {
+auto FirstDecl = Decls.begin();
+auto SecondDecl = std::next(Decls.begin());
+
+if (llvm::isa

[PATCH] D135489: [clangd] Fix rename for symbol introduced by UsingDecl

2022-10-07 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:169
+// For renaming, we're only interested in foo's declaration, so drop the other 
one
+void filterBaseUsingDecl(llvm::DenseSet& Decls) {
+  if (Decls.size() == 2) {

I'm not really happy with the name here, open for suggestions


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135489

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


[PATCH] D135506: [clangd] FindTarget: UsingEnumDecl is not an alias

2022-10-08 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders accepted this revision.
tom-anders added a comment.
This revision is now accepted and ready to land.

lgtm, thanks! With this change in place, we could probably ajdust 
`pickDeclToUse` in Hover.cpp (introduced in https://reviews.llvm.org/D133664) 
to also check for `UsingDecl` instead of `BaseUsingDecl`, right?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135506

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


[PATCH] D135489: [clangd] Fix rename for symbol introduced by UsingDecl

2022-10-08 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders marked 4 inline comments as done.
tom-anders added a comment.

In D135489#3844426 , @sammccall wrote:

>   namespace ns { int foo(int); char foo(char); }
>   using ns::foo;
>   int x = foo(42);
>   char y = foo('x');
>
> What should happen when we rename `foo(int)` on line 1?
>
> - rename both functions
> - rename one function + the usingdecl
> - rename one function and not the usingdecl
> - rename one function and add a second usingdecl
> - return an error
>
> In general the UsingDecl will be in another file and not visible in the AST. 
> Index only knows "there's a reference there". So I think our only real option 
> is to rename one function + the UsingDecl.
> (Assuming we want the common non-overloaded case to work. And assuming we 
> don't want to do something drastic like "silently rename overload sets 
> together in all cases").

Agreed.

> What should happen when we rename `using ns::foo` on line 2?
>
> - rename both functions
> - rename one arbitrarily
> - return an error
>
> Renaming both functions sounds great here. However for now the rename 
> implementation requires a single canonical decl, so we need to return an 
> error for now.
> If there's a single decl, renaming it seems fine.

Agreed, I added a FIXME in the test that we might want to extend 
canonicalRenameDecl to return multiple Decls (Probably a `llvm::DenseSet`?)
There already is a similar issue when renaming virtual methods with 
`size_overridden_methods() > 1`.

> What should happen when we rename `foo(42)` on line 3?
>
> - rename both functions
> - rename one function + the usingdecl
> - rename one function and not the usingdecl
> - rename one function and add a second usingdecl
> - return an error
>
> We *can* rely on the UsingDecl being visible here. However we should be 
> reasonably consistent with the first case, which I think rules out options 1, 
> 3 and 5.
> Splitting the usingdecl is a neat trick, but complicated, so let's start with 
> renaming one + functiondecl and maybe tack that on later.

Sounds good, splitting the using decl would be fancy though, maybe also add a 
FIXME for this?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135489

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


[PATCH] D135489: [clangd] Fix rename for symbol introduced by UsingDecl

2022-10-08 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 466292.
tom-anders added a comment.

Add additional tests, only handle UsingDecl instead of BaseUsingDecl


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135489

Files:
  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
@@ -817,6 +817,29 @@
   char [[da^ta]];
 } @end
   )cpp",
+
+  // Issue 170: Rename symbol introduced by UsingDecl
+  R"cpp(
+namespace ns { void [[f^oo]](); } 
+
+using ns::[[f^oo]];
+
+void f() {
+[[f^oo]]();
+auto p = &[[f^oo]];
+}
+  )cpp",
+
+  // Issue 170: using decl that imports multiple overloads
+  // -> Only the overload under the cursor is renamed
+  R"cpp(
+namespace ns { int [[^foo]](int); char foo(char); }
+using ns::[[foo]];
+void f() {
+  [[^foo]](42);
+  foo('x');
+}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1062,6 +1085,14 @@
 };
   )cpp",
"no symbol", false},
+
+  {R"cpp(// FIXME we probably want to rename both overloads here,
+ // but renaming currently assumes there's only a 
+ // single canonical declaration.
+namespace ns { int foo(int); char foo(char); }
+using ns::^foo;
+  )cpp",
+   "there are multiple symbols at the given location", !HeaderFile},
   };
 
   for (const auto& Case : Cases) {
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -133,6 +133,10 @@
 if (const VarDecl *OriginalVD = VD->getInstantiatedFromStaticDataMember())
   return canonicalRenameDecl(OriginalVD);
   }
+  if (const auto *UD = dyn_cast(D)) {
+if (const auto* TargetDecl = UD->getTargetDecl()) 
+  return canonicalRenameDecl(TargetDecl);
+  }
   return dyn_cast(D->getCanonicalDecl());
 }
 
@@ -157,6 +161,21 @@
   return Result;
 }
 
+// For something like 
+// namespace ns { void foo(); }
+// void bar() { using ns::f^oo; foo(); }
+// locateDeclAt() will return a UsingDecl and foo's actual declaration.
+// For renaming, we're only interested in foo's declaration, so drop the other 
one
+void filterUsingDecl(llvm::DenseSet& Decls) {
+  // There should never be more than one UsingDecl here, 
+  // otherwise the rename would be ambiguos anyway.
+  auto UD = std::find_if(Decls.begin(), Decls.end(), 
+ [](const NamedDecl* D) { return 
llvm::isa(D); });
+  if (UD != Decls.end()) {
+Decls.erase(UD);
+  }
+}
+
 // By default, we exclude symbols from system headers and protobuf symbols as
 // renaming these symbols would change system/generated files which are 
unlikely
 // to be good candidates for modification.
@@ -737,6 +756,7 @@
 return makeError(ReasonToReject::UnsupportedSymbol);
 
   auto DeclsUnderCursor = locateDeclAt(AST, IdentifierToken->location());
+  filterUsingDecl(DeclsUnderCursor);
   if (DeclsUnderCursor.empty())
 return makeError(ReasonToReject::NoSymbolFound);
   if (DeclsUnderCursor.size() > 1)


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -817,6 +817,29 @@
   char [[da^ta]];
 } @end
   )cpp",
+
+  // Issue 170: Rename symbol introduced by UsingDecl
+  R"cpp(
+namespace ns { void [[f^oo]](); } 
+
+using ns::[[f^oo]];
+
+void f() {
+[[f^oo]]();
+auto p = &[[f^oo]];
+}
+  )cpp",
+
+  // Issue 170: using decl that imports multiple overloads
+  // -> Only the overload under the cursor is renamed
+  R"cpp(
+namespace ns { int [[^foo]](int); char foo(char); }
+using ns::[[foo]];
+void f() {
+  [[^foo]](42);
+  foo('x');
+}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1062,6 +1085,14 @@
 };
   )cpp",
"no symbol", false},
+
+  {R"cpp(// FIXME we probably want to rename both overloads here,
+ // but renaming currently assumes there's only a 
+ // single canonical declaration.
+namespace ns { int foo(int); char foo(char); }
+using ns::^foo;
+  )cpp",
+   "there are multiple symbols at the given location", !HeaderFile},
   

[PATCH] D135489: [clangd] Fix rename for symbol introduced by UsingDecl

2022-10-09 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders marked 2 inline comments as done.
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/refactor/Rename.cpp:170
+void filterUsingDecl(llvm::DenseSet& Decls) {
+  // There should never be more than one UsingDecl here, 
+  // otherwise the rename would be ambiguos anyway.

sammccall wrote:
> nit: `llvm::erase_if(Decls, [](const NamedDecl *D) { ... })`?
Does not work unfortunately, `DenseSet` does not have the `erase(iterator 
first, iterator last)` overload, there's only `erase(iterator pos)`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135489

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


[PATCH] D135489: [clangd] Fix rename for symbol introduced by UsingDecl

2022-10-09 Thread Tom Praschan 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 rGac21938fbdfa: [clangd] Fix rename for symbol introduced by 
UsingDecl (authored by tom-anders).

Changed prior to commit:
  https://reviews.llvm.org/D135489?vs=466292&id=466360#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135489

Files:
  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
@@ -817,6 +817,29 @@
   char [[da^ta]];
 } @end
   )cpp",
+
+  // Issue 170: Rename symbol introduced by UsingDecl
+  R"cpp(
+namespace ns { void [[f^oo]](); } 
+
+using ns::[[f^oo]];
+
+void f() {
+[[f^oo]]();
+auto p = &[[f^oo]];
+}
+  )cpp",
+
+  // Issue 170: using decl that imports multiple overloads
+  // -> Only the overload under the cursor is renamed
+  R"cpp(
+namespace ns { int [[^foo]](int); char foo(char); }
+using ns::[[foo]];
+void f() {
+  [[^foo]](42);
+  foo('x');
+}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1062,6 +1085,14 @@
 };
   )cpp",
"no symbol", false},
+
+  {R"cpp(// FIXME we probably want to rename both overloads here,
+ // but renaming currently assumes there's only a 
+ // single canonical declaration.
+namespace ns { int foo(int); char foo(char); }
+using ns::^foo;
+  )cpp",
+   "there are multiple symbols at the given location", !HeaderFile},
   };
 
   for (const auto& Case : Cases) {
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -133,6 +133,10 @@
 if (const VarDecl *OriginalVD = VD->getInstantiatedFromStaticDataMember())
   return canonicalRenameDecl(OriginalVD);
   }
+  if (const auto *UD = dyn_cast(D)) {
+if (const auto *TargetDecl = UD->getTargetDecl())
+  return canonicalRenameDecl(TargetDecl);
+  }
   return dyn_cast(D->getCanonicalDecl());
 }
 
@@ -157,6 +161,22 @@
   return Result;
 }
 
+void filterRenameTargets(llvm::DenseSet &Decls) {
+  // For something like
+  // namespace ns { void foo(); }
+  // void bar() { using ns::f^oo; foo(); }
+  // locateDeclAt() will return a UsingDecl and foo's actual declaration.
+  // For renaming, we're only interested in foo's declaration, so drop the 
other
+  // one. There should never be more than one UsingDecl here, otherwise the
+  // rename would be ambiguos anyway.
+  auto UD = std::find_if(Decls.begin(), Decls.end(), [](const NamedDecl *D) {
+return llvm::isa(D);
+  });
+  if (UD != Decls.end()) {
+Decls.erase(UD);
+  }
+}
+
 // By default, we exclude symbols from system headers and protobuf symbols as
 // renaming these symbols would change system/generated files which are 
unlikely
 // to be good candidates for modification.
@@ -737,6 +757,7 @@
 return makeError(ReasonToReject::UnsupportedSymbol);
 
   auto DeclsUnderCursor = locateDeclAt(AST, IdentifierToken->location());
+  filterRenameTargets(DeclsUnderCursor);
   if (DeclsUnderCursor.empty())
 return makeError(ReasonToReject::NoSymbolFound);
   if (DeclsUnderCursor.size() > 1)


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -817,6 +817,29 @@
   char [[da^ta]];
 } @end
   )cpp",
+
+  // Issue 170: Rename symbol introduced by UsingDecl
+  R"cpp(
+namespace ns { void [[f^oo]](); } 
+
+using ns::[[f^oo]];
+
+void f() {
+[[f^oo]]();
+auto p = &[[f^oo]];
+}
+  )cpp",
+
+  // Issue 170: using decl that imports multiple overloads
+  // -> Only the overload under the cursor is renamed
+  R"cpp(
+namespace ns { int [[^foo]](int); char foo(char); }
+using ns::[[foo]];
+void f() {
+  [[^foo]](42);
+  foo('x');
+}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1062,6 +1085,14 @@
 };
   )cpp",
"no symbol", false},
+
+  {R"cpp(// FIXME we probably want to rename both overloads here,
+ // but renaming currently assumes there's only a 
+ // single canonical declara

[PATCH] D135536: [clangd] Hover: Only drop UsingDecl instead of BaseUsingDecl

2022-10-09 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added a reviewer: sammccall.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Since https://reviews.llvm.org/D135506 it's sufficient to only drop UsingDecl 
here


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135536

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


Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1017,7 +1017,7 @@
   // which isn't really useful for Hover. So use the other one,
   // which in this example would be the actual declaration of foo.
   if (Candidates.size() <= 2) {
-if (llvm::isa(Candidates.front()))
+if (llvm::isa(Candidates.front()))
   return Candidates.back();
 return Candidates.front();
   }
@@ -1029,7 +1029,7 @@
   // we actually want to show the using declaration,
   // it's not clear which declaration to pick otherwise.
   auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) {
-return llvm::isa(D);
+return llvm::isa(D);
   });
   if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1)
 return *BaseDecls.begin();


Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1017,7 +1017,7 @@
   // which isn't really useful for Hover. So use the other one,
   // which in this example would be the actual declaration of foo.
   if (Candidates.size() <= 2) {
-if (llvm::isa(Candidates.front()))
+if (llvm::isa(Candidates.front()))
   return Candidates.back();
 return Candidates.front();
   }
@@ -1029,7 +1029,7 @@
   // we actually want to show the using declaration,
   // it's not clear which declaration to pick otherwise.
   auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) {
-return llvm::isa(D);
+return llvm::isa(D);
   });
   if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1)
 return *BaseDecls.begin();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135542: [clangd] Rename: Allow multiple canonical declarations [1/3]

2022-10-09 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added a reviewer: sammccall.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders updated this revision to Diff 466391.
tom-anders added a comment.
tom-anders published this revision for review.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

clang-format


Note that locateDeclAt() now does *not* canonicalize the declaration anymore, 
since that would now lead to "AmbiguousSymbol" when there's a single 
declaration under the cursor that has multiple canonical declarations.
Instead, only canonicalize *after* checking how many decls we've found under 
the cursor.

This will allow renaming virtual methods with size_overridden_methods() > 1 in 
a follow-up commit.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135542

Files:
  clang-tools-extra/clangd/refactor/Rename.cpp

Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -82,35 +82,35 @@
 //
 // Here, both partial (2) and full (3) specializations are canonicalized to (1)
 // which ensures all three of them are renamed.
-const NamedDecl *canonicalRenameDecl(const NamedDecl *D) {
+llvm::DenseSet canonicalRenameDecls(const NamedDecl *D) {
   if (const auto *VarTemplate = dyn_cast(D))
-return canonicalRenameDecl(
+return canonicalRenameDecls(
 VarTemplate->getSpecializedTemplate()->getTemplatedDecl());
   if (const auto *Template = dyn_cast(D))
 if (const NamedDecl *TemplatedDecl = Template->getTemplatedDecl())
-  return canonicalRenameDecl(TemplatedDecl);
+  return canonicalRenameDecls(TemplatedDecl);
   if (const auto *ClassTemplateSpecialization =
   dyn_cast(D))
-return canonicalRenameDecl(
+return canonicalRenameDecls(
 ClassTemplateSpecialization->getSpecializedTemplate()
 ->getTemplatedDecl());
   if (const auto *Method = dyn_cast(D)) {
 if (Method->getDeclKind() == Decl::Kind::CXXConstructor ||
 Method->getDeclKind() == Decl::Kind::CXXDestructor)
-  return canonicalRenameDecl(Method->getParent());
+  return canonicalRenameDecls(Method->getParent());
 if (const FunctionDecl *InstantiatedMethod =
 Method->getInstantiatedFromMemberFunction())
-  return canonicalRenameDecl(InstantiatedMethod);
+  return canonicalRenameDecls(InstantiatedMethod);
 // FIXME(kirillbobyrev): For virtual methods with
 // size_overridden_methods() > 1, this will not rename all functions it
 // overrides, because this code assumes there is a single canonical
 // declaration.
 if (Method->isVirtual() && Method->size_overridden_methods())
-  return canonicalRenameDecl(*Method->overridden_methods().begin());
+  return {canonicalRenameDecls(*Method->overridden_methods().begin())};
   }
   if (const auto *Function = dyn_cast(D))
 if (const FunctionTemplateDecl *Template = Function->getPrimaryTemplate())
-  return canonicalRenameDecl(Template);
+  return canonicalRenameDecls(Template);
   if (const auto *Field = dyn_cast(D)) {
 // This is a hacky way to do something like
 // CXXMethodDecl::getInstantiatedFromMemberFunction for the field because
@@ -119,25 +119,25 @@
 const auto *FieldParent =
 dyn_cast_or_null(Field->getParent());
 if (!FieldParent)
-  return Field->getCanonicalDecl();
+  return {Field->getCanonicalDecl()};
 FieldParent = FieldParent->getTemplateInstantiationPattern();
 // Field is not instantiation.
 if (!FieldParent || Field->getParent() == FieldParent)
-  return Field->getCanonicalDecl();
+  return {Field->getCanonicalDecl()};
 for (const FieldDecl *Candidate : FieldParent->fields())
   if (Field->getDeclName() == Candidate->getDeclName())
-return Candidate->getCanonicalDecl();
+return {Candidate->getCanonicalDecl()};
 elog("FieldParent should have field with the same name as Field.");
   }
   if (const auto *VD = dyn_cast(D)) {
 if (const VarDecl *OriginalVD = VD->getInstantiatedFromStaticDataMember())
-  return canonicalRenameDecl(OriginalVD);
+  return canonicalRenameDecls(OriginalVD);
   }
   if (const auto *UD = dyn_cast(D)) {
 if (const auto *TargetDecl = UD->getTargetDecl())
-  return canonicalRenameDecl(TargetDecl);
+  return canonicalRenameDecls(TargetDecl);
   }
-  return dyn_cast(D->getCanonicalDecl());
+  return {dyn_cast(D->getCanonicalDecl())};
 }
 
 llvm::DenseSet locateDeclAt(ParsedAST &AST,
@@ -156,7 +156,7 @@
targetDecl(SelectedNode->ASTNode,
   DeclRelation::Alias | DeclRelation::TemplatePattern,
   AST.getHeuristicResolver())) {
-Result.insert(canonicalRenameDecl(D));
+Result.insert(D);
   }
   return Result;
 }
@@ -267,7 +267,7 @@
 st

[PATCH] D135543: [clangd] Rename: Allow renaming virtual methods overriding multiple base methods [2/3]

2022-10-09 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added a reviewer: sammccall.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders updated this revision to Diff 466392.
tom-anders added a comment.
tom-anders updated this revision to Diff 466394.
tom-anders published this revision for review.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

clang-format


tom-anders added a comment.

Fix test case


For virtual methods that override the same method from multiple base classes 
(e.g. diamond-shaped inheritance graph) previously only one of the base class 
methods would be renamed.
Now, we report a canonicalDeclaration for each base class and will thus 
correctly rename all of them.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135543

Files:
  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
@@ -1522,26 +1522,32 @@
   virtual void [[foo]]();
 };
 class Derived1 : public Base {
-  void [[f^oo]]() override;
+  void [[foo]]() override;
+};
+class Derived2 : public Base {
+  void [[foo]]() override;
 };
-class NotDerived {
-  void foo() {};
+class DerivedDerived : public Derived1, public Derived2 {
+  void [[f^oo]]() override;
 }
   )cpp",
   R"cpp(
 #include "foo.h"
 void Base::[[foo]]() {}
 void Derived1::[[foo]]() {}
+void Derived2::[[foo]]() {}
+void DerivedDerived::[[foo]]() {}
 
-class Derived2 : public Derived1 {
+class Derived3 : public Derived1 {
   void [[foo]]() override {};
 };
 
-void func(Base* b, Derived1* d1, 
-  Derived2* d2, NotDerived* nd) {
+void func(Base* b, Derived1* d1, Derived2* d2,
+  DerivedDerived* dd, NotDerived* nd) {
   b->[[foo]]();
   d1->[[foo]]();
   d2->[[foo]]();
+  dd->[[foo]]();
   nd->foo();
 }
   )cpp",
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -101,12 +101,14 @@
 if (const FunctionDecl *InstantiatedMethod =
 Method->getInstantiatedFromMemberFunction())
   return canonicalRenameDecls(InstantiatedMethod);
-// FIXME(kirillbobyrev): For virtual methods with
-// size_overridden_methods() > 1, this will not rename all functions it
-// overrides, because this code assumes there is a single canonical
-// declaration.
-if (Method->isVirtual() && Method->size_overridden_methods())
-  return {canonicalRenameDecls(*Method->overridden_methods().begin())};
+if (Method->isVirtual() && Method->size_overridden_methods()) {
+  llvm::DenseSet Result;
+  for (const auto *OM : Method->overridden_methods()) {
+auto Decls = canonicalRenameDecls(OM);
+Result.insert(Decls.begin(), Decls.end());
+  }
+  return Result;
+}
   }
   if (const auto *Function = dyn_cast(D))
 if (const FunctionTemplateDecl *Template = Function->getPrimaryTemplate())


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -1522,26 +1522,32 @@
   virtual void [[foo]]();
 };
 class Derived1 : public Base {
-  void [[f^oo]]() override;
+  void [[foo]]() override;
+};
+class Derived2 : public Base {
+  void [[foo]]() override;
 };
-class NotDerived {
-  void foo() {};
+class DerivedDerived : public Derived1, public Derived2 {
+  void [[f^oo]]() override;
 }
   )cpp",
   R"cpp(
 #include "foo.h"
 void Base::[[foo]]() {}
 void Derived1::[[foo]]() {}
+void Derived2::[[foo]]() {}
+void DerivedDerived::[[foo]]() {}
 
-class Derived2 : public Derived1 {
+class Derived3 : public Derived1 {
   void [[foo]]() override {};
 };
 
-void func(Base* b, Derived1* d1, 
-  Derived2* d2, NotDerived* nd) {
+void func(Base* b, Derived1* d1, Derived2* d2,
+  DerivedDerived* dd, NotDerived* nd) {
   b->[[foo]]();
   d1->[[foo]]();
   d2->[[foo]]();
+  dd->[[foo]]();
   nd->foo();
 }
   )cpp",
Index: clang-tools-extra/clangd/refactor/Ren

[PATCH] D135544: [clangd] Rename: Allow renaming using declaration introducing multiple symbols [3/3]

2022-10-09 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added a reviewer: sammccall.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders updated this revision to Diff 466393.
tom-anders added a comment.
tom-anders edited the summary of this revision.
tom-anders published this revision for review.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

clang-format


I needed to add a helper function to make sure that this is not reported as 
AmbiguousSymbol.
I think filterRenameTargets() now technically is not needed anymore at the 
moment, but dropping the UsingDecl probably is better for performance down the 
line.
Also, as discussed filterRenameTargets() might be extended with more conditions 
in the future, so let's keep it.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135544

Files:
  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,17 @@
   foo('x');
 }
   )cpp",
+
+  // Renaming a using-declaration that introduces multiple symbols
+  R"cpp(
+namespace ns { struct [[foo]] {}; int [[foo]](int); char 
[[foo]](char); }
+using ns::[[f^oo]];
+void bar() {
+  [[foo]](1);
+  [[foo]]('x');
+  struct [[foo]] f;
+}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1085,14 +1096,6 @@
 };
   )cpp",
"no symbol", false},
-
-  {R"cpp(// FIXME we probably want to rename both overloads here,
- // but renaming currently assumes there's only a 
- // single canonical declaration.
-namespace ns { int foo(int); char foo(char); }
-using ns::^foo;
-  )cpp",
-   "there are multiple symbols at the given location", !HeaderFile},
   };
 
   for (const auto& Case : Cases) {
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -737,6 +737,21 @@
LexedIndex + 1, Fuel, MatchedCB);
 }
 
+/// In general, if we have multiple targets under the cursor we consider them
+/// ambiguous and return an error. However, there are some exceptions.
+bool areRenameTargetsAmbiguous(
+const llvm::DenseSet &Targets) {
+  // If the cursor is on a using declaration, we may get multiple targets, e.g.
+  //namespace ns { void foo(int); void foo(char); }
+  //using ns::f^oo
+  // We want to rename both declarations here, so allow this.
+  if (llvm::any_of(Targets,
+   [](const NamedDecl *D) { return llvm::isa(D); }))
+return false;
+
+  return Targets.size() > 1;
+}
+
 } // namespace
 
 llvm::Expected rename(const RenameInputs &RInputs) {
@@ -766,12 +781,13 @@
 return makeError(ReasonToReject::UnsupportedSymbol);
 
   auto DeclsUnderCursor = locateDeclAt(AST, IdentifierToken->location());
-  filterRenameTargets(DeclsUnderCursor);
   if (DeclsUnderCursor.empty())
 return makeError(ReasonToReject::NoSymbolFound);
-  if (DeclsUnderCursor.size() > 1)
+  if (areRenameTargetsAmbiguous(DeclsUnderCursor))
 return makeError(ReasonToReject::AmbiguousSymbol);
 
+  filterRenameTargets(DeclsUnderCursor);
+
   llvm::DenseSet RenameDecls;
   for (const auto *D : DeclsUnderCursor) {
 auto CD = canonicalRenameDecls(D);


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,17 @@
   foo('x');
 }
   )cpp",
+
+  // Renaming a using-declaration that introduces multiple symbols
+  R"cpp(
+namespace ns { struct [[foo]] {}; int [[foo]](int); char [[foo]](char); }
+using ns::[[f^oo]];
+void bar() {
+  [[foo]](1);
+  [[foo]]('x');
+  struct [[foo]] f;
+}
+  )cpp",
   };
   llvm::StringRef NewName = "NewName";
   for (llvm::StringRef T : Tests) {
@@ -1085,14 +1096,6 @@
 };
   )cpp",
"no symbol", false},
-
-  {R"cpp(// FIXME we probably want to rename both overloads here,
- // but renaming currently assumes there's only a 
- // single canonical declaration.
-namespace ns { int foo(int); char foo(char); }
-using ns::^foo;
-  )cpp",
-   "there are multiple symbols at the given location", !HeaderFile},
   };
 
   for (const auto& Case : Cases) {
Index: clang-tools-extra/clangd/refactor/Rename.cpp
==

[PATCH] D133843: [clangd] Prefer definitions for gototype and implementation

2022-10-11 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

> happy to add some comments for the reasoning if you (and possibly others 
> seeing this change) also agree that this is more useful

Can confirm that (at least to me) it's really annoying when it takes me to a 
forward declaration here. I 99% of the time will immediately trigger 
textDocument/definition when this happens.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133843

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


[PATCH] D135892: [clangd] Add missing readonly modifier for const generic parameters

2022-10-13 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added reviewers: nridge, sammccall.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Fixes https://github.com/clangd/clangd/issues/1222. As discussed there, we saw 
no reason to keep this check.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135892

Files:
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -847,6 +847,17 @@
 const char *$LocalVariable_decl_readonly[[s]] = 
$LocalVariable_readonly_static[[__func__]];
 }
   )cpp",
+  // Issue 1022: readonly modifier for generic parameter
+  R"cpp(
+template 
+auto $Function_decl[[foo]](const $TemplateParameter[[T]] 
$Parameter_decl_readonly[[template_type]], 
+   const $TemplateParameter[[auto]] 
$Parameter_decl_readonly[[auto_type]], 
+   const int 
$Parameter_decl_readonly[[explicit_type]]) {
+return $Parameter_readonly[[template_type]] 
+ + $Parameter_readonly[[auto_type]] 
+ + $Parameter_readonly[[explicit_type]];
+}
+  )cpp",
   // Explicit template specialization
   R"cpp(
 struct $Class_decl[[Base]]{};
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -164,7 +164,7 @@
 
 // Whether T is const in a loose sense - is a variable with this type readonly?
 bool isConst(QualType T) {
-  if (T.isNull() || T->isDependentType())
+  if (T.isNull())
 return false;
   T = T.getNonReferenceType();
   if (T.isConstQualified())


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -847,6 +847,17 @@
 const char *$LocalVariable_decl_readonly[[s]] = $LocalVariable_readonly_static[[__func__]];
 }
   )cpp",
+  // Issue 1022: readonly modifier for generic parameter
+  R"cpp(
+template 
+auto $Function_decl[[foo]](const $TemplateParameter[[T]] $Parameter_decl_readonly[[template_type]], 
+   const $TemplateParameter[[auto]] $Parameter_decl_readonly[[auto_type]], 
+   const int $Parameter_decl_readonly[[explicit_type]]) {
+return $Parameter_readonly[[template_type]] 
+ + $Parameter_readonly[[auto_type]] 
+ + $Parameter_readonly[[explicit_type]];
+}
+  )cpp",
   // Explicit template specialization
   R"cpp(
 struct $Class_decl[[Base]]{};
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -164,7 +164,7 @@
 
 // Whether T is const in a loose sense - is a variable with this type readonly?
 bool isConst(QualType T) {
-  if (T.isNull() || T->isDependentType())
+  if (T.isNull())
 return false;
   T = T.getNonReferenceType();
   if (T.isConstQualified())
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135892: [clangd] Add missing readonly modifier for const generic parameters

2022-10-13 Thread Tom Praschan 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 rGa8124eea9df5: [clangd] Add missing readonly modifier for 
const generic parameters (authored by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135892

Files:
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -855,6 +855,17 @@
 const char *$LocalVariable_decl_readonly[[s]] = 
$LocalVariable_readonly_static[[__func__]];
 }
   )cpp",
+  // Issue 1022: readonly modifier for generic parameter
+  R"cpp(
+template 
+auto $Function_decl[[foo]](const $TemplateParameter[[T]] 
$Parameter_decl_readonly[[template_type]], 
+   const $TemplateParameter[[auto]] 
$Parameter_decl_readonly[[auto_type]], 
+   const int 
$Parameter_decl_readonly[[explicit_type]]) {
+return $Parameter_readonly[[template_type]] 
+ + $Parameter_readonly[[auto_type]] 
+ + $Parameter_readonly[[explicit_type]];
+}
+  )cpp",
   // Explicit template specialization
   R"cpp(
 struct $Class_decl[[Base]]{};
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -164,7 +164,7 @@
 
 // Whether T is const in a loose sense - is a variable with this type readonly?
 bool isConst(QualType T) {
-  if (T.isNull() || T->isDependentType())
+  if (T.isNull())
 return false;
   T = T.getNonReferenceType();
   if (T.isConstQualified())


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -855,6 +855,17 @@
 const char *$LocalVariable_decl_readonly[[s]] = $LocalVariable_readonly_static[[__func__]];
 }
   )cpp",
+  // Issue 1022: readonly modifier for generic parameter
+  R"cpp(
+template 
+auto $Function_decl[[foo]](const $TemplateParameter[[T]] $Parameter_decl_readonly[[template_type]], 
+   const $TemplateParameter[[auto]] $Parameter_decl_readonly[[auto_type]], 
+   const int $Parameter_decl_readonly[[explicit_type]]) {
+return $Parameter_readonly[[template_type]] 
+ + $Parameter_readonly[[auto_type]] 
+ + $Parameter_readonly[[explicit_type]];
+}
+  )cpp",
   // Explicit template specialization
   R"cpp(
 struct $Class_decl[[Base]]{};
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -164,7 +164,7 @@
 
 // Whether T is const in a loose sense - is a variable with this type readonly?
 bool isConst(QualType T) {
-  if (T.isNull() || T->isDependentType())
+  if (T.isNull())
 return false;
   T = T.getNonReferenceType();
   if (T.isConstQualified())
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135892: [clangd] Add missing readonly modifier for const generic parameters

2022-10-13 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135892

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


[PATCH] D137894: [clangd] Add extension for adding context (enclosing function or class) in references results

2022-12-28 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/XRefs.cpp:1484
+LookupRequest ContainerLookup;
+llvm::DenseMap RefIndexForContainer;
 Results.HasMore |= Index->refs(Req, [&](const Ref &R) {

nridge wrote:
> We can have multiple references with the same container (e.g. multiple 
> references in the same function), so I think we need `DenseMap std::vector>` here.
Good catch! Turns out this fixes the FIXME I added in 
FindReferences.RefsToBaseMethod



Comment at: clang-tools-extra/clangd/XRefs.cpp:1501
   }
+  SymbolID Container = R.Container;
+  ContainerLookup.IDs.insert(Container);

nridge wrote:
> For good measure, perhaps condition the container-related logic here on 
> `AddContext`?
Good point, otherwise we're just wasting cycles and memory here if `AddContext` 
is false anyway



Comment at: clang-tools-extra/clangd/unittests/XRefsTests.cpp:2238
   for (const auto &R : Code.ranges())
 ExpectedLocations.push_back(rangeIs(R));
   EXPECT_THAT(findReferences(AST, Code.point(), 0).References,

nridge wrote:
> Did you mean to test the payload here?
Hmm I think I instead missed that this test does not use `checkFindRefs`. 
Removed the payload here, this path is already covered by other tests anyway.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137894

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


[PATCH] D137894: [clangd] Add extension for adding context (enclosing function or class) in references results

2022-12-28 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 485482.
tom-anders marked 8 inline comments as done.
tom-anders added a comment.

Rebase, fix review comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137894

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/XRefs.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/test/references-container.test
  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
@@ -301,6 +301,9 @@
 MATCHER_P(sym, Name, "") { return arg.Name == Name; }
 
 MATCHER_P(rangeIs, R, "") { return arg.Loc.range == R; }
+MATCHER_P(containerIs, C, "") {
+  return arg.Loc.containerName.value_or("") == C;
+}
 MATCHER_P(attrsAre, A, "") { return arg.Attributes == A; }
 MATCHER_P(hasID, ID, "") { return arg.ID == ID; }
 
@@ -1900,28 +1903,30 @@
 
   auto AST = TU.build();
   std::vector> ExpectedLocations;
-  for (const auto &R : T.ranges())
-ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
+  for (const auto &[R, Context] : T.rangesWithPayload())
+ExpectedLocations.push_back(
+AllOf(rangeIs(R), containerIs(Context), attrsAre(0u)));
   // $def is actually shorthand for both definition and declaration.
   // If we have cases that are definition-only, we should change this.
-  for (const auto &R : T.ranges("def"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Definition |
-   ReferencesResult::Declaration)));
-  for (const auto &R : T.ranges("decl"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration)));
-  for (const auto &R : T.ranges("overridedecl"))
+  for (const auto &[R, Context] : T.rangesWithPayload("def"))
+ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
+  attrsAre(ReferencesResult::Definition |
+   ReferencesResult::Declaration)));
+  for (const auto &[R, Context] : T.rangesWithPayload("decl"))
+ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
+  attrsAre(ReferencesResult::Declaration)));
+  for (const auto &[R, Context] : T.rangesWithPayload("overridedecl"))
 ExpectedLocations.push_back(AllOf(
-rangeIs(R),
+rangeIs(R), containerIs(Context),
 attrsAre(ReferencesResult::Declaration | ReferencesResult::Override)));
-  for (const auto &R : T.ranges("overridedef"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration |
-   ReferencesResult::Definition |
-   ReferencesResult::Override)));
+  for (const auto &[R, Context] : T.rangesWithPayload("overridedef"))
+ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
+  attrsAre(ReferencesResult::Declaration |
+   ReferencesResult::Definition |
+   ReferencesResult::Override)));
   for (const auto &P : T.points()) {
-EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr)
+EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr,
+   /*AddContext*/ true)
 .References,
 UnorderedElementsAreArray(ExpectedLocations))
 << "Failed for Refs at " << P << "\n"
@@ -1933,18 +1938,18 @@
   const char *Tests[] = {
   R"cpp(// Local variable
 int main() {
-  int $def[[foo]];
-  [[^foo]] = 2;
-  int test1 = [[foo]];
+  int $def(main)[[foo]];
+  $(main)[[^foo]] = 2;
+  int test1 = $(main)[[foo]];
 }
   )cpp",
 
   R"cpp(// Struct
 namespace ns1 {
-struct $def[[Foo]] {};
+struct $def(ns1)[[Foo]] {};
 } // namespace ns1
 int main() {
-  ns1::[[Fo^o]]* Params;
+  ns1::$(main)[[Fo^o]]* Params;
 }
   )cpp",
 
@@ -1952,51 +1957,51 @@
 class $decl[[Foo]];
 class $def[[Foo]] {};
 int main() {
-  [[Fo^o]] foo;
+  $(main)[[Fo^o]] foo;
 }
   )cpp",
 
   R"cpp(// Function
 int $def[[foo]](int) {}
 int m

[PATCH] D138028: [clangd] Fix action `RemoveUsingNamespace` for inline namespace

2022-12-28 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders accepted this revision.
tom-anders added a comment.
This revision is now accepted and ready to land.

LGTM!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138028

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


[PATCH] D137894: [clangd] Add extension for adding context (enclosing function or class) in references results

2022-12-28 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 485483.
tom-anders added a comment.

s/llvm::Optional/std::optional/ for containerName field


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137894

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/XRefs.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/test/references-container.test
  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
@@ -301,6 +301,9 @@
 MATCHER_P(sym, Name, "") { return arg.Name == Name; }
 
 MATCHER_P(rangeIs, R, "") { return arg.Loc.range == R; }
+MATCHER_P(containerIs, C, "") {
+  return arg.Loc.containerName.value_or("") == C;
+}
 MATCHER_P(attrsAre, A, "") { return arg.Attributes == A; }
 MATCHER_P(hasID, ID, "") { return arg.ID == ID; }
 
@@ -1900,28 +1903,30 @@
 
   auto AST = TU.build();
   std::vector> ExpectedLocations;
-  for (const auto &R : T.ranges())
-ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
+  for (const auto &[R, Context] : T.rangesWithPayload())
+ExpectedLocations.push_back(
+AllOf(rangeIs(R), containerIs(Context), attrsAre(0u)));
   // $def is actually shorthand for both definition and declaration.
   // If we have cases that are definition-only, we should change this.
-  for (const auto &R : T.ranges("def"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Definition |
-   ReferencesResult::Declaration)));
-  for (const auto &R : T.ranges("decl"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration)));
-  for (const auto &R : T.ranges("overridedecl"))
+  for (const auto &[R, Context] : T.rangesWithPayload("def"))
+ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
+  attrsAre(ReferencesResult::Definition |
+   ReferencesResult::Declaration)));
+  for (const auto &[R, Context] : T.rangesWithPayload("decl"))
+ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
+  attrsAre(ReferencesResult::Declaration)));
+  for (const auto &[R, Context] : T.rangesWithPayload("overridedecl"))
 ExpectedLocations.push_back(AllOf(
-rangeIs(R),
+rangeIs(R), containerIs(Context),
 attrsAre(ReferencesResult::Declaration | ReferencesResult::Override)));
-  for (const auto &R : T.ranges("overridedef"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration |
-   ReferencesResult::Definition |
-   ReferencesResult::Override)));
+  for (const auto &[R, Context] : T.rangesWithPayload("overridedef"))
+ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
+  attrsAre(ReferencesResult::Declaration |
+   ReferencesResult::Definition |
+   ReferencesResult::Override)));
   for (const auto &P : T.points()) {
-EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr)
+EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr,
+   /*AddContext*/ true)
 .References,
 UnorderedElementsAreArray(ExpectedLocations))
 << "Failed for Refs at " << P << "\n"
@@ -1933,18 +1938,18 @@
   const char *Tests[] = {
   R"cpp(// Local variable
 int main() {
-  int $def[[foo]];
-  [[^foo]] = 2;
-  int test1 = [[foo]];
+  int $def(main)[[foo]];
+  $(main)[[^foo]] = 2;
+  int test1 = $(main)[[foo]];
 }
   )cpp",
 
   R"cpp(// Struct
 namespace ns1 {
-struct $def[[Foo]] {};
+struct $def(ns1)[[Foo]] {};
 } // namespace ns1
 int main() {
-  ns1::[[Fo^o]]* Params;
+  ns1::$(main)[[Fo^o]]* Params;
 }
   )cpp",
 
@@ -1952,51 +1957,51 @@
 class $decl[[Foo]];
 class $def[[Foo]] {};
 int main() {
-  [[Fo^o]] foo;
+  $(main)[[Fo^o]] foo;
 }
   )cpp",
 
   R"cpp(// Function
 int $def[[foo]](int) {}
 int main() {
-

[PATCH] D138028: [clangd] Fix action `RemoveUsingNamespace` for inline namespace

2022-12-28 Thread Tom Praschan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG46575f60380b: [clangd] Fix action `RemoveUsingNamespace` for 
inline namespace (authored by v1nh1shungry, committed by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138028

Files:
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp


Index: clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
===
--- clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
+++ clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
@@ -264,6 +264,17 @@
   }
   
   int main() { 1.5_w; }
+)cpp"},
+  {
+  R"cpp(
+  namespace a { inline namespace b { void foobar(); } }
+  using namespace a::[[b]];
+  int main() { foobar(); }
+)cpp",
+  R"cpp(
+  namespace a { inline namespace b { void foobar(); } }
+  
+  int main() { a::b::foobar(); }
 )cpp"}};
   for (auto C : Cases)
 EXPECT_EQ(C.second, apply(C.first)) << C.first;
Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -89,16 +89,15 @@
   return Node->Parent && Node->Parent->ASTNode.get();
 }
 
-// Returns the first visible context that contains this DeclContext.
-// For example: Returns ns1 for S1 and a.
-// namespace ns1 {
-// inline namespace ns2 { struct S1 {}; }
-// enum E { a, b, c, d };
-// }
-const DeclContext *visibleContext(const DeclContext *D) {
-  while (D->isInlineNamespace() || D->isTransparentContext())
+// Return true if `LHS` is declared in `RHS`
+bool isDeclaredIn(const NamedDecl *LHS, const DeclContext *RHS) {
+  const auto *D = LHS->getDeclContext();
+  while (D->isInlineNamespace() || D->isTransparentContext()) {
+if (D->Equals(RHS))
+  return true;
 D = D->getParent();
-  return D;
+  }
+  return D->Equals(RHS);
 }
 
 bool RemoveUsingNamespace::prepare(const Selection &Inputs) {
@@ -152,8 +151,7 @@
 return; // This reference is already qualified.
 
   for (auto *T : Ref.Targets) {
-if (!visibleContext(T->getDeclContext())
- ->Equals(TargetDirective->getNominatedNamespace()))
+if (!isDeclaredIn(T, TargetDirective->getNominatedNamespace()))
   return;
 auto Kind = T->getDeclName().getNameKind();
 // Avoid adding qualifiers before operators, e.g.


Index: clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
===
--- clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
+++ clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
@@ -264,6 +264,17 @@
   }
   
   int main() { 1.5_w; }
+)cpp"},
+  {
+  R"cpp(
+  namespace a { inline namespace b { void foobar(); } }
+  using namespace a::[[b]];
+  int main() { foobar(); }
+)cpp",
+  R"cpp(
+  namespace a { inline namespace b { void foobar(); } }
+  
+  int main() { a::b::foobar(); }
 )cpp"}};
   for (auto C : Cases)
 EXPECT_EQ(C.second, apply(C.first)) << C.first;
Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -89,16 +89,15 @@
   return Node->Parent && Node->Parent->ASTNode.get();
 }
 
-// Returns the first visible context that contains this DeclContext.
-// For example: Returns ns1 for S1 and a.
-// namespace ns1 {
-// inline namespace ns2 { struct S1 {}; }
-// enum E { a, b, c, d };
-// }
-const DeclContext *visibleContext(const DeclContext *D) {
-  while (D->isInlineNamespace() || D->isTransparentContext())
+// Return true if `LHS` is declared in `RHS`
+bool isDeclaredIn(const NamedDecl *LHS, const DeclContext *RHS) {
+  const auto *D = LHS->getDeclContext();
+  while (D->isInlineNamespace() || D->isTransparentContext()) {
+if (D->Equals(RHS))
+  return true;
 D = D->getParent();
-  return D;
+  }
+  return D->Equals(RHS);
 }
 
 bool RemoveUsingNamespace::prepare(const Selection &Inputs) {
@@ -152,8 +151,7 @@
 return; // This reference is already qualified.
 
   for (auto *T : Ref.Targets) {
-if (!visibleContext(T->getDeclContext())
- ->Equals(TargetDirective->getNominatedNamespace()))
+if (!isDeclaredIn(T, TargetDirectiv

[PATCH] D140775: [clangd] Hover: show CalleeArgInfo for literals

2022-12-30 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added reviewers: nridge, sammccall.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

This is very useful when inlay hints are disabled.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D140775

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp

Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -900,6 +900,22 @@
  HI.CalleeArgInfo->Type = "int &";
  HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};
}},
+  {// Literal passed to function call
+   R"cpp(
+  void fun(int arg_a, const int &arg_b) {};
+  void code() {
+int a = 1;
+fun(a, [[^2]]);
+  }
+  )cpp",
+   [](HoverInfo &HI) {
+ HI.Name = "literal";
+ HI.Kind = index::SymbolKind::Unknown;
+ HI.CalleeArgInfo.emplace();
+ HI.CalleeArgInfo->Name = "arg_b";
+ HI.CalleeArgInfo->Type = "const int &";
+ HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, false};
+   }},
   {// Extra info for method call.
R"cpp(
   class C {
@@ -1226,8 +1242,10 @@
   } Tests[] = {
   // Integer tests
   {"int_by_value([[^int_x]]);", PassMode::Value, false},
+  {"int_by_value([[^123]]);", PassMode::Value, false},
   {"int_by_ref([[^int_x]]);", PassMode::Ref, false},
   {"int_by_const_ref([[^int_x]]);", PassMode::ConstRef, false},
+  {"int_by_const_ref([[^123]]);", PassMode::ConstRef, false},
   {"int_by_value([[^int_ref]]);", PassMode::Value, false},
   {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},
   {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},
@@ -1245,6 +1263,8 @@
   {"float_by_value([[^int_x]]);", PassMode::Value, true},
   {"float_by_value([[^int_ref]]);", PassMode::Value, true},
   {"float_by_value([[^int_const_ref]]);", PassMode::Value, true},
+  {"float_by_value([[^123.0f]]);", PassMode::Value, false},
+  {"float_by_value([[^123]]);", PassMode::Value, true},
   {"custom_by_value([[^int_x]]);", PassMode::Ref, true},
   {"custom_by_value([[^float_x]]);", PassMode::Value, true},
   {"custom_by_value([[^base]]);", PassMode::ConstRef, true},
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -776,15 +776,11 @@
   return HI;
 }
 
-HoverInfo getStringLiteralContents(const StringLiteral *SL,
-   const PrintingPolicy &PP) {
-  HoverInfo HI;
-
+void addStringLiteralContents(const StringLiteral *SL, const PrintingPolicy &PP,
+  HoverInfo &HI) {
   HI.Name = "string-literal";
   HI.Size = (SL->getLength() + 1) * SL->getCharByteWidth();
   HI.Type = SL->getType().getAsString(PP).c_str();
-
-  return HI;
 }
 
 bool isLiteral(const Expr *E) {
@@ -795,7 +791,7 @@
  llvm::isa(E) ||
  llvm::isa(E) || llvm::isa(E) ||
  llvm::isa(E) || llvm::isa(E) ||
- llvm::isa(E);
+ llvm::isa(E) || llvm::isa(E);
 }
 
 llvm::StringLiteral getNameForExpr(const Expr *E) {
@@ -809,20 +805,34 @@
   return llvm::StringLiteral("expression");
 }
 
+void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI,
+   const PrintingPolicy &PP);
+
 // Generates hover info for `this` and evaluatable expressions.
 // FIXME: Support hover for literals (esp user-defined)
-std::optional getHoverContents(const Expr *E, ParsedAST &AST,
+std::optional getHoverContents(const SelectionTree::Node *N,
+  const Expr *E, ParsedAST &AST,
   const PrintingPolicy &PP,
   const SymbolIndex *Index) {
+  HoverInfo HI;
+
   // There's not much value in hovering over "42" and getting a hover card
-  // saying "42 is an int", similar for other literals.
-  if (isLiteral(E))
+  // saying "42 is an int", similar for most other literals.
+  // However, if we have CalleeArgInfo, it's still useful to show it.
+  if (isLiteral(E)) {
+maybeAddCalleeArgInfo(N, HI, PP);
+// Print the type and the size for string literals
+if (const StringLiteral *SL = dyn_cast(E)) {
+  addStringLiteralContents(SL, PP, HI);
+  return HI;
+}
+if (HI.CalleeArgInfo) {
+  HI.Name = "literal";
+  return HI;
+}
 return std::nullopt;
+  }
 
-  HoverInfo HI;
-  // Print the type and the size for string 

[PATCH] D140775: [clangd] Hover: show CalleeArgInfo for literals

2022-12-30 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/Hover.cpp:808
 
+void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI,
+   const PrintingPolicy &PP);

(I also modified this function, so I added this forward declaration for easier 
review.

If this patch gets accepted, I'd move the definition up to here before landing)



Comment at: clang-tools-extra/clangd/Hover.cpp:830
+if (HI.CalleeArgInfo) {
+  HI.Name = "literal";
+  return HI;

`HoverInfo::present` has an assertion that the `Name` has to be non-empty. I'm 
open for other name suggestions here (Or we could of course adjust 
`HoverInfo::present` instead)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140775

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


[PATCH] D140775: [clangd] Hover: show CalleeArgInfo for literals

2022-12-31 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 485761.
tom-anders marked 4 inline comments as done.
tom-anders added a comment.

Refactor getHoverContents to add CalleeArgInfo for all kinds of expression


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140775

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp

Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -900,6 +900,22 @@
  HI.CalleeArgInfo->Type = "int &";
  HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};
}},
+  {// Literal passed to function call
+   R"cpp(
+  void fun(int arg_a, const int &arg_b) {};
+  void code() {
+int a = 1;
+fun(a, [[^2]]);
+  }
+  )cpp",
+   [](HoverInfo &HI) {
+ HI.Name = "literal";
+ HI.Kind = index::SymbolKind::Unknown;
+ HI.CalleeArgInfo.emplace();
+ HI.CalleeArgInfo->Name = "arg_b";
+ HI.CalleeArgInfo->Type = "const int &";
+ HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, false};
+   }},
   {// Extra info for method call.
R"cpp(
   class C {
@@ -1226,8 +1242,10 @@
   } Tests[] = {
   // Integer tests
   {"int_by_value([[^int_x]]);", PassMode::Value, false},
+  {"int_by_value([[^123]]);", PassMode::Value, false},
   {"int_by_ref([[^int_x]]);", PassMode::Ref, false},
   {"int_by_const_ref([[^int_x]]);", PassMode::ConstRef, false},
+  {"int_by_const_ref([[^123]]);", PassMode::ConstRef, false},
   {"int_by_value([[^int_ref]]);", PassMode::Value, false},
   {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},
   {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},
@@ -1245,6 +1263,8 @@
   {"float_by_value([[^int_x]]);", PassMode::Value, true},
   {"float_by_value([[^int_ref]]);", PassMode::Value, true},
   {"float_by_value([[^int_const_ref]]);", PassMode::Value, true},
+  {"float_by_value([[^123.0f]]);", PassMode::Value, false},
+  {"float_by_value([[^123]]);", PassMode::Value, true},
   {"custom_by_value([[^int_x]]);", PassMode::Ref, true},
   {"custom_by_value([[^float_x]]);", PassMode::Value, true},
   {"custom_by_value([[^base]]);", PassMode::ConstRef, true},
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -795,7 +795,7 @@
  llvm::isa(E) ||
  llvm::isa(E) || llvm::isa(E) ||
  llvm::isa(E) || llvm::isa(E) ||
- llvm::isa(E);
+ llvm::isa(E) || llvm::isa(E);
 }
 
 llvm::StringLiteral getNameForExpr(const Expr *E) {
@@ -809,34 +809,53 @@
   return llvm::StringLiteral("expression");
 }
 
+void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI,
+   const PrintingPolicy &PP);
+
 // Generates hover info for `this` and evaluatable expressions.
 // FIXME: Support hover for literals (esp user-defined)
-std::optional getHoverContents(const Expr *E, ParsedAST &AST,
+std::optional getHoverContents(const SelectionTree::Node *N,
+  const Expr *E, ParsedAST &AST,
   const PrintingPolicy &PP,
   const SymbolIndex *Index) {
-  // There's not much value in hovering over "42" and getting a hover card
-  // saying "42 is an int", similar for other literals.
-  if (isLiteral(E))
+  std::optional HI;
+
+  if (const StringLiteral *SL = dyn_cast(E)) {
+// Print the type and the size for string literals
+HI = getStringLiteralContents(SL, PP);
+  } else if (isLiteral(E)) {
+// There's not much value in hovering over "42" and getting a hover card
+// saying "42 is an int", similar for most other literals.
+// However, if we have CalleeArgInfo, it's still useful to show it.
+maybeAddCalleeArgInfo(N, HI.emplace(), PP);
+if (HI->CalleeArgInfo) {
+  // FIXME Might want to show the expression's value here instead?
+  // E.g. if the literal is in hex it might be useful to show the decimal
+  // value here.
+  HI->Name = "literal";
+  return HI;
+}
 return std::nullopt;
+  }
 
-  HoverInfo HI;
-  // Print the type and the size for string literals
-  if (const StringLiteral *SL = dyn_cast(E))
-return getStringLiteralContents(SL, PP);
   // For `this` expr we currently generate hover with pointee type.
   if (const CXXThisExpr *CTE = dyn_cast(E))
-return getThisExprHoverContents(CTE, AST.getASTContext(), PP);
+HI = getThisExprHoverContents(CTE, AST.getASTContext(), PP);
   if (co

[PATCH] D140775: [clangd] Hover: show CalleeArgInfo for literals

2022-12-31 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/Hover.cpp:779
 
-HoverInfo getStringLiteralContents(const StringLiteral *SL,
-   const PrintingPolicy &PP) {
-  HoverInfo HI;
-
+void addStringLiteralContents(const StringLiteral *SL, const PrintingPolicy 
&PP,
+  HoverInfo &HI) {

nridge wrote:
> nit: "contents" seems a bit strange now that this is no longer necessarily 
> the entirety of the hover contents (nor is it the string literal's contents)
> 
> maybe name it `addStringLiteralInfo`?
Changed back to the previous signature in current patch version



Comment at: clang-tools-extra/clangd/Hover.cpp:830
+if (HI.CalleeArgInfo) {
+  HI.Name = "literal";
+  return HI;

nridge wrote:
> tom-anders wrote:
> > `HoverInfo::present` has an assertion that the `Name` has to be non-empty. 
> > I'm open for other name suggestions here (Or we could of course adjust 
> > `HoverInfo::present` instead)
> It at least seems no worse than `"expression"` for other expressions.
> 
> I think the expression's value would be more useful (and despite the "not 
> much value" comment above, I think there //can// be value in showing this if 
> e.g. the expression is written as hex and the hover shows you the decimal 
> value), but that can be left for a later change.
Added a FIXME for that



Comment at: clang-tools-extra/clangd/Hover.cpp:843
   // evaluatable.
   if (auto Val = printExprValue(E, AST.getASTContext())) {
 HI.Type = printType(E->getType(), AST.getASTContext(), PP);

nridge wrote:
> Any reason not to also add CalleeArgInfo in this branch?
> 
> I know this branch is not for literals so I'm suggesting to expand the scope 
> of the patch, feel free to leave this for later, but conceptually I don't see 
> why the CalleeArgInfo would be any less useful for non-literal expressions 
> that take this branch.
Good point, I refactored the logic here a bit, now CalleeArgInfo is added for 
this branch, and also the two branches above. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140775

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


[PATCH] D137894: [clangd] Add extension for adding context (enclosing function or class) in references results

2022-12-31 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

Thanks both of you for reviewing!

I added documentation to the website here: 
https://github.com/llvm/clangd-www/pull/77


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137894

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


[PATCH] D137894: [clangd] Add extension for adding context (enclosing function or class) in references results

2023-01-01 Thread Tom Praschan 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 rGd408c34d1f58: [clangd] Add extension for adding context 
(enclosing function or class) in… (authored by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137894

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/XRefs.h
  clang-tools-extra/clangd/index/SymbolCollector.cpp
  clang-tools-extra/clangd/index/SymbolCollector.h
  clang-tools-extra/clangd/test/references-container.test
  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
@@ -301,6 +301,9 @@
 MATCHER_P(sym, Name, "") { return arg.Name == Name; }
 
 MATCHER_P(rangeIs, R, "") { return arg.Loc.range == R; }
+MATCHER_P(containerIs, C, "") {
+  return arg.Loc.containerName.value_or("") == C;
+}
 MATCHER_P(attrsAre, A, "") { return arg.Attributes == A; }
 MATCHER_P(hasID, ID, "") { return arg.ID == ID; }
 
@@ -1900,28 +1903,30 @@
 
   auto AST = TU.build();
   std::vector> ExpectedLocations;
-  for (const auto &R : T.ranges())
-ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
+  for (const auto &[R, Context] : T.rangesWithPayload())
+ExpectedLocations.push_back(
+AllOf(rangeIs(R), containerIs(Context), attrsAre(0u)));
   // $def is actually shorthand for both definition and declaration.
   // If we have cases that are definition-only, we should change this.
-  for (const auto &R : T.ranges("def"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Definition |
-   ReferencesResult::Declaration)));
-  for (const auto &R : T.ranges("decl"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration)));
-  for (const auto &R : T.ranges("overridedecl"))
+  for (const auto &[R, Context] : T.rangesWithPayload("def"))
+ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
+  attrsAre(ReferencesResult::Definition |
+   ReferencesResult::Declaration)));
+  for (const auto &[R, Context] : T.rangesWithPayload("decl"))
+ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
+  attrsAre(ReferencesResult::Declaration)));
+  for (const auto &[R, Context] : T.rangesWithPayload("overridedecl"))
 ExpectedLocations.push_back(AllOf(
-rangeIs(R),
+rangeIs(R), containerIs(Context),
 attrsAre(ReferencesResult::Declaration | ReferencesResult::Override)));
-  for (const auto &R : T.ranges("overridedef"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration |
-   ReferencesResult::Definition |
-   ReferencesResult::Override)));
+  for (const auto &[R, Context] : T.rangesWithPayload("overridedef"))
+ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),
+  attrsAre(ReferencesResult::Declaration |
+   ReferencesResult::Definition |
+   ReferencesResult::Override)));
   for (const auto &P : T.points()) {
-EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr)
+EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr,
+   /*AddContext*/ true)
 .References,
 UnorderedElementsAreArray(ExpectedLocations))
 << "Failed for Refs at " << P << "\n"
@@ -1933,18 +1938,18 @@
   const char *Tests[] = {
   R"cpp(// Local variable
 int main() {
-  int $def[[foo]];
-  [[^foo]] = 2;
-  int test1 = [[foo]];
+  int $def(main)[[foo]];
+  $(main)[[^foo]] = 2;
+  int test1 = $(main)[[foo]];
 }
   )cpp",
 
   R"cpp(// Struct
 namespace ns1 {
-struct $def[[Foo]] {};
+struct $def(ns1)[[Foo]] {};
 } // namespace ns1
 int main() {
-  ns1::[[Fo^o]]* Params;
+  ns1::$(main)[[Fo^o]]* Params;
 }
   )cpp",
 
@@ -1952,51 +1957,51 @@
 class $decl[[Foo]];
 class $def[[Foo]] {};
 int main() {
-  [[Fo^o]] foo;
+  $(main

[PATCH] D140775: [clangd] Hover: show CalleeArgInfo for literals

2023-01-02 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

In D140775#4021634 , @nridge wrote:

> Do you want to add a simple test case for a non-literal expression? Something 
> like hovering over the `+` in `2 + 3` should work.

Will do!

> Also, this is pre-existing, but I noticed that in a case like this:
>
>   void bar(int);
>   void func() {
> int x = 42;
> bar(x);
>   }
>
> the hover for `x` includes a line that just says `Passed` -- is that useful 
> in any way? Should we just omit the CalleeArgInfo a case like that?

Hmm, the thing is that if the function signature is `void bar(int&)`, then 
"Passed by reference" would be useful again, so we can't just add a `if 
(!CalleeArgInfo->Name.empty())` around the `OS << "Passed ";` Maybe we could 
instead display "Passed **by value**" if and only if the name is empty?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140775

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


[PATCH] D140775: [clangd] Hover: show CalleeArgInfo for literals

2023-01-03 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 486039.
tom-anders added a comment.

Add test for expression, improve presentation for signature with unnamed 
parameter


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140775

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp

Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -900,6 +900,40 @@
  HI.CalleeArgInfo->Type = "int &";
  HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};
}},
+  {// Literal passed to function call
+   R"cpp(
+  void fun(int arg_a, const int &arg_b) {};
+  void code() {
+int a = 1;
+fun(a, [[^2]]);
+  }
+  )cpp",
+   [](HoverInfo &HI) {
+ HI.Name = "literal";
+ HI.Kind = index::SymbolKind::Unknown;
+ HI.CalleeArgInfo.emplace();
+ HI.CalleeArgInfo->Name = "arg_b";
+ HI.CalleeArgInfo->Type = "const int &";
+ HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, false};
+   }},
+  {// Expression passed to function call
+   R"cpp(
+  void fun(int arg_a, const int &arg_b) {};
+  void code() {
+int a = 1;
+fun(a, 1 [[^+]] 2);
+  }
+  )cpp",
+   [](HoverInfo &HI) {
+ HI.Name = "expression";
+ HI.Kind = index::SymbolKind::Unknown;
+ HI.Type = "int";
+ HI.Value = "3";
+ HI.CalleeArgInfo.emplace();
+ HI.CalleeArgInfo->Name = "arg_b";
+ HI.CalleeArgInfo->Type = "const int &";
+ HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, false};
+   }},
   {// Extra info for method call.
R"cpp(
   class C {
@@ -1226,8 +1260,10 @@
   } Tests[] = {
   // Integer tests
   {"int_by_value([[^int_x]]);", PassMode::Value, false},
+  {"int_by_value([[^123]]);", PassMode::Value, false},
   {"int_by_ref([[^int_x]]);", PassMode::Ref, false},
   {"int_by_const_ref([[^int_x]]);", PassMode::ConstRef, false},
+  {"int_by_const_ref([[^123]]);", PassMode::ConstRef, false},
   {"int_by_value([[^int_ref]]);", PassMode::Value, false},
   {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},
   {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},
@@ -1245,6 +1281,8 @@
   {"float_by_value([[^int_x]]);", PassMode::Value, true},
   {"float_by_value([[^int_ref]]);", PassMode::Value, true},
   {"float_by_value([[^int_const_ref]]);", PassMode::Value, true},
+  {"float_by_value([[^123.0f]]);", PassMode::Value, false},
+  {"float_by_value([[^123]]);", PassMode::Value, true},
   {"custom_by_value([[^int_x]]);", PassMode::Ref, true},
   {"custom_by_value([[^float_x]]);", PassMode::Value, true},
   {"custom_by_value([[^base]]);", PassMode::ConstRef, true},
@@ -3043,6 +3081,18 @@
 
 // In test::Bar
 int foo = 3)",
+  },
+  {
+  [](HoverInfo &HI) {
+HI.Kind = index::SymbolKind::Variable;
+HI.Name = "foo";
+HI.CalleeArgInfo.emplace();
+HI.CalleeArgInfo->Type = "int";
+HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};
+  },
+  R"(variable foo
+
+Passed by value)",
   },
   {
   [](HoverInfo &HI) {
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -795,7 +795,7 @@
  llvm::isa(E) ||
  llvm::isa(E) || llvm::isa(E) ||
  llvm::isa(E) || llvm::isa(E) ||
- llvm::isa(E);
+ llvm::isa(E) || llvm::isa(E);
 }
 
 llvm::StringLiteral getNameForExpr(const Expr *E) {
@@ -809,34 +809,53 @@
   return llvm::StringLiteral("expression");
 }
 
+void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI,
+   const PrintingPolicy &PP);
+
 // Generates hover info for `this` and evaluatable expressions.
 // FIXME: Support hover for literals (esp user-defined)
-std::optional getHoverContents(const Expr *E, ParsedAST &AST,
+std::optional getHoverContents(const SelectionTree::Node *N,
+  const Expr *E, ParsedAST &AST,
   const PrintingPolicy &PP,
   const SymbolIndex *Index) {
-  // There's not much value in hovering over "42" and getting a hover card
-  // saying "42 is an int", similar for other literals.
-  if (isLiteral(E))
+  std::optional HI;
+
+  if (const StringLiteral *SL = dyn_cast(E)) {
+// Print the type and the size for string literals
+HI =

[PATCH] D140915: [clangd] Fix getQueryScopes for using-directive with inline namespace

2023-01-03 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added reviewers: nridge, kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

For example, in the folliwong code

  #include 
  
  using namespace std::string_literals;
  
  int main() {
  strin^ // Completes `string` instead of `std::string`
  }

The using declaration would make completion drop the std namespace, even though 
it shouldn't.

printNamespaceScope() skips inline namespaces, so to fix this use
printQualifiedName() instead

See https://github.com/clangd/clangd/issues/1451


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D140915

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
@@ -1700,9 +1700,11 @@
   namespace ns1 {}
   namespace ns2 {} // ignore
   namespace ns3 { namespace nns3 {} }
+  namespace ns4 { inline namespace ns4_inline {} }
   namespace foo {
   using namespace ns1;
   using namespace ns3::nns3;
+  using namespace ns4::ns4_inline;
   }
   namespace ns {
   void f() {
@@ -1711,10 +1713,11 @@
   }
   )cpp");
 
-  EXPECT_THAT(Requests,
-  ElementsAre(Field(
-  &FuzzyFindRequest::Scopes,
-  UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::";
+  EXPECT_THAT(
+  Requests,
+  ElementsAre(Field(&FuzzyFindRequest::Scopes,
+UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::",
+ "ns4::ns4_inline::";
 }
 
 TEST(CompletionTest, UnresolvedQualifierIdQuery) {
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -670,8 +670,12 @@
   for (auto *Context : CCContext.getVisitedContexts()) {
 if (isa(Context))
   Scopes.AccessibleScopes.push_back(""); // global namespace
-else if (isa(Context))
-  Scopes.AccessibleScopes.push_back(printNamespaceScope(*Context));
+else if (const auto *ND = dyn_cast(Context)) {
+  if (ND->isInlineNamespace())
+Scopes.AccessibleScopes.push_back(printQualifiedName(*ND) + "::");
+  else
+Scopes.AccessibleScopes.push_back(printNamespaceScope(*ND));
+}
   }
 
   const CXXScopeSpec *SemaSpecifier =


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1700,9 +1700,11 @@
   namespace ns1 {}
   namespace ns2 {} // ignore
   namespace ns3 { namespace nns3 {} }
+  namespace ns4 { inline namespace ns4_inline {} }
   namespace foo {
   using namespace ns1;
   using namespace ns3::nns3;
+  using namespace ns4::ns4_inline;
   }
   namespace ns {
   void f() {
@@ -1711,10 +1713,11 @@
   }
   )cpp");
 
-  EXPECT_THAT(Requests,
-  ElementsAre(Field(
-  &FuzzyFindRequest::Scopes,
-  UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::";
+  EXPECT_THAT(
+  Requests,
+  ElementsAre(Field(&FuzzyFindRequest::Scopes,
+UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::",
+ "ns4::ns4_inline::";
 }
 
 TEST(CompletionTest, UnresolvedQualifierIdQuery) {
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -670,8 +670,12 @@
   for (auto *Context : CCContext.getVisitedContexts()) {
 if (isa(Context))
   Scopes.AccessibleScopes.push_back(""); // global namespace
-else if (isa(Context))
-  Scopes.AccessibleScopes.push_back(printNamespaceScope(*Context));
+else if (const auto *ND = dyn_cast(Context)) {
+  if (ND->isInlineNamespace())
+Scopes.AccessibleScopes.push_back(printQualifiedName(*ND) + "::");
+  else
+Scopes.AccessibleScopes.push_back(printNamespaceScope(*ND));
+}
   }
 
   const CXXScopeSpec *SemaSpecifier =
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D140915: [clangd] Fix getQueryScopes for using-directive with inline namespace

2023-01-04 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:674
+else if (const auto *ND = dyn_cast(Context)) {
+  if (ND->isInlineNamespace())
+Scopes.AccessibleScopes.push_back(printQualifiedName(*ND) + "::");

kadircet wrote:
> since we know that the `Context` is a `NamespaceDecl` it should be safe to 
> use `printQualifiedName` always. any reason for the extra branching here 
> (apart from minimizing the change to behaviour)? if not I think we can get 
> rid of the special casing.
Unfortunately, this fails CompletionTest.EnclosingScopeComesFirst and 
CompletionTest.NoDuplicatedQueryScopes, I think because of anonymous namespaces 
(where printNameSpaceScope would return an empty string, but 
(printQualifiedName(*ND) + "::" does not). 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140915

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


[PATCH] D140915: [clangd] Fix getQueryScopes for using-directive with inline namespace

2023-01-08 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:674
+else if (const auto *ND = dyn_cast(Context)) {
+  if (ND->isInlineNamespace())
+Scopes.AccessibleScopes.push_back(printQualifiedName(*ND) + "::");

kadircet wrote:
> tom-anders wrote:
> > kadircet wrote:
> > > since we know that the `Context` is a `NamespaceDecl` it should be safe 
> > > to use `printQualifiedName` always. any reason for the extra branching 
> > > here (apart from minimizing the change to behaviour)? if not I think we 
> > > can get rid of the special casing.
> > Unfortunately, this fails CompletionTest.EnclosingScopeComesFirst and 
> > CompletionTest.NoDuplicatedQueryScopes, I think because of anonymous 
> > namespaces (where printNameSpaceScope would return an empty string, but 
> > (printQualifiedName(*ND) + "::" does not). 
> i see. taking a closer look at this `getQueryScopes` is used for two things:
> - The scopes to query with fuzzyfind requests, hence this should use the same 
> "serialization" as symbolcollector (which only strips anon namespaces today, 
> but initially it were to strip both anon & inline namespaces. it got changed 
> inside clang without clangd tests catching it).
> - The shortening of the fully qualified name in `CodeCompletionBuilder`. Not 
> having inline namespaces spelled in the available namespaces implies getting 
> wrong qualifiers (such as the bug you're fixing).
> 
> so considering the requirements here:
> - when querying index, we actually want to hide inline namespaces (as 
> `ns::hidden::Foo` should be a viable alternative even if only `ns::` is 
> accessible). so we should actually fix `printQualifiedName` to set 
> `SuppressInlineNamespace` in printing policy to restore the old behaviour 
> (and keep using `printNamespaceScope` here).
> - inside `CodeCompletionBuilder`, we shouldn't use the same scopes we use 
> during index queries. we should use the visible namespaces while preserving 
> inline namespace information and only ignoring the anonymous namespaces.
> 
> hence can we have 2 separate scopes in `CodeCompleteFlow` instead?
> One called `QueryScopes`, which has the behavior we have today (fixing 
> printQualifiedName is a separate issues).
> Other called `AccessibleScopes`, which has accessible namespaces spelled 
> **with** inline namespaces, so that we can get proper qualification during 
> code-complete.
> 
> does that make sense?
tbh I'm a bit confused - I understand your requirements, but am not sure I 
understand your proposed solution. Can you expand a bit further? Looking at the 
code, there are already both `QueryScopes` and `AccessibleScopes` 
variables/fields in various classes, I'm not really sure at which places you 
want to make changes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140915

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


[PATCH] D136925: [clangd] Index unscoped enums inside classes for code completion

2022-11-01 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 472425.
tom-anders marked 4 inline comments as done.
tom-anders added a comment.

Add additional test, don't bump index version


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136925

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.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
@@ -27,6 +27,8 @@
 Symbol cls(llvm::StringRef Name);
 // Creates an enum symbol.
 Symbol enm(llvm::StringRef Name);
+// Creates an enum constant symbol.
+Symbol enmConstant(llvm::StringRef Name);
 // Creates a variable symbol.
 Symbol var(llvm::StringRef Name);
 // Creates a namespace symbol.
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -69,6 +69,10 @@
   return sym(Name, index::SymbolKind::Enum, "@E@\\0");
 }
 
+Symbol enmConstant(llvm::StringRef Name) {
+  return sym(Name, index::SymbolKind::EnumConstant, "@\\0");
+}
+
 Symbol var(llvm::StringRef Name) {
   return sym(Name, index::SymbolKind::Variable, "@\\0");
 }
Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1316,6 +1316,11 @@
   Black
 };
 }
+class Color3 {
+  enum {
+Blue
+  };
+};
   )";
   runSymbolCollector(Header, /*Main=*/"");
   EXPECT_THAT(Symbols,
@@ -1326,7 +1331,9 @@
   AllOf(qName("Color2"), forCodeCompletion(true)),
   AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
   AllOf(qName("ns"), forCodeCompletion(true)),
-  AllOf(qName("ns::Black"), forCodeCompletion(true;
+  AllOf(qName("ns::Black"), forCodeCompletion(true)),
+  AllOf(qName("Color3"), forCodeCompletion(true)),
+  AllOf(qName("Color3::Blue"), forCodeCompletion(true;
 }
 
 TEST_F(SymbolCollectorTest, NamelessSymbols) {
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -1,4 +1,5 @@
-//===-- CodeCompleteTests.cpp ---*- C++ -*-===//
+//===-- CodeCompleteTests.cpp ---*- C++
+//-*-===//codecom
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -2962,14 +2963,20 @@
 }
   )cpp",
   {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
-   cls("na::nb::Clangd4")},
+   cls("na::nb::Clangd4"), enmConstant("na::C::Clangd5")},
   Opts);
   EXPECT_THAT(
   Results.Completions,
-  UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1")),
-   AllOf(qualifier("ny::"), named("Clangd2")),
-   AllOf(qualifier(""), scope(""), named("Clangd3")),
-   AllOf(qualifier("nb::"), named("Clangd4";
+  UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("ny::"), named("Clangd2"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier(""), scope(""), named("Clangd3"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("nb::"), named("Clangd4"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("C::"), named("Clangd5"),
+ kind(CompletionItemKind::EnumMember;
 }
 
 TEST(CompletionTest, NoQualifierIfShadowed) {
@@ -3353,6 +3360,31 @@
 kind(CompletionItemKind::Reference;
 }
 
+TEST(CompletionTest, Enums) {
+  const char *Header(R"cpp(
+namespace ns {
+  enum Unscoped { Clangd1 };
+  class C {
+  enum Unscoped { Clangd2 };
+  };
+  enum class Scoped { Clangd3 };
+})cpp");
+  const char *Source(R"cpp(
+void bar() {
+  Clangd^
+})cpp");
+  auto Index = TestTU::withHeaderCode(

[PATCH] D137104: [clangd] Add scoped enum constants to all-scopes-completion

2022-11-01 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 472426.
tom-anders added a comment.

Rebase onto previous commit


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137104

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  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
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
   AllOf(qName("ns::Black"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -291,7 +291,7 @@
 // For index-based completion, we only consider:
 //   * symbols in namespaces or translation unit scopes (e.g. no class
 // members, no locals)
-//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * enum constants (both scoped and unscoped)
 //   * primary templates (no specializations)
 // For the other cases, we let Clang do the completion because it does not
 // need any non-local information and it will be much better at following
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -2114,9 +2114,6 @@
 };
 return false;
   };
-  auto InClassScope = [](const NamedDecl &ND) {
-return ND.getDeclContext()->getDeclKind() == Decl::CXXRecord;
-  };
   // We only complete symbol's name, which is the same as the name of the
   // *primary* template in case of template specializations.
   if (isExplicitTemplateSpecialization(&ND))
@@ -2135,8 +2132,8 @@
   // Always index enum constants, even if they're not in the top level scope:
   // when
   // --all-scopes-completion is set, we'll want to complete those as well.
-  if (const auto *EnumDecl = dyn_cast(ND.getDeclContext()))
-return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl)) && 
!EnumDecl->isScoped();
+  if (llvm::isa(ND.getDeclContext()))
+return true;
 
   return false;
 }


Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
   AllOf(qName("ns::Black"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -291,7 +291,7 @@
 // For index-based completion, we only consider:
 //   * symbols in namespaces or translation unit scopes (e.g. no class
 // members, no locals)
-//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * enum constants (both scoped and unscoped)
 //   * primary templates (no specializations)
 // For the other cases, we let Clang do the completion because it does not
 // need any non-local information and it will be much better at following
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -2114,9 +2114,6 @@
 };
 return false;
   };
-  auto InClassScope = [](const NamedDecl &ND) {
-return ND.getDeclContext()->getDeclKind() == Decl::CXXRecord;
-  };
   // We only complete symbol's name, which is the same as the name of the
   // *primary* template in case of template specializations.

[PATCH] D136925: [clangd] Index unscoped enums inside classes for code completion

2022-11-01 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp:2966
   {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
-   cls("na::nb::Clangd4")},
+   cls("na::nb::Clangd4"), enmConstant("na::C::Clangd5")},
   Opts);

nridge wrote:
> nridge wrote:
> > Hmm, I don't think this type of test actually exercises the 
> > `isIndexedForCodeCompletion()` codepath (since we're just mocking out the 
> > index contents, instead of running the actual indexer).
> > 
> > Could we use [this 
> > type](https://searchfox.org/llvm/source/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp#3341-3359)
> >  instead?
> > 
> > (Sorry, this is partly my fault for not looking more carefully at what 
> > sorts of tests are in CodeCompleteTests.cpp before my earlier comment.)
> (Indeed, this test passes even without the change to CodeComplete.cpp.)
Ah right, no problem, I didn't see that there also tests in that file that 
don't mock out the index, I added a test similar to the one you mentioned.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136925

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


[PATCH] D136925: [clangd] Index unscoped enums inside classes for code completion

2022-11-01 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 472428.
tom-anders added a comment.

Fix accidental line break in comment


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136925

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.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
@@ -27,6 +27,8 @@
 Symbol cls(llvm::StringRef Name);
 // Creates an enum symbol.
 Symbol enm(llvm::StringRef Name);
+// Creates an enum constant symbol.
+Symbol enmConstant(llvm::StringRef Name);
 // Creates a variable symbol.
 Symbol var(llvm::StringRef Name);
 // Creates a namespace symbol.
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -69,6 +69,10 @@
   return sym(Name, index::SymbolKind::Enum, "@E@\\0");
 }
 
+Symbol enmConstant(llvm::StringRef Name) {
+  return sym(Name, index::SymbolKind::EnumConstant, "@\\0");
+}
+
 Symbol var(llvm::StringRef Name) {
   return sym(Name, index::SymbolKind::Variable, "@\\0");
 }
Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1316,6 +1316,11 @@
   Black
 };
 }
+class Color3 {
+  enum {
+Blue
+  };
+};
   )";
   runSymbolCollector(Header, /*Main=*/"");
   EXPECT_THAT(Symbols,
@@ -1326,7 +1331,9 @@
   AllOf(qName("Color2"), forCodeCompletion(true)),
   AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
   AllOf(qName("ns"), forCodeCompletion(true)),
-  AllOf(qName("ns::Black"), forCodeCompletion(true;
+  AllOf(qName("ns::Black"), forCodeCompletion(true)),
+  AllOf(qName("Color3"), forCodeCompletion(true)),
+  AllOf(qName("Color3::Blue"), forCodeCompletion(true;
 }
 
 TEST_F(SymbolCollectorTest, NamelessSymbols) {
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2962,14 +2962,20 @@
 }
   )cpp",
   {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
-   cls("na::nb::Clangd4")},
+   cls("na::nb::Clangd4"), enmConstant("na::C::Clangd5")},
   Opts);
   EXPECT_THAT(
   Results.Completions,
-  UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1")),
-   AllOf(qualifier("ny::"), named("Clangd2")),
-   AllOf(qualifier(""), scope(""), named("Clangd3")),
-   AllOf(qualifier("nb::"), named("Clangd4";
+  UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("ny::"), named("Clangd2"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier(""), scope(""), named("Clangd3"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("nb::"), named("Clangd4"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("C::"), named("Clangd5"),
+ kind(CompletionItemKind::EnumMember;
 }
 
 TEST(CompletionTest, NoQualifierIfShadowed) {
@@ -3353,6 +3359,31 @@
 kind(CompletionItemKind::Reference;
 }
 
+TEST(CompletionTest, Enums) {
+  const char *Header(R"cpp(
+namespace ns {
+  enum Unscoped { Clangd1 };
+  class C {
+  enum Unscoped { Clangd2 };
+  };
+  enum class Scoped { Clangd3 };
+})cpp");
+  const char *Source(R"cpp(
+void bar() {
+  Clangd^
+})cpp");
+  auto Index = TestTU::withHeaderCode(Header).index();
+  clangd::CodeCompleteOptions Opts;
+  Opts.Index = Index.get();
+  Opts.AllScopes = true;
+  auto R = completions(Source, {}, Opts);
+  EXPECT_THAT(R.Completions,
+  ElementsAre(AllOf(scope("ns::"), named("Clangd1"),
+kind(CompletionItemKind::EnumMember)),
+  AllOf(scope("ns::C::"), named("Clangd2"),
+  

[PATCH] D136925: [clangd] Index unscoped enums inside classes for code completion

2022-11-02 Thread Tom Praschan 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 rGa68bcd81dcc9: [clangd] Index unscoped enums in class scope 
for code completion (authored by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136925

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/SymbolCollectorTests.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
@@ -27,6 +27,8 @@
 Symbol cls(llvm::StringRef Name);
 // Creates an enum symbol.
 Symbol enm(llvm::StringRef Name);
+// Creates an enum constant symbol.
+Symbol enmConstant(llvm::StringRef Name);
 // Creates a variable symbol.
 Symbol var(llvm::StringRef Name);
 // Creates a namespace symbol.
Index: clang-tools-extra/clangd/unittests/TestIndex.cpp
===
--- clang-tools-extra/clangd/unittests/TestIndex.cpp
+++ clang-tools-extra/clangd/unittests/TestIndex.cpp
@@ -69,6 +69,10 @@
   return sym(Name, index::SymbolKind::Enum, "@E@\\0");
 }
 
+Symbol enmConstant(llvm::StringRef Name) {
+  return sym(Name, index::SymbolKind::EnumConstant, "@\\0");
+}
+
 Symbol var(llvm::StringRef Name) {
   return sym(Name, index::SymbolKind::Variable, "@\\0");
 }
Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1316,6 +1316,11 @@
   Black
 };
 }
+class Color3 {
+  enum {
+Blue
+  };
+};
   )";
   runSymbolCollector(Header, /*Main=*/"");
   EXPECT_THAT(Symbols,
@@ -1326,7 +1331,9 @@
   AllOf(qName("Color2"), forCodeCompletion(true)),
   AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
   AllOf(qName("ns"), forCodeCompletion(true)),
-  AllOf(qName("ns::Black"), forCodeCompletion(true;
+  AllOf(qName("ns::Black"), forCodeCompletion(true)),
+  AllOf(qName("Color3"), forCodeCompletion(true)),
+  AllOf(qName("Color3::Blue"), forCodeCompletion(true;
 }
 
 TEST_F(SymbolCollectorTest, NamelessSymbols) {
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2967,14 +2967,20 @@
 }
   )cpp",
   {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),
-   cls("na::nb::Clangd4")},
+   cls("na::nb::Clangd4"), enmConstant("na::C::Clangd5")},
   Opts);
   EXPECT_THAT(
   Results.Completions,
-  UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1")),
-   AllOf(qualifier("ny::"), named("Clangd2")),
-   AllOf(qualifier(""), scope(""), named("Clangd3")),
-   AllOf(qualifier("nb::"), named("Clangd4";
+  UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("ny::"), named("Clangd2"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier(""), scope(""), named("Clangd3"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("nb::"), named("Clangd4"),
+ kind(CompletionItemKind::Class)),
+   AllOf(qualifier("C::"), named("Clangd5"),
+ kind(CompletionItemKind::EnumMember;
 }
 
 TEST(CompletionTest, NoQualifierIfShadowed) {
@@ -3358,6 +3364,31 @@
 kind(CompletionItemKind::Reference;
 }
 
+TEST(CompletionTest, Enums) {
+  const char *Header(R"cpp(
+namespace ns {
+  enum Unscoped { Clangd1 };
+  class C {
+  enum Unscoped { Clangd2 };
+  };
+  enum class Scoped { Clangd3 };
+})cpp");
+  const char *Source(R"cpp(
+void bar() {
+  Clangd^
+})cpp");
+  auto Index = TestTU::withHeaderCode(Header).index();
+  clangd::CodeCompleteOptions Opts;
+  Opts.Index = Index.get();
+  Opts.AllScopes = true;
+  auto R = completions(Source, {}, Opts);
+  EXPECT_THAT(R.Completions,
+  ElementsAre(AllOf(scope("ns::"), named("Clangd1"),
+

[PATCH] D136925: [clangd] Index unscoped enums inside classes for code completion

2022-11-02 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

In D136925#3901509 , @nridge wrote:

> Thanks!
>
> I don't think we need this much detail in the commit message; I think after 
> the first line it would be sufficient to say:
>
>   Fixes https://github.com/clangd/clangd/issues/1082
>   See the issue for disk/memory usage measurements
>
> (Note also that "Fixes " triggers the github issue to be closed when 
> the commit is merged.)
>
> I forget whether you have commit access -- let me know if you need me to 
> merge the patch for you.

Yep, I do have access. I adjusted the message and pushed this, but the 
corresponding Github issue is not closed automatically because I don't have the 
necessary permisions (I think we already hat that problem in another patch)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136925

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


[PATCH] D137104: [clangd] Add scoped enum constants to all-scopes-completion

2022-11-02 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 472568.
tom-anders added a comment.

Update `CompletionTest.Enums`, keep scope condition in 
isIndexedForCodeCompletion


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137104

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/unittests/CodeCompleteTests.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
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
   AllOf(qName("ns::Black"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3386,6 +3386,8 @@
   ElementsAre(AllOf(scope("ns::"), named("Clangd1"),
 kind(CompletionItemKind::EnumMember)),
   AllOf(scope("ns::C::"), named("Clangd2"),
+kind(CompletionItemKind::EnumMember)),
+  AllOf(scope("ns::C::Scoped"), named("Clangd3"),
 kind(CompletionItemKind::EnumMember;
 }
 
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -291,7 +291,7 @@
 // For index-based completion, we only consider:
 //   * symbols in namespaces or translation unit scopes (e.g. no class
 // members, no locals)
-//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * enum constants (both scoped and unscoped)
 //   * primary templates (no specializations)
 // For the other cases, we let Clang do the completion because it does not
 // need any non-local information and it will be much better at following
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -2145,7 +2145,7 @@
   // when
   // --all-scopes-completion is set, we'll want to complete those as well.
   if (const auto *EnumDecl = dyn_cast(ND.getDeclContext()))
-return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl)) && 
!EnumDecl->isScoped();
+return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl));
 
   return false;
 }


Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
   AllOf(qName("ns::Black"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3386,6 +3386,8 @@
   ElementsAre(AllOf(scope("ns::"), named("Clangd1"),
 kind(CompletionItemKind::EnumMember)),
   AllOf(scope("ns::C::"), named("Clangd2"),
+kind(CompletionItemKind::EnumMember)),
+  AllOf(scope("ns::C::Scoped"), named("Clangd3"),
 kind(CompletionItemKind::EnumMember;
 }
 
Index: clang-tools-extra/clangd/CodeComplete.h
==

[PATCH] D137104: [clangd] Add scoped enum constants to all-scopes-completion

2022-11-02 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders marked an inline comment as done.
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:2136
+  if (llvm::isa(ND.getDeclContext()))
+return true;
 

nridge wrote:
> Why remove the `(InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl))` part?
Huh, because I thought this covered all the scopes where you could declare 
enums anyway, but of course that's wrong - You can e.g. declare a 
function-local enum, which we of course don't want to index. 



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:2136
+  if (llvm::isa(ND.getDeclContext()))
+return true;
 

tom-anders wrote:
> nridge wrote:
> > Why remove the `(InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl))` 
> > part?
> Huh, because I thought this covered all the scopes where you could declare 
> enums anyway, but of course that's wrong - You can e.g. declare a 
> function-local enum, which we of course don't want to index. 
d


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137104

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


[PATCH] D137104: [clangd] Add scoped enum constants to all-scopes-completion

2022-11-02 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 472578.
tom-anders marked an inline comment as done.
tom-anders added a comment.

Actually fix test...


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137104

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/unittests/CodeCompleteTests.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
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
   AllOf(qName("ns::Black"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3382,11 +3382,13 @@
   Opts.Index = Index.get();
   Opts.AllScopes = true;
   auto R = completions(Source, {}, Opts);
-  EXPECT_THAT(R.Completions,
-  ElementsAre(AllOf(scope("ns::"), named("Clangd1"),
-kind(CompletionItemKind::EnumMember)),
-  AllOf(scope("ns::C::"), named("Clangd2"),
-kind(CompletionItemKind::EnumMember;
+  EXPECT_THAT(R.Completions, UnorderedElementsAre(
+ AllOf(scope("ns::"), named("Clangd1"),
+   kind(CompletionItemKind::EnumMember)),
+ AllOf(scope("ns::C::"), named("Clangd2"),
+   kind(CompletionItemKind::EnumMember)),
+ AllOf(scope("ns::Scoped::"), named("Clangd3"),
+   kind(CompletionItemKind::EnumMember;
 }
 
 TEST(CompletionTest, ScopeIsUnresolved) {
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -291,7 +291,7 @@
 // For index-based completion, we only consider:
 //   * symbols in namespaces or translation unit scopes (e.g. no class
 // members, no locals)
-//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * enum constants (both scoped and unscoped)
 //   * primary templates (no specializations)
 // For the other cases, we let Clang do the completion because it does not
 // need any non-local information and it will be much better at following
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -2145,7 +2145,7 @@
   // when
   // --all-scopes-completion is set, we'll want to complete those as well.
   if (const auto *EnumDecl = dyn_cast(ND.getDeclContext()))
-return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl)) && 
!EnumDecl->isScoped();
+return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl));
 
   return false;
 }


Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
   AllOf(qName("ns::Black"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3382,11 +3382,13 @@
   Opts.Index 

[PATCH] D137104: [clangd] Add scoped enum constants to all-scopes-completion

2022-11-02 Thread Tom Praschan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG990c18937967: [clangd] Add scoped enum constants to 
all-scopes-completion (authored by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137104

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/unittests/CodeCompleteTests.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
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
   AllOf(qName("ns::Black"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3382,11 +3382,13 @@
   Opts.Index = Index.get();
   Opts.AllScopes = true;
   auto R = completions(Source, {}, Opts);
-  EXPECT_THAT(R.Completions,
-  ElementsAre(AllOf(scope("ns::"), named("Clangd1"),
-kind(CompletionItemKind::EnumMember)),
-  AllOf(scope("ns::C::"), named("Clangd2"),
-kind(CompletionItemKind::EnumMember;
+  EXPECT_THAT(R.Completions, UnorderedElementsAre(
+ AllOf(scope("ns::"), named("Clangd1"),
+   kind(CompletionItemKind::EnumMember)),
+ AllOf(scope("ns::C::"), named("Clangd2"),
+   kind(CompletionItemKind::EnumMember)),
+ AllOf(scope("ns::Scoped::"), named("Clangd3"),
+   kind(CompletionItemKind::EnumMember;
 }
 
 TEST(CompletionTest, ScopeIsUnresolved) {
Index: clang-tools-extra/clangd/CodeComplete.h
===
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -291,7 +291,7 @@
 // For index-based completion, we only consider:
 //   * symbols in namespaces or translation unit scopes (e.g. no class
 // members, no locals)
-//   * enum constants in unscoped enum decl (e.g. "red" in "enum {red};")
+//   * enum constants (both scoped and unscoped)
 //   * primary templates (no specializations)
 // For the other cases, we let Clang do the completion because it does not
 // need any non-local information and it will be much better at following
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -2145,7 +2145,7 @@
   // when
   // --all-scopes-completion is set, we'll want to complete those as well.
   if (const auto *EnumDecl = dyn_cast(ND.getDeclContext()))
-return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl)) && 
!EnumDecl->isScoped();
+return (InTopLevelScope(*EnumDecl) || InClassScope(*EnumDecl));
 
   return false;
 }


Index: clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
===
--- clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1329,7 +1329,7 @@
   AllOf(qName("Color"), forCodeCompletion(true)),
   AllOf(qName("Green"), forCodeCompletion(true)),
   AllOf(qName("Color2"), forCodeCompletion(true)),
-  AllOf(qName("Color2::Yellow"), forCodeCompletion(false)),
+  AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
   AllOf(qName("ns"), forCodeCompletion(true)),
   AllOf(qName("ns::Black"), forCodeCompletion(true)),
   AllOf(qName("Color3"), forCodeCompletion(true)),
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeComplet

[PATCH] D137040: [clangd] Add heuristic for dropping snippet when completing member function pointer

2022-11-04 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

In D137040#3907497 , @nridge wrote:

> Thanks for the patch!
>
> The test looks good to me.
>
> As for the fix, I wonder if it would make sense to implement it in the Sema 
> layer rather than in clangd. For example, we could give 
> `clang::CodeCompletionResult` a new flag 
> 
>  called something like `CanBeCall`, which, for a completion result that 
> refers to a function, is set to true (by the code that creates the 
> CodeCompletionResult, in SemaCodeComplete.cpp) if the use of the function may 
> be a call, and false if it cannot.
>
> Then clangd can check this flag, and clear the snippet suffix (or even 
> better, not build it in the first place) if the value is false.
>
> I think this approach could have a couple of advantages:
>
> 1. By placing the logic into libSema, other consumers of the Sema completion 
> layer, besides clangd, could benefit from it as well. (A couple of other 
> consumers that I'm aware of are libclang 
>  and cling 
> .)
> 2. Because the logic now resides inside `Sema` itself, if we make 
> enhancements to the heuristics for computing `CanBeCall` that require 
> additional state (besides `CurContext`), we can just use them in place rather 
> than having to propagate them into places like clangd's 
> `CodeCompletionBuilder`.
>
> What do you think?

That indeed sounds like a better solution. I haven't looked much into 
SemaCodeComplete.cpp up to now, but I'll take a look and try to implement the 
heuristic over there.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137040

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


[PATCH] D137040: [clangd] Add heuristic for dropping snippet when completing member function pointer

2022-11-05 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 473408.
tom-anders added a comment.
Herald added a project: clang.

Move logic to SemaCodeComplete.cpp


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137040

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang/include/clang/Sema/CodeCompleteConsumer.h
  clang/lib/Sema/SemaCodeComplete.cpp

Index: clang/lib/Sema/SemaCodeComplete.cpp
===
--- clang/lib/Sema/SemaCodeComplete.cpp
+++ clang/lib/Sema/SemaCodeComplete.cpp
@@ -1379,6 +1379,33 @@
 OverloadSet.Add(Method, Results.size());
   }
 
+  // When completing a non-static member function (and not via
+  // dot/arrow member access) and we're not inside that class' scope,
+  // it can't be a call.
+  if (CompletionContext.getKind() == clang::CodeCompletionContext::CCC_Symbol) {
+const auto *Method = dyn_cast(R.getDeclaration());
+if (Method && !Method->isStatic()) {
+  // Find the class scope that we're currently in.
+  // We could e.g. be inside a lambda, so walk up the DeclContext until we
+  // find a CXXMethodDecl.
+  const auto *CurrentClassScope = [&]() -> const CXXRecordDecl * {
+for (DeclContext *Ctx = SemaRef.CurContext; Ctx;
+ Ctx = Ctx->getParent()) {
+  const auto *CtxMethod = llvm::dyn_cast(Ctx);
+  if (CtxMethod && !CtxMethod->getParent()->isLambda()) {
+return CtxMethod->getParent();
+  }
+}
+return nullptr;
+  }();
+
+  R.FunctionCanBeCall =
+  CurrentClassScope &&
+  (CurrentClassScope == Method->getParent() ||
+   CurrentClassScope->isDerivedFrom(Method->getParent()));
+}
+  }
+
   // Insert this result into the set of results.
   Results.push_back(R);
 
Index: clang/include/clang/Sema/CodeCompleteConsumer.h
===
--- clang/include/clang/Sema/CodeCompleteConsumer.h
+++ clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -850,6 +850,12 @@
   /// rather than a use of that entity.
   bool DeclaringEntity : 1;
 
+  /// When completing a function, whether it can be a call. This will usually be
+  /// true, but we have some heuristics, e.g. when a pointer to a non-static
+  /// member function is completed outside of that class' scope, it can never
+  /// be a call.
+  bool FunctionCanBeCall : 1;
+
   /// If the result should have a nested-name-specifier, this is it.
   /// When \c QualifierIsInformative, the nested-name-specifier is
   /// informative rather than required.
@@ -876,7 +882,7 @@
 FixIts(std::move(FixIts)), Hidden(false), InBaseClass(false),
 QualifierIsInformative(QualifierIsInformative),
 StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-DeclaringEntity(false), Qualifier(Qualifier) {
+DeclaringEntity(false), FunctionCanBeCall(true), Qualifier(Qualifier) {
 // FIXME: Add assert to check FixIts range requirements.
 computeCursorKindAndAvailability(Accessible);
   }
@@ -886,7 +892,8 @@
   : Keyword(Keyword), Priority(Priority), Kind(RK_Keyword),
 CursorKind(CXCursor_NotImplemented), Hidden(false), InBaseClass(false),
 QualifierIsInformative(false), StartsNestedNameSpecifier(false),
-AllParametersAreInformative(false), DeclaringEntity(false) {}
+AllParametersAreInformative(false), DeclaringEntity(false),
+FunctionCanBeCall(true) {}
 
   /// Build a result that refers to a macro.
   CodeCompletionResult(const IdentifierInfo *Macro,
@@ -896,7 +903,7 @@
 CursorKind(CXCursor_MacroDefinition), Hidden(false), InBaseClass(false),
 QualifierIsInformative(false), StartsNestedNameSpecifier(false),
 AllParametersAreInformative(false), DeclaringEntity(false),
-MacroDefInfo(MI) {}
+FunctionCanBeCall(true), MacroDefInfo(MI) {}
 
   /// Build a result that refers to a pattern.
   CodeCompletionResult(
@@ -908,7 +915,7 @@
 CursorKind(CursorKind), Availability(Availability), Hidden(false),
 InBaseClass(false), QualifierIsInformative(false),
 StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-DeclaringEntity(false) {}
+DeclaringEntity(false), FunctionCanBeCall(true) {}
 
   /// Build a result that refers to a pattern with an associated
   /// declaration.
@@ -917,7 +924,7 @@
   : Declaration(D), Pattern(Pattern), Priority(Priority), Kind(RK_Pattern),
 Hidden(false), InBaseClass(false), QualifierIsInformative(false),
 StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-DeclaringEntity(false) {
+DeclaringEntity(false), FunctionCanBeCall(true) {
 computeCursorKindAndAvailability();
   }
 
Index: clang-tools-extra/clangd/unittests/CodeCom

[PATCH] D137040: [clangd] Add heuristic for dropping snippet when completing member function pointer

2022-11-05 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

The test in clangd/unittests/CodeCompleteTests.cpp still passes. We now 
probably also need a unit test for Sema that tests the new flag, right?




Comment at: clang-tools-extra/clangd/CodeComplete.cpp:414
&Completion.RequiredQualifier, IsPattern);
+  if (!C.SemaResult->FunctionCanBeCall)
+S.SnippetSuffix.clear();

Here, the SnippetSuffix is still created and then immediately cleared again. 
But the logic inside getSignature is quite complex and it's used in multiple 
places, so I didn't really want to touch that function for now.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137040

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


[PATCH] D137494: [Clangd] Fix the code action `RemoveUsingNamespace`

2022-11-05 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders requested changes to this revision.
tom-anders added a comment.
This revision now requires changes to proceed.

Did a quick test on my machine, seems to work! Can you add a regression test to 
clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp though?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137494

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


[PATCH] D137494: [Clangd] Fix the code action `RemoveUsingNamespace`

2022-11-06 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders accepted this revision.
tom-anders added a comment.
This revision is now accepted and ready to land.

Thanks for the fix, LGTM! Do you want me to commit this for you?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137494

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


[PATCH] D137494: [Clangd] Fix the code action `RemoveUsingNamespace`

2022-11-06 Thread Tom Praschan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf5a2ef80fa47: [clangd] Fix the code action 
`RemoveUsingNamespace` (authored by v1nh1shungry, committed by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137494

Files:
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp


Index: clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
===
--- clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
+++ clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
@@ -226,6 +226,29 @@
   int main() {
 std::vector V;
   }
+)cpp"},
+  {// Does not qualify operators declared in a non-class context
+   R"cpp(
+  namespace ns {
+  struct Foo {};
+  void operator+(const Foo &, int) {}
+  }
+  using namespace n^s;
+  int main() {
+Foo foo;
+foo + 10;
+  }
+)cpp",
+   R"cpp(
+  namespace ns {
+  struct Foo {};
+  void operator+(const Foo &, int) {}
+  }
+  
+  int main() {
+ns::Foo foo;
+foo + 10;
+  }
 )cpp"}};
   for (auto C : Cases)
 EXPECT_EQ(C.second, apply(C.first)) << C.first;
Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -155,6 +155,13 @@
 if (!visibleContext(T->getDeclContext())
  ->Equals(TargetDirective->getNominatedNamespace()))
   return;
+// Avoid adding qualifiers before operators, e.g.
+//   using namespace std;
+//   cout << "foo"; // Must not changed to std::cout std:: << "foo"
+// FIXME: User-defined literals are not handled
+if (T->isInIdentifierNamespace(
+Decl::IdentifierNamespace::IDNS_NonMemberOperator))
+  return;
   }
   SourceLocation Loc = Ref.NameLoc;
   if (Loc.isMacroID()) {


Index: clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
===
--- clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
+++ clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
@@ -226,6 +226,29 @@
   int main() {
 std::vector V;
   }
+)cpp"},
+  {// Does not qualify operators declared in a non-class context
+   R"cpp(
+  namespace ns {
+  struct Foo {};
+  void operator+(const Foo &, int) {}
+  }
+  using namespace n^s;
+  int main() {
+Foo foo;
+foo + 10;
+  }
+)cpp",
+   R"cpp(
+  namespace ns {
+  struct Foo {};
+  void operator+(const Foo &, int) {}
+  }
+  
+  int main() {
+ns::Foo foo;
+foo + 10;
+  }
 )cpp"}};
   for (auto C : Cases)
 EXPECT_EQ(C.second, apply(C.first)) << C.first;
Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -155,6 +155,13 @@
 if (!visibleContext(T->getDeclContext())
  ->Equals(TargetDirective->getNominatedNamespace()))
   return;
+// Avoid adding qualifiers before operators, e.g.
+//   using namespace std;
+//   cout << "foo"; // Must not changed to std::cout std:: << "foo"
+// FIXME: User-defined literals are not handled
+if (T->isInIdentifierNamespace(
+Decl::IdentifierNamespace::IDNS_NonMemberOperator))
+  return;
   }
   SourceLocation Loc = Ref.NameLoc;
   if (Loc.isMacroID()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D137550: [clangd] Fix the code action `RemoveUsingNamespace`

2022-11-08 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders accepted this revision.
tom-anders added a comment.
This revision is now accepted and ready to land.

Would be cool if in the future we could instead transform something like

  using namespace std;
  int main() {
 auto t = 5ms;
  }

into

  using namespace std::chrono_literals;
  int main() {
 auto t = 5ms;
  }

But I think your fix certainly improved the behavior for now, so LGTM!




Comment at: 
clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp:253
+)cpp"},
+  {// Does qualify user-defined literals
+   R"cpp(






Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137550

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


[PATCH] D137650: [clangd] Implement hover for C++ string literals

2022-11-08 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added inline comments.



Comment at: clang-tools-extra/clangd/Hover.cpp:785
+
+  // TODO: Show string literal's contents
+  HI.Name = "String Literal";

Is it really useful to show the contents inside the Hover? You already see the 
contents of the string literal anyway, so I don't think this adds any value



Comment at: clang-tools-extra/clangd/Hover.cpp:788
+
+  // In C++ string literals have `const` qualifier, but in C it don't.
+  std::string Qualifier;

(nit)



Comment at: clang-tools-extra/clangd/Hover.cpp:814
+  } else {
+// TODO: For other languages
+return llvm::None;

Hmm so what's stopping us from adding support for C here?



Comment at: clang-tools-extra/clangd/Hover.cpp:820
+  Type.Type =
+  Qualifier + CharType + "[" + std::to_string(SL->getLength() + 1) + "]";
+  HI.Type = Type;

I think you should prefer `llvm::formatv` here


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137650

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


[PATCH] D137550: [clangd] Fix the code action `RemoveUsingNamespace`

2022-11-09 Thread Tom Praschan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG82ca918b5755: [clangd] Fix the code action 
`RemoveUsingNamespace` (authored by v1nh1shungry, committed by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137550

Files:
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp


Index: clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
===
--- clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
+++ clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
@@ -249,6 +249,21 @@
 ns::Foo foo;
 foo + 10;
   }
+)cpp"},
+  {// Does not qualify user-defined literals
+   R"cpp(
+  namespace ns {
+  long double operator "" _w(long double);
+  }
+  using namespace n^s;
+  int main() { 1.5_w; }
+)cpp",
+   R"cpp(
+  namespace ns {
+  long double operator "" _w(long double);
+  }
+  
+  int main() { 1.5_w; }
 )cpp"}};
   for (auto C : Cases)
 EXPECT_EQ(C.second, apply(C.first)) << C.first;
Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -155,12 +155,23 @@
 if (!visibleContext(T->getDeclContext())
  ->Equals(TargetDirective->getNominatedNamespace()))
   return;
+auto Kind = T->getDeclName().getNameKind();
 // Avoid adding qualifiers before operators, e.g.
 //   using namespace std;
 //   cout << "foo"; // Must not changed to std::cout std:: << "foo"
-// FIXME: User-defined literals are not handled
-if (T->isInIdentifierNamespace(
-Decl::IdentifierNamespace::IDNS_NonMemberOperator))
+if (Kind == DeclarationName::CXXOperatorName)
+  return;
+// Avoid adding qualifiers before user-defined literals, e.g.
+//   using namespace std;
+//   auto s = "foo"s; // Must not changed to auto s = "foo" std::s;
+// FIXME: Add a using-directive for user-defined literals
+// declared in an inline namespace, e.g.
+//   using namespace s^td;
+//   int main() { cout << "foo"s; }
+// change to
+//   using namespace std::literals;
+//   int main() { std::cout << "foo"s; }
+if (Kind == DeclarationName::NameKind::CXXLiteralOperatorName)
   return;
   }
   SourceLocation Loc = Ref.NameLoc;


Index: clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
===
--- clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
+++ clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp
@@ -249,6 +249,21 @@
 ns::Foo foo;
 foo + 10;
   }
+)cpp"},
+  {// Does not qualify user-defined literals
+   R"cpp(
+  namespace ns {
+  long double operator "" _w(long double);
+  }
+  using namespace n^s;
+  int main() { 1.5_w; }
+)cpp",
+   R"cpp(
+  namespace ns {
+  long double operator "" _w(long double);
+  }
+  
+  int main() { 1.5_w; }
 )cpp"}};
   for (auto C : Cases)
 EXPECT_EQ(C.second, apply(C.first)) << C.first;
Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -155,12 +155,23 @@
 if (!visibleContext(T->getDeclContext())
  ->Equals(TargetDirective->getNominatedNamespace()))
   return;
+auto Kind = T->getDeclName().getNameKind();
 // Avoid adding qualifiers before operators, e.g.
 //   using namespace std;
 //   cout << "foo"; // Must not changed to std::cout std:: << "foo"
-// FIXME: User-defined literals are not handled
-if (T->isInIdentifierNamespace(
-Decl::IdentifierNamespace::IDNS_NonMemberOperator))
+if (Kind == DeclarationName::CXXOperatorName)
+  return;
+// Avoid adding qualifiers before user-defined literals, e.g.
+//   using namespace std;
+//   auto s = "foo"s; // Must not changed to auto s = "foo" std::s;
+// FIXME: Add a using-directive for user-de

[PATCH] D137040: [clangd] Add heuristic for dropping snippet when completing member function pointer

2022-11-09 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 474358.
tom-anders added a comment.

Add test to sema


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137040

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang/include/clang/Sema/CodeCompleteConsumer.h
  clang/lib/Sema/SemaCodeComplete.cpp
  clang/unittests/Sema/CodeCompleteTest.cpp

Index: clang/unittests/Sema/CodeCompleteTest.cpp
===
--- clang/unittests/Sema/CodeCompleteTest.cpp
+++ clang/unittests/Sema/CodeCompleteTest.cpp
@@ -23,7 +23,10 @@
 
 using namespace clang;
 using namespace clang::tooling;
+using ::testing::AllOf;
+using ::testing::Contains;
 using ::testing::Each;
+using ::testing::Field;
 using ::testing::UnorderedElementsAre;
 
 const char TestCCName[] = "test.cc";
@@ -36,6 +39,48 @@
   std::string PtrDiffType;
 };
 
+struct CompletedFunctionDecl {
+  std::string Name;
+  bool IsStatic;
+  bool CanBeCall;
+};
+
+class SaveCompletedFunctions : public CodeCompleteConsumer {
+public:
+  SaveCompletedFunctions(std::vector &CompletedFuncDecls)
+  : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}),
+CompletedFuncDecls(CompletedFuncDecls),
+CCTUInfo(std::make_shared()) {}
+
+  void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
+  CodeCompletionResult *Results,
+  unsigned NumResults) override {
+for (unsigned I = 0; I < NumResults; ++I) {
+  auto R = Results[I];
+  if (R.Kind == CodeCompletionResult::RK_Declaration) {
+if (const auto *FD = llvm::dyn_cast(R.getDeclaration())) {
+  CompletedFunctionDecl D;
+  D.Name = FD->getNameAsString();
+  D.CanBeCall = R.FunctionCanBeCall;
+  D.IsStatic = FD->isStatic();
+  CompletedFuncDecls.emplace_back(std::move(D));
+}
+  }
+}
+  }
+
+private:
+  CodeCompletionAllocator &getAllocator() override {
+return CCTUInfo.getAllocator();
+  }
+
+  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
+
+  std::vector &CompletedFuncDecls;
+
+  CodeCompletionTUInfo CCTUInfo;
+};
+
 class VisitedContextFinder : public CodeCompleteConsumer {
 public:
   VisitedContextFinder(CompletionContext &ResultCtx)
@@ -74,12 +119,15 @@
 
 class CodeCompleteAction : public SyntaxOnlyAction {
 public:
-  CodeCompleteAction(ParsedSourceLocation P, CompletionContext &ResultCtx)
-  : CompletePosition(std::move(P)), ResultCtx(ResultCtx) {}
+  CodeCompleteAction(ParsedSourceLocation P, CompletionContext &ResultCtx,
+ CodeCompleteConsumer *Consumer = nullptr)
+  : CompletePosition(std::move(P)), ResultCtx(ResultCtx),
+Consumer(Consumer) {}
 
   bool BeginInvocation(CompilerInstance &CI) override {
 CI.getFrontendOpts().CodeCompletionAt = CompletePosition;
-CI.setCodeCompletionConsumer(new VisitedContextFinder(ResultCtx));
+CI.setCodeCompletionConsumer(
+Consumer ? Consumer : new VisitedContextFinder(ResultCtx));
 return true;
   }
 
@@ -87,6 +135,7 @@
   // 1-based code complete position ;
   ParsedSourceLocation CompletePosition;
   CompletionContext &ResultCtx;
+  CodeCompleteConsumer *Consumer;
 };
 
 ParsedSourceLocation offsetToPosition(llvm::StringRef Code, size_t Offset) {
@@ -129,6 +178,83 @@
   return Types;
 }
 
+std::vector
+CollectCompletedFunctions(StringRef Code, std::size_t Point) {
+  CompletionContext DummyContext;
+  std::vector Result;
+  clang::tooling::runToolOnCodeWithArgs(
+  std::make_unique(offsetToPosition(Code, Point),
+   DummyContext,
+   new SaveCompletedFunctions(Result)),
+  Code, {"-std=c++11"}, TestCCName);
+  return Result;
+}
+
+TEST(SemaCodeCompleteTest, FunctionCanBeCall) {
+  llvm::Annotations Code(R"cpp(
+struct Foo {
+  static int staticMethod();
+  int method() const;
+  Foo() {
+this->$canBeCall^
+$canBeCall^
+Foo::$canBeCall^
+  }
+};
+
+struct Derived : Foo {
+  Derived() {
+Foo::$canBeCall^
+  }
+};
+
+struct OtherClass {
+  OtherClass() {
+Foo f;
+f.$canBeCall^
+&Foo::$cannotBeCall^
+  }
+};
+
+int main() {
+  Foo f;
+  f.$canBeCall^
+  &Foo::$cannotBeCall^
+}
+)cpp");
+
+  for (const auto &P : Code.points("canBeCall")) {
+auto Results = CollectCompletedFunctions(Code.code(), P);
+EXPECT_THAT(
+Results,
+Contains(AllOf(
+Field("Name", &CompletedFunctionDecl::Name, "method"),
+Field("IsStatic", &CompletedFunctionDecl::IsStatic, false),
+Field("CanBeCall", &CompletedFunctionDecl::CanBeCall, true;
+  }
+
+  for (const auto &P : Code.points("keepSnip

  1   2   >