[PATCH] D141800: [clangd] Fix qualifier not being dropped for using declaration referring to scoped enum

2023-09-19 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

(friendly ping)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141800

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


[PATCH] D147847: [clangd] Hover: Add CalleeArgInfo for constructor expressions

2023-04-29 Thread Tom Praschan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGcb133a4629a5: [clangd] Hover: Add CalleeArgInfo for 
constructor expressions (authored by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147847

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
@@ -956,6 +956,29 @@
 HI.CalleeArgInfo->Type = "const float &";
 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
   }},
+  {
+  R"cpp(
+  struct Foo {
+explicit Foo(const float& arg) {}
+  };
+  int main() {
+int a = 0;
+Foo foo([[^a]]);
+  }
+  )cpp",
+  [](HoverInfo ) {
+HI.Name = "a";
+HI.Kind = index::SymbolKind::Variable;
+HI.NamespaceScope = "";
+HI.Definition = "int a = 0";
+HI.LocalScope = "main::";
+HI.Value = "0";
+HI.Type = "int";
+HI.CalleeArgInfo.emplace();
+HI.CalleeArgInfo->Name = "arg";
+HI.CalleeArgInfo->Type = "const float &";
+HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
+  }},
   {// Literal passed to function call
R"cpp(
   void fun(int arg_a, const int _b) {};
@@ -1342,6 +1365,7 @@
   CustomClass(const Base ) {}
   CustomClass(int ) {}
   CustomClass(float x) {}
+  CustomClass(int x, int y) {}
 };
 
 void int_by_ref(int ) {}
@@ -1388,6 +1412,11 @@
   {"base_by_ref([[^derived]]);", PassMode::Ref, false},
   {"base_by_const_ref([[^derived]]);", PassMode::ConstRef, false},
   {"base_by_value([[^derived]]);", PassMode::Value, false},
+  // Custom class constructor tests
+  {"CustomClass c1([[^base]]);", PassMode::ConstRef, false},
+  {"auto c2 = new CustomClass([[^base]]);", PassMode::ConstRef, false},
+  {"CustomClass c3([[^int_x]]);", PassMode::Ref, false},
+  {"CustomClass c3(int_x, [[^int_x]]);", PassMode::Value, false},
   // Converted tests
   {"float_by_value([[^int_x]]);", PassMode::Value, true},
   {"float_by_value([[^int_ref]]);", PassMode::Value, true},
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -981,12 +981,23 @@
   const auto  = N->outerImplicit();
   if (!OuterNode.Parent)
 return;
-  const auto *CE = OuterNode.Parent->ASTNode.get();
-  if (!CE)
+
+  const FunctionDecl *FD = nullptr;
+  llvm::ArrayRef Args;
+
+  if (const auto *CE = OuterNode.Parent->ASTNode.get()) {
+FD = CE->getDirectCallee();
+Args = {CE->getArgs(), CE->getNumArgs()};
+  } else if (const auto *CE =
+ OuterNode.Parent->ASTNode.get()) {
+FD = CE->getConstructor();
+Args = {CE->getArgs(), CE->getNumArgs()};
+  }
+  if (!FD)
 return;
-  const FunctionDecl *FD = CE->getDirectCallee();
-  // For non-function-call-like operatators (e.g. operator+, operator<<) it's
-  // not immediattely obvious what the "passed as" would refer to and, given
+
+  // For non-function-call-like operators (e.g. operator+, operator<<) it's
+  // not immediately obvious what the "passed as" would refer to and, given
   // fixed function signature, the value would be very low anyway, so we choose
   // to not support that.
   // Both variadic functions and operator() (especially relevant for lambdas)
@@ -999,8 +1010,8 @@
   auto Parameters = resolveForwardingParameters(FD);
 
   // Find argument index for N.
-  for (unsigned I = 0; I < CE->getNumArgs() && I < Parameters.size(); ++I) {
-if (CE->getArg(I) != OuterNode.ASTNode.get())
+  for (unsigned I = 0; I < Args.size() && I < Parameters.size(); ++I) {
+if (Args[I] != OuterNode.ASTNode.get())
   continue;
 
 // Extract matching argument from function declaration.


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -956,6 +956,29 @@
 HI.CalleeArgInfo->Type = "const float &";
 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
   }},
+  {
+  R"cpp(
+  struct Foo {
+explicit Foo(const float& arg) {}
+  };
+  int main() {
+int a = 0;
+Foo foo([[^a]]);
+  }
+  )cpp",
+  [](HoverInfo ) {
+HI.Name = "a";
+HI.Kind = 

[PATCH] D143112: [clang] Support parsing comments without ASTContext

2023-04-28 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

(ping) Does this make sense or are more adjustments needed?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143112

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


[PATCH] D147847: [clangd] Hover: Add CalleeArgInfo for constructor expressions

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



Comment at: clang-tools-extra/clangd/Hover.cpp:986
+  const FunctionDecl *FD = nullptr;
+  llvm::SmallVector Args;
+

nridge wrote:
> tom-anders wrote:
> > Unfortunately, while CallExpr and CXXConstructExpr basically have the same 
> > API for getting Args, they're not related by a common base class.
> > 
> > Is there a more elegant solution than temporarily storing the Args in a 
> > SmallVector here?
> You can use `ArrayRef` instead of `SmallVector` and avoid copying the 
> arguments (compare 
> [process_call](https://searchfox.org/llvm/rev/b34ca0851a5209a10c0ca285c000a18073677891/clang-tools-extra/clangd/InlayHints.cpp#239,265)
>  in `InlayHintVisitor`).
Ah perfect, thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147847

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


[PATCH] D147847: [clangd] Hover: Add CalleeArgInfo for constructor expressions

2023-04-28 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 517994.
tom-anders marked an inline comment as done.
tom-anders added a comment.

Use ArrayRef instead of SmallVector to avoid copy (also fix 2 typos in the 
comment below)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147847

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
@@ -956,6 +956,29 @@
 HI.CalleeArgInfo->Type = "const float &";
 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
   }},
+  {
+  R"cpp(
+  struct Foo {
+explicit Foo(const float& arg) {}
+  };
+  int main() {
+int a = 0;
+Foo foo([[^a]]);
+  }
+  )cpp",
+  [](HoverInfo ) {
+HI.Name = "a";
+HI.Kind = index::SymbolKind::Variable;
+HI.NamespaceScope = "";
+HI.Definition = "int a = 0";
+HI.LocalScope = "main::";
+HI.Value = "0";
+HI.Type = "int";
+HI.CalleeArgInfo.emplace();
+HI.CalleeArgInfo->Name = "arg";
+HI.CalleeArgInfo->Type = "const float &";
+HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
+  }},
   {// Literal passed to function call
R"cpp(
   void fun(int arg_a, const int _b) {};
@@ -1342,6 +1365,7 @@
   CustomClass(const Base ) {}
   CustomClass(int ) {}
   CustomClass(float x) {}
+  CustomClass(int x, int y) {}
 };
 
 void int_by_ref(int ) {}
@@ -1388,6 +1412,11 @@
   {"base_by_ref([[^derived]]);", PassMode::Ref, false},
   {"base_by_const_ref([[^derived]]);", PassMode::ConstRef, false},
   {"base_by_value([[^derived]]);", PassMode::Value, false},
+  // Custom class constructor tests
+  {"CustomClass c1([[^base]]);", PassMode::ConstRef, false},
+  {"auto c2 = new CustomClass([[^base]]);", PassMode::ConstRef, false},
+  {"CustomClass c3([[^int_x]]);", PassMode::Ref, false},
+  {"CustomClass c3(int_x, [[^int_x]]);", PassMode::Value, false},
   // Converted tests
   {"float_by_value([[^int_x]]);", PassMode::Value, true},
   {"float_by_value([[^int_ref]]);", PassMode::Value, true},
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -981,12 +981,23 @@
   const auto  = N->outerImplicit();
   if (!OuterNode.Parent)
 return;
-  const auto *CE = OuterNode.Parent->ASTNode.get();
-  if (!CE)
+
+  const FunctionDecl *FD = nullptr;
+  llvm::ArrayRef Args;
+
+  if (const auto *CE = OuterNode.Parent->ASTNode.get()) {
+FD = CE->getDirectCallee();
+Args = {CE->getArgs(), CE->getNumArgs()};
+  } else if (const auto *CE =
+ OuterNode.Parent->ASTNode.get()) {
+FD = CE->getConstructor();
+Args = {CE->getArgs(), CE->getNumArgs()};
+  }
+  if (!FD)
 return;
-  const FunctionDecl *FD = CE->getDirectCallee();
-  // For non-function-call-like operatators (e.g. operator+, operator<<) it's
-  // not immediattely obvious what the "passed as" would refer to and, given
+
+  // For non-function-call-like operators (e.g. operator+, operator<<) it's
+  // not immediately obvious what the "passed as" would refer to and, given
   // fixed function signature, the value would be very low anyway, so we choose
   // to not support that.
   // Both variadic functions and operator() (especially relevant for lambdas)
@@ -999,8 +1010,8 @@
   auto Parameters = resolveForwardingParameters(FD);
 
   // Find argument index for N.
-  for (unsigned I = 0; I < CE->getNumArgs() && I < Parameters.size(); ++I) {
-if (CE->getArg(I) != OuterNode.ASTNode.get())
+  for (unsigned I = 0; I < Args.size() && I < Parameters.size(); ++I) {
+if (Args[I] != OuterNode.ASTNode.get())
   continue;
 
 // Extract matching argument from function declaration.


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -956,6 +956,29 @@
 HI.CalleeArgInfo->Type = "const float &";
 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
   }},
+  {
+  R"cpp(
+  struct Foo {
+explicit Foo(const float& arg) {}
+  };
+  int main() {
+int a = 0;
+Foo foo([[^a]]);
+  }
+  )cpp",
+  [](HoverInfo ) {
+HI.Name = "a";
+HI.Kind = 

[PATCH] D147846: [clangd] Hover: resolve forwarding parameters for CalleeArgInfo

2023-04-28 Thread Tom Praschan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa7b4fd953f44: [clangd] Hover: resolve forwarding parameters 
for CalleeArgInfo (authored by tom-anders).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147846

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
@@ -906,6 +906,35 @@
  HI.CalleeArgInfo->Type = "int &";
  HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};
}},
+  {// make_unique-like function call
+   R"cpp(
+  struct Foo {
+explicit Foo(int arg_a) {}
+  };
+  template
+  T make(Args&&... args)
+  {
+  return T(args...);
+  }
+
+  void code() {
+int a = 1;
+auto foo = make([[^a]]);
+  }
+  )cpp",
+   [](HoverInfo ) {
+ HI.Name = "a";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.Definition = "int a = 1";
+ HI.LocalScope = "code::";
+ HI.Value = "1";
+ HI.Type = "int";
+ HI.CalleeArgInfo.emplace();
+ HI.CalleeArgInfo->Name = "arg_a";
+ HI.CalleeArgInfo->Type = "int";
+ HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};
+   }},
   {
   R"cpp(
   void foobar(const float );
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -996,13 +996,15 @@
 
   HoverInfo::PassType PassType;
 
+  auto Parameters = resolveForwardingParameters(FD);
+
   // Find argument index for N.
-  for (unsigned I = 0; I < CE->getNumArgs() && I < FD->getNumParams(); ++I) {
+  for (unsigned I = 0; I < CE->getNumArgs() && I < Parameters.size(); ++I) {
 if (CE->getArg(I) != OuterNode.ASTNode.get())
   continue;
 
 // Extract matching argument from function declaration.
-if (const ParmVarDecl *PVD = FD->getParamDecl(I)) {
+if (const ParmVarDecl *PVD = Parameters[I]) {
   HI.CalleeArgInfo.emplace(toHoverInfoParam(PVD, PP));
   if (N == )
 PassType.PassBy = getPassMode(PVD->getType());


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -906,6 +906,35 @@
  HI.CalleeArgInfo->Type = "int &";
  HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};
}},
+  {// make_unique-like function call
+   R"cpp(
+  struct Foo {
+explicit Foo(int arg_a) {}
+  };
+  template
+  T make(Args&&... args)
+  {
+  return T(args...);
+  }
+
+  void code() {
+int a = 1;
+auto foo = make([[^a]]);
+  }
+  )cpp",
+   [](HoverInfo ) {
+ HI.Name = "a";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.Definition = "int a = 1";
+ HI.LocalScope = "code::";
+ HI.Value = "1";
+ HI.Type = "int";
+ HI.CalleeArgInfo.emplace();
+ HI.CalleeArgInfo->Name = "arg_a";
+ HI.CalleeArgInfo->Type = "int";
+ HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};
+   }},
   {
   R"cpp(
   void foobar(const float );
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -996,13 +996,15 @@
 
   HoverInfo::PassType PassType;
 
+  auto Parameters = resolveForwardingParameters(FD);
+
   // Find argument index for N.
-  for (unsigned I = 0; I < CE->getNumArgs() && I < FD->getNumParams(); ++I) {
+  for (unsigned I = 0; I < CE->getNumArgs() && I < Parameters.size(); ++I) {
 if (CE->getArg(I) != OuterNode.ASTNode.get())
   continue;
 
 // Extract matching argument from function declaration.
-if (const ParmVarDecl *PVD = FD->getParamDecl(I)) {
+if (const ParmVarDecl *PVD = Parameters[I]) {
   HI.CalleeArgInfo.emplace(toHoverInfoParam(PVD, PP));
   if (N == )
 PassType.PassBy = getPassMode(PVD->getType());
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D147847: [clangd] Hover: Add CalleeArgInfo for constructor expressions

2023-04-08 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

(Note that this diff is stacked on D147846 )


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147847

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


[PATCH] D147847: [clangd] Hover: Add CalleeArgInfo for constructor expressions

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



Comment at: clang-tools-extra/clangd/Hover.cpp:986
+  const FunctionDecl *FD = nullptr;
+  llvm::SmallVector Args;
+

Unfortunately, while CallExpr and CXXConstructExpr basically have the same API 
for getting Args, they're not related by a common base class.

Is there a more elegant solution than temporarily storing the Args in a 
SmallVector here?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147847

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


[PATCH] D147847: [clangd] Hover: Add CalleeArgInfo for constructor expressions

2023-04-08 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.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D147847

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
@@ -956,6 +956,29 @@
 HI.CalleeArgInfo->Type = "const float &";
 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
   }},
+  {
+  R"cpp(
+  struct Foo {
+explicit Foo(const float& arg) {}
+  };
+  int main() {
+int a = 0;
+Foo foo([[^a]]);
+  }
+  )cpp",
+  [](HoverInfo ) {
+HI.Name = "a";
+HI.Kind = index::SymbolKind::Variable;
+HI.NamespaceScope = "";
+HI.Definition = "int a = 0";
+HI.LocalScope = "main::";
+HI.Value = "0";
+HI.Type = "int";
+HI.CalleeArgInfo.emplace();
+HI.CalleeArgInfo->Name = "arg";
+HI.CalleeArgInfo->Type = "const float &";
+HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
+  }},
   {// Literal passed to function call
R"cpp(
   void fun(int arg_a, const int _b) {};
@@ -1342,6 +1365,7 @@
   CustomClass(const Base ) {}
   CustomClass(int ) {}
   CustomClass(float x) {}
+  CustomClass(int x, int y) {}
 };
 
 void int_by_ref(int ) {}
@@ -1388,6 +1412,11 @@
   {"base_by_ref([[^derived]]);", PassMode::Ref, false},
   {"base_by_const_ref([[^derived]]);", PassMode::ConstRef, false},
   {"base_by_value([[^derived]]);", PassMode::Value, false},
+  // Custom class constructor tests
+  {"CustomClass c1([[^base]]);", PassMode::ConstRef, false},
+  {"auto c2 = new CustomClass([[^base]]);", PassMode::ConstRef, false},
+  {"CustomClass c3([[^int_x]]);", PassMode::Ref, false},
+  {"CustomClass c3(int_x, [[^int_x]]);", PassMode::Value, false},
   // Converted tests
   {"float_by_value([[^int_x]]);", PassMode::Value, true},
   {"float_by_value([[^int_ref]]);", PassMode::Value, true},
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -981,10 +981,21 @@
   const auto  = N->outerImplicit();
   if (!OuterNode.Parent)
 return;
-  const auto *CE = OuterNode.Parent->ASTNode.get();
-  if (!CE)
+
+  const FunctionDecl *FD = nullptr;
+  llvm::SmallVector Args;
+
+  if (const auto *CE = OuterNode.Parent->ASTNode.get()) {
+FD = CE->getDirectCallee();
+Args = {CE->arg_begin(), CE->arg_end()};
+  } else if (const auto *CE =
+ OuterNode.Parent->ASTNode.get()) {
+FD = CE->getConstructor();
+Args = {CE->arg_begin(), CE->arg_end()};
+  }
+  if (!FD)
 return;
-  const FunctionDecl *FD = CE->getDirectCallee();
+
   // For non-function-call-like operatators (e.g. operator+, operator<<) it's
   // not immediattely obvious what the "passed as" would refer to and, given
   // fixed function signature, the value would be very low anyway, so we choose
@@ -999,8 +1010,8 @@
   auto Parameters = resolveForwardingParameters(FD);
 
   // Find argument index for N.
-  for (unsigned I = 0; I < CE->getNumArgs() && I < Parameters.size(); ++I) {
-if (CE->getArg(I) != OuterNode.ASTNode.get())
+  for (unsigned I = 0; I < Args.size() && I < Parameters.size(); ++I) {
+if (Args[I] != OuterNode.ASTNode.get())
   continue;
 
 // Extract matching argument from function declaration.


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -956,6 +956,29 @@
 HI.CalleeArgInfo->Type = "const float &";
 HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
   }},
+  {
+  R"cpp(
+  struct Foo {
+explicit Foo(const float& arg) {}
+  };
+  int main() {
+int a = 0;
+Foo foo([[^a]]);
+  }
+  )cpp",
+  [](HoverInfo ) {
+HI.Name = "a";
+HI.Kind = index::SymbolKind::Variable;
+HI.NamespaceScope = "";
+HI.Definition = "int a = 0";
+HI.LocalScope = "main::";
+HI.Value = "0";
+HI.Type = "int";
+

[PATCH] D147846: [clangd] Hover: resolve forwarding parameters for CalleeArgInfo

2023-04-08 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added reviewers: nridge, upsj.
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 uses the logic added in D124690 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D147846

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
@@ -906,6 +906,35 @@
  HI.CalleeArgInfo->Type = "int &";
  HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};
}},
+  {// make_unique-like function call
+   R"cpp(
+  struct Foo {
+explicit Foo(int arg_a) {}
+  };
+  template
+  T make(Args&&... args)
+  {
+  return T(args...);
+  }
+
+  void code() {
+int a = 1;
+auto foo = make([[^a]]);
+  }
+  )cpp",
+   [](HoverInfo ) {
+ HI.Name = "a";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.Definition = "int a = 1";
+ HI.LocalScope = "code::";
+ HI.Value = "1";
+ HI.Type = "int";
+ HI.CalleeArgInfo.emplace();
+ HI.CalleeArgInfo->Name = "arg_a";
+ HI.CalleeArgInfo->Type = "int";
+ HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};
+   }},
   {
   R"cpp(
   void foobar(const float );
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -996,13 +996,15 @@
 
   HoverInfo::PassType PassType;
 
+  auto Parameters = resolveForwardingParameters(FD);
+
   // Find argument index for N.
-  for (unsigned I = 0; I < CE->getNumArgs() && I < FD->getNumParams(); ++I) {
+  for (unsigned I = 0; I < CE->getNumArgs() && I < Parameters.size(); ++I) {
 if (CE->getArg(I) != OuterNode.ASTNode.get())
   continue;
 
 // Extract matching argument from function declaration.
-if (const ParmVarDecl *PVD = FD->getParamDecl(I)) {
+if (const ParmVarDecl *PVD = Parameters[I]) {
   HI.CalleeArgInfo.emplace(toHoverInfoParam(PVD, PP));
   if (N == )
 PassType.PassBy = getPassMode(PVD->getType());


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -906,6 +906,35 @@
  HI.CalleeArgInfo->Type = "int &";
  HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};
}},
+  {// make_unique-like function call
+   R"cpp(
+  struct Foo {
+explicit Foo(int arg_a) {}
+  };
+  template
+  T make(Args&&... args)
+  {
+  return T(args...);
+  }
+
+  void code() {
+int a = 1;
+auto foo = make([[^a]]);
+  }
+  )cpp",
+   [](HoverInfo ) {
+ HI.Name = "a";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.Definition = "int a = 1";
+ HI.LocalScope = "code::";
+ HI.Value = "1";
+ HI.Type = "int";
+ HI.CalleeArgInfo.emplace();
+ HI.CalleeArgInfo->Name = "arg_a";
+ HI.CalleeArgInfo->Type = "int";
+ HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};
+   }},
   {
   R"cpp(
   void foobar(const float );
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -996,13 +996,15 @@
 
   HoverInfo::PassType PassType;
 
+  auto Parameters = resolveForwardingParameters(FD);
+
   // Find argument index for N.
-  for (unsigned I = 0; I < CE->getNumArgs() && I < FD->getNumParams(); ++I) {
+  for (unsigned I = 0; I < CE->getNumArgs() && I < Parameters.size(); ++I) {
 if (CE->getArg(I) != OuterNode.ASTNode.get())
   continue;
 
 // Extract matching argument from function declaration.
-if (const ParmVarDecl *PVD = FD->getParamDecl(I)) {
+if (const ParmVarDecl *PVD = Parameters[I]) {
   HI.CalleeArgInfo.emplace(toHoverInfoParam(PVD, PP));
   if (N == )
 PassType.PassBy = getPassMode(PVD->getType());
___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[PATCH] D143112: [clang] Support parsing comments without ASTContext

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



Comment at: clang/lib/AST/RawCommentList.cpp:227
+  
SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()),
+  Allocator, SourceMgr.getDiagnostics(), Traits);
+}

kadircet wrote:
> tom-anders wrote:
> > I wasn't sure if it's worth making the `Diagnostics` parameter optional 
> > here - Our `SourceMgr` already has it anyway, does it impact performance 
> > significantly to use it, even though we don't need it (yet)?
> as things stand, Lexer, Sema and Parser expect a non-null diagnosticsengine 
> so we have to pass something (i guess that's what you meant by making it 
> optional).
> 
> the performance implications comes from two places:
> 1- extra analysis being performed in the face of malformed comments to 
> produce "useful" diagnostics
> 2- creation cost of diagnostic itself, as all the data about ranges, decls 
> etc. are copied around when constructing a diagnostic.
> 
> i don't know how costly the first action is today, it's unfortunately the 
> case that would require a lot of code changes, if it's happening quite often 
> in practice (especially when we're in codebases without proper doxygen 
> comments)
> the latter is somewhat easier to address by providing our own "mock" 
> diagnostics engine, that'll just drop all of these extra diagnostic data on 
> the floor instead of copying around.
> 
> i think taking a look at the codebase for the first (searching for `Diag(...) 
> <<` patterns in Comment{Lexer,Sema,Parser}.cpp should give some ideas) and 
> assessing whether we're performing any extra complicated analysis would be a 
> good start. i would expect us not to, and if that's the case i think we can 
> leave it at that and don't try to make code changes.
> the latter we can address easily and we should.
1 - At first glance it indeed seems like there's no significant extra analysis 
performed, so I think we're good for now.
2 - I think this is already taken care of by `SourceManagerForFile` which just 
passes `nullptr` as the `DiagnosticConsumer`, right?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143112

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


[PATCH] D143112: [clang] Support parsing comments without ASTContext

2023-02-18 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 498586.
tom-anders added a comment.
Herald added a subscriber: arphaman.
Herald added a project: clang-tools-extra.

- Move to free function in CodeCompletionStrings.h
- Add back comment markers before parsing (Index stores comments without 
markers, but the comment lexer expects them)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143112

Files:
  clang-tools-extra/clangd/CodeCompletionStrings.cpp
  clang-tools-extra/clangd/CodeCompletionStrings.h
  clang/include/clang/Basic/SourceManager.h


Index: clang/include/clang/Basic/SourceManager.h
===
--- clang/include/clang/Basic/SourceManager.h
+++ clang/include/clang/Basic/SourceManager.h
@@ -1944,7 +1944,7 @@
 };
 
 /// SourceManager and necessary dependencies (e.g. VFS, FileManager) for a
-/// single in-memorty file.
+/// single in-memory file.
 class SourceManagerForFile {
 public:
   /// Creates SourceManager and necessary dependencies (e.g. VFS, FileManager).
Index: clang-tools-extra/clangd/CodeCompletionStrings.h
===
--- clang-tools-extra/clangd/CodeCompletionStrings.h
+++ clang-tools-extra/clangd/CodeCompletionStrings.h
@@ -19,6 +19,11 @@
 namespace clang {
 class ASTContext;
 
+namespace comments {
+class CommandTraits;
+class FullComment;
+} // namespace comments
+
 namespace clangd {
 
 /// Gets a minimally formatted documentation comment of \p Result, with comment
@@ -61,6 +66,12 @@
 /// is usually the return type of a function.
 std::string getReturnType(const CodeCompletionString );
 
+/// Parse the \p Comment, storing the result in \p Allocator, assuming
+/// that comment markers have already been stripped (e.g. via getDocComment())
+comments::FullComment *parseComment(llvm::StringRef Comment,
+llvm::BumpPtrAllocator ,
+comments::CommandTraits );
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/CodeCompletionStrings.cpp
===
--- clang-tools-extra/clangd/CodeCompletionStrings.cpp
+++ clang-tools-extra/clangd/CodeCompletionStrings.cpp
@@ -8,6 +8,9 @@
 
 #include "CodeCompletionStrings.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/CommentLexer.h"
+#include "clang/AST/CommentParser.h"
+#include "clang/AST/CommentSema.h"
 #include "clang/AST/RawCommentList.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
@@ -279,5 +282,26 @@
   return "";
 }
 
+comments::FullComment *parseComment(llvm::StringRef Comment,
+llvm::BumpPtrAllocator ,
+comments::CommandTraits ) {
+  // The comment lexer expects markers, so add them back
+  auto CommentWithMarkers = "/*" + Comment.str() + "*/";
+
+  SourceManagerForFile SourceMgrForFile("mock_file.cpp", CommentWithMarkers);
+  SourceManager  = SourceMgrForFile.get();
+
+  comments::Lexer L(Allocator, SourceMgr.getDiagnostics(), Traits,
+SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()),
+CommentWithMarkers.data(),
+CommentWithMarkers.data() + CommentWithMarkers.size());
+  comments::Sema S(Allocator, SourceMgr, SourceMgr.getDiagnostics(), Traits,
+   nullptr);
+  comments::Parser P(L, S, Allocator, SourceMgr, SourceMgr.getDiagnostics(),
+ Traits);
+
+  return P.parseFullComment();
+}
+
 } // namespace clangd
 } // namespace clang


Index: clang/include/clang/Basic/SourceManager.h
===
--- clang/include/clang/Basic/SourceManager.h
+++ clang/include/clang/Basic/SourceManager.h
@@ -1944,7 +1944,7 @@
 };
 
 /// SourceManager and necessary dependencies (e.g. VFS, FileManager) for a
-/// single in-memorty file.
+/// single in-memory file.
 class SourceManagerForFile {
 public:
   /// Creates SourceManager and necessary dependencies (e.g. VFS, FileManager).
Index: clang-tools-extra/clangd/CodeCompletionStrings.h
===
--- clang-tools-extra/clangd/CodeCompletionStrings.h
+++ clang-tools-extra/clangd/CodeCompletionStrings.h
@@ -19,6 +19,11 @@
 namespace clang {
 class ASTContext;
 
+namespace comments {
+class CommandTraits;
+class FullComment;
+} // namespace comments
+
 namespace clangd {
 
 /// Gets a minimally formatted documentation comment of \p Result, with comment
@@ -61,6 +66,12 @@
 /// is usually the return type of a function.
 std::string getReturnType(const CodeCompletionString );
 
+/// Parse the \p Comment, storing the result in \p Allocator, assuming
+/// that comment markers have already been stripped (e.g. via getDocComment())
+comments::FullComment 

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

2023-02-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 rGce87b0314370: [clangd] Fix getQueryScopes for 
using-directive with inline namespace (authored by tom-anders).

Changed prior to commit:
  https://reviews.llvm.org/D140915?vs=494074=496182#toc

Repository:
  rG LLVM Github Monorepo

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

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
@@ -465,6 +465,18 @@
   Not(Contains(AllOf(qualifier(""), named("foo");
 }
 
+// https://github.com/clangd/clangd/issues/1451
+TEST(CompletionTest, QualificationWithInlineNamespace) {
+  auto Results = completions(R"cpp(
+namespace a { inline namespace b {} }
+using namespace a::b;
+void f() { Foo^ }
+  )cpp",
+ {cls("a::Foo")});
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(AllOf(qualifier("a::"), named("Foo";
+}
+
 TEST(CompletionTest, InjectedTypename) {
   // These are suppressed when accessed as a member...
   EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -313,7 +313,7 @@
 struct CodeCompletionBuilder {
   CodeCompletionBuilder(ASTContext *ASTCtx, const CompletionCandidate ,
 CodeCompletionString *SemaCCS,
-llvm::ArrayRef QueryScopes,
+llvm::ArrayRef AccessibleScopes,
 const IncludeInserter ,
 llvm::StringRef FileName,
 CodeCompletionContext::Kind ContextKind,
@@ -367,7 +367,7 @@
   // avoids unneeded qualifiers in cases like with `using ns::X`.
   if (Completion.RequiredQualifier.empty() && !C.SemaResult) {
 llvm::StringRef ShortestQualifier = C.IndexResult->Scope;
-for (llvm::StringRef Scope : QueryScopes) {
+for (llvm::StringRef Scope : AccessibleScopes) {
   llvm::StringRef Qualifier = C.IndexResult->Scope;
   if (Qualifier.consume_front(Scope) &&
   Qualifier.size() < ShortestQualifier.size())
@@ -646,40 +646,70 @@
   //
   // Examples of unqualified completion:
   //
-  //   "vec^"   => {""}
-  //   "using namespace std; vec^"  => {"", "std::"}
-  //   "using namespace std; namespace ns { vec^ }" => {"ns::", "std::", ""}
+  //   "vec^"=> {""}
+  //   "using namespace std; vec^"   => {"", "std::"}
+  //   "namespace ns {inline namespace ni { struct Foo {}}}
+  //using namespace ns::ni; Fo^ "=> {"", "ns::ni::"}
+  //   "using namespace std; namespace ns { vec^ }"  => {"ns::", "std::", ""}
   //
   // "" for global namespace, "ns::" for normal namespace.
   std::vector AccessibleScopes;
+  // This is an overestimate of AccessibleScopes, e.g. it ignores inline
+  // namespaces, to fetch more relevant symbols from index.
+  std::vector QueryScopes;
   // The full scope qualifier as typed by the user (without the leading "::").
   // Set if the qualifier is not fully resolved by Sema.
   std::optional UnresolvedQualifier;
 
-  // Construct scopes being queried in indexes. The results are deduplicated.
-  // This method format the scopes to match the index request representation.
-  std::vector scopesForIndexQuery() {
+  std::optional EnclosingNamespace;
+
+  bool AllowAllScopes = false;
+
+  // Scopes that are accessible from current context. Used for dropping
+  // unnecessary namespecifiers.
+  std::vector scopesForQualification() {
 std::set Results;
 for (llvm::StringRef AS : AccessibleScopes)
   Results.insert(
   (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
 return {Results.begin(), Results.end()};
   }
+
+  // Construct scopes being queried in indexes. The results are deduplicated.
+  // This method formats the scopes to match the index request representation.
+  std::vector scopesForIndexQuery() {
+// The enclosing namespace must be first, it gets a quality boost.
+std::vector EnclosingAtFront;
+if (EnclosingNamespace.has_value())
+  EnclosingAtFront.push_back(*EnclosingNamespace);
+std::set Deduplicated;
+for (llvm::StringRef S : QueryScopes)
+  if (S != EnclosingNamespace)
+Deduplicated.insert((S + 

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

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

Thanks for reviewing!


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] D142014: [clangd] fix wrong CalleeArgInfo in the hover

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

In D142014#4106088 , @v1nh1shungry 
wrote:

> Thanks for the review! @kadircet
>
> Would you mind having a look at if there're any concerns about the current 
> code change, @nridge, @tom-anders, and @adamcz? Thanks a lot!

Nothing more from my side!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D142014

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


[PATCH] D143112: [clang] Support parsing comments without ASTContext

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



Comment at: clang/include/clang/AST/RawCommentList.h:159
+  /// Parse the \p Comment, storing the result in \p Allocator
+  static comments::FullComment *parse(llvm::StringRef Comment,
+  llvm::BumpPtrAllocator ,

Not sure if this is the right place for this? Could be moved to `FullComment` 
or made a free function instead?



Comment at: clang/lib/AST/RawCommentList.cpp:227
+  
SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()),
+  Allocator, SourceMgr.getDiagnostics(), Traits);
+}

I wasn't sure if it's worth making the `Diagnostics` parameter optional here - 
Our `SourceMgr` already has it anyway, does it impact performance significantly 
to use it, even though we don't need it (yet)?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143112

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


[PATCH] D143112: [clang] Support parsing comments without ASTContext

2023-02-01 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders created this revision.
tom-anders added a reviewer: kadircet.
Herald added a project: All.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
Herald added a project: clang.

This is in preparation for implementing doxygen parsing, see discussion in 
https://github.com/clangd/clangd/issues/529.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D143112

Files:
  clang/include/clang/AST/RawCommentList.h
  clang/include/clang/Basic/SourceManager.h
  clang/lib/AST/RawCommentList.cpp
  clang/unittests/AST/CommentParser.cpp

Index: clang/unittests/AST/CommentParser.cpp
===
--- clang/unittests/AST/CommentParser.cpp
+++ clang/unittests/AST/CommentParser.cpp
@@ -6,11 +6,8 @@
 //
 //===--===//
 
-#include "clang/AST/CommentParser.h"
 #include "clang/AST/Comment.h"
-#include "clang/AST/CommentCommandTraits.h"
-#include "clang/AST/CommentLexer.h"
-#include "clang/AST/CommentSema.h"
+#include "clang/AST/RawCommentList.h"
 #include "clang/Basic/CommentOptions.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
@@ -28,52 +25,17 @@
 
 namespace {
 
-const bool MY_DEBUG = true;
-
 class CommentParserTest : public ::testing::Test {
 protected:
-  CommentParserTest()
-: FileMgr(FileMgrOpts),
-  DiagID(new DiagnosticIDs()),
-  Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
-  SourceMgr(Diags, FileMgr),
-  Traits(Allocator, CommentOptions()) {
-  }
+  CommentParserTest() : Traits(Allocator, CommentOptions()) {}
 
-  FileSystemOptions FileMgrOpts;
-  FileManager FileMgr;
-  IntrusiveRefCntPtr DiagID;
-  DiagnosticsEngine Diags;
-  SourceManager SourceMgr;
   llvm::BumpPtrAllocator Allocator;
   CommandTraits Traits;
 
-  FullComment *parseString(const char *Source);
-};
-
-FullComment *CommentParserTest::parseString(const char *Source) {
-  std::unique_ptr Buf = MemoryBuffer::getMemBuffer(Source);
-  FileID File = SourceMgr.createFileID(std::move(Buf));
-  SourceLocation Begin = SourceMgr.getLocForStartOfFile(File);
-
-  Lexer L(Allocator, Diags, Traits, Begin, Source, Source + strlen(Source));
-
-  Sema S(Allocator, SourceMgr, Diags, Traits, /*PP=*/ nullptr);
-  Parser P(L, S, Allocator, SourceMgr, Diags, Traits);
-  FullComment *FC = P.parseFullComment();
-
-  if (MY_DEBUG) {
-llvm::errs() << "=== Source:\n" << Source << "\n=== AST:\n";
-FC->dump();
+  FullComment *parseString(const char *Source) {
+return RawComment::parse(Source, Allocator, Traits);
   }
-
-  Token Tok;
-  L.lex(Tok);
-  if (Tok.is(tok::eof))
-return FC;
-  else
-return nullptr;
-}
+};
 
 ::testing::AssertionResult HasChildCount(const Comment *C, size_t Count) {
   if (!C)
Index: clang/lib/AST/RawCommentList.cpp
===
--- clang/lib/AST/RawCommentList.cpp
+++ clang/lib/AST/RawCommentList.cpp
@@ -201,26 +201,41 @@
   return BriefTextPtr;
 }
 
+namespace {
+comments::FullComment *
+parseComment(llvm::StringRef Comment, const SourceManager ,
+ SourceLocation FileLoc, llvm::BumpPtrAllocator ,
+ DiagnosticsEngine , comments::CommandTraits ,
+ const Preprocessor *PP = nullptr, const Decl *D = nullptr) {
+  comments::Lexer L(Allocator, Diagnostics, Traits, FileLoc, Comment.begin(),
+Comment.end());
+  comments::Sema S(Allocator, SourceManager, Diagnostics, Traits, PP);
+  S.setDecl(D);
+  comments::Parser P(L, S, Allocator, SourceManager, Diagnostics, Traits);
+
+  return P.parseFullComment();
+}
+} // namespace
+
+comments::FullComment *RawComment::parse(llvm::StringRef Comment,
+ llvm::BumpPtrAllocator ,
+ comments::CommandTraits ) {
+  SourceManagerForFile SourceMgrForFile("mock_file.cpp", Comment);
+  SourceManager  = SourceMgrForFile.get();
+  return parseComment(Comment, SourceMgr,
+  SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()),
+  Allocator, SourceMgr.getDiagnostics(), Traits);
+}
+
 comments::FullComment *RawComment::parse(const ASTContext ,
  const Preprocessor *PP,
  const Decl *D) const {
   // Lazily initialize RawText using the accessor before using it.
   (void)getRawText(Context.getSourceManager());
-
-  comments::Lexer L(Context.getAllocator(), Context.getDiagnostics(),
-Context.getCommentCommandTraits(),
-getSourceRange().getBegin(),
-RawText.begin(), RawText.end());
-  comments::Sema S(Context.getAllocator(), Context.getSourceManager(),
-   Context.getDiagnostics(),
-   Context.getCommentCommandTraits(),
-   PP);
-  

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

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



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1709
+
+// The enclosing namespace must be first, it gets a quality boost.
+if (auto Enclosing = SpecifiedScopes.EnclosingNamespace) {

kadircet wrote:
> i was actually suggesting to put this logic inside 
> `SpecifiedScope::scopesForIndexQuery` any reason for only including it in 
> this code path?
Ah I just misunderstood, moved the logic to `scopesForIndexQuery` now.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1719
+  });
+llvm::copy_if(SpecifiedScopes.scopesForQualification(),
+  std::back_inserter(AccessibleScopes),

kadircet wrote:
> `AccessibleScopes` doesn't need any particular ordering. we can use 
> `scopesForQualification` as-is.
Might as well just make it a std::set instead of std::vector? 


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-02-01 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 494074.
tom-anders marked 4 inline comments as done.
tom-anders added a comment.

Move EnclosingNamespace logic to scopesForIndexQuery, add FIXME


Repository:
  rG LLVM Github Monorepo

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

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
@@ -465,6 +465,18 @@
   Not(Contains(AllOf(qualifier(""), named("foo");
 }
 
+// https://github.com/clangd/clangd/issues/1451
+TEST(CompletionTest, QualificationWithInlineNamespace) {
+  auto Results = completions(R"cpp(
+namespace a { inline namespace b {} }
+using namespace a::b;
+void f() { Foo^ }
+  )cpp",
+ {cls("a::Foo")});
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(AllOf(qualifier("a::"), named("Foo";
+}
+
 TEST(CompletionTest, InjectedTypename) {
   // These are suppressed when accessed as a member...
   EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -307,7 +307,7 @@
 struct CodeCompletionBuilder {
   CodeCompletionBuilder(ASTContext *ASTCtx, const CompletionCandidate ,
 CodeCompletionString *SemaCCS,
-llvm::ArrayRef QueryScopes,
+llvm::ArrayRef AccessibleScopes,
 const IncludeInserter ,
 llvm::StringRef FileName,
 CodeCompletionContext::Kind ContextKind,
@@ -361,7 +361,7 @@
   // avoids unneeded qualifiers in cases like with `using ns::X`.
   if (Completion.RequiredQualifier.empty() && !C.SemaResult) {
 llvm::StringRef ShortestQualifier = C.IndexResult->Scope;
-for (llvm::StringRef Scope : QueryScopes) {
+for (llvm::StringRef Scope : AccessibleScopes) {
   llvm::StringRef Qualifier = C.IndexResult->Scope;
   if (Qualifier.consume_front(Scope) &&
   Qualifier.size() < ShortestQualifier.size())
@@ -638,40 +638,71 @@
   //
   // Examples of unqualified completion:
   //
-  //   "vec^"   => {""}
-  //   "using namespace std; vec^"  => {"", "std::"}
-  //   "using namespace std; namespace ns { vec^ }" => {"ns::", "std::", ""}
+  //   "vec^"=> {""}
+  //   "using namespace std; vec^"   => {"", "std::"}
+  //   "namespace ns {inline namespace ni { struct Foo {}}}
+  //using namespace ns::ni; Fo^ "=> {"", "ns::ni::"}
+  //   "using namespace std; namespace ns { vec^ }"  => {"ns::", "std::", ""}
   //
   // "" for global namespace, "ns::" for normal namespace.
   std::vector AccessibleScopes;
+  // This is an overestimate of AccessibleScopes, e.g. it ignores inline
+  // namespaces, to fetch more relevant symbols from index.
+  std::vector QueryScopes;
   // The full scope qualifier as typed by the user (without the leading "::").
   // Set if the qualifier is not fully resolved by Sema.
   llvm::Optional UnresolvedQualifier;
 
-  // Construct scopes being queried in indexes. The results are deduplicated.
-  // This method format the scopes to match the index request representation.
-  std::vector scopesForIndexQuery() {
+  std::optional EnclosingNamespace;
+
+  bool AllowAllScopes = false;
+
+  // Scopes that are accessible from current context. Used for dropping
+  // unnecessary namespecifiers.
+  std::vector scopesForQualification() {
 std::set Results;
 for (llvm::StringRef AS : AccessibleScopes)
   Results.insert(
   (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
 return {Results.begin(), Results.end()};
   }
+
+  // Construct scopes being queried in indexes. The results are deduplicated.
+  // This method formats the scopes to match the index request representation.
+  std::vector scopesForIndexQuery() {
+// The enclosing namespace must be first, it gets a quality boost.
+std::vector EnclosingAtFront;
+if (EnclosingNamespace.has_value()) {
+  EnclosingAtFront.push_back(*EnclosingNamespace);
+}
+std::set Deduplicated;
+for (llvm::StringRef S : QueryScopes)
+  if (S != EnclosingNamespace)
+Deduplicated.insert((S + UnresolvedQualifier.value_or("")).str());
+
+EnclosingAtFront.reserve(EnclosingAtFront.size() + Deduplicated.size());
+llvm::copy(Deduplicated, 

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

2023-01-29 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:1714
+}
+llvm::copy_if(SpecifiedScopes.scopesForIndexQuery(),
+  std::back_inserter(QueryScopes),

Should I add a `reserve` here for QueryScopes and AccessibleScopes? Would make 
this a bit more complicated for a small performance boost.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:712
+std::vector EnclosingAtFrontForCompletion;
 std::string EnclosingScope = printNamespaceScope(*CCSema.CurContext);
+EnclosingAtFrontForIndex.push_back(EnclosingScope);

kadircet wrote:
> note that this is actually going to skip inline namespaces (and you're using 
> that in the returned set)
Hm I should probably fix this and add another regression test for this..?



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1660
 // First scope is the (modified) enclosing scope.
 QueryScopes = Scopes.scopesForIndexQuery();
 ScopeProximity.emplace(QueryScopes);

kadircet wrote:
> we should be setting `AccessibleScopes` too
Ah thanks, that's what caused the one failing test. I just copied over 
QueryScopes here for now, looks like this doesn't need any special handling for 
inline namespaces, does it?



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:
> > > tom-anders wrote:
> > > > 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.
> > > sorry for the long and confusing answer :D
> > > 
> > > I was talking about `CodeCompleteFlow` class specifically, inside 
> > > `CodeComplete.cpp`. Currently it only has `QueryScopes`, derived from the 
> > > visible contexts reported by Sema. Unfortunately it loses some 
> > > granularity to fetch more symbols from index hence it should not be used 
> > > 

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

2023-01-29 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 493096.
tom-anders marked 8 inline comments as done.
tom-anders added a comment.

Address review comments, add regression test


Repository:
  rG LLVM Github Monorepo

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

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
@@ -465,6 +465,18 @@
   Not(Contains(AllOf(qualifier(""), named("foo");
 }
 
+// https://github.com/clangd/clangd/issues/1451
+TEST(CompletionTest, QualificationWithInlineNamespace) {
+  auto Results = completions(R"cpp(
+namespace a { inline namespace b {} }
+using namespace a::b;
+void f() { Foo^ }
+  )cpp",
+ {cls("a::Foo")});
+  EXPECT_THAT(Results.Completions,
+  UnorderedElementsAre(AllOf(qualifier("a::"), named("Foo";
+}
+
 TEST(CompletionTest, InjectedTypename) {
   // These are suppressed when accessed as a member...
   EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -307,7 +307,7 @@
 struct CodeCompletionBuilder {
   CodeCompletionBuilder(ASTContext *ASTCtx, const CompletionCandidate ,
 CodeCompletionString *SemaCCS,
-llvm::ArrayRef QueryScopes,
+llvm::ArrayRef AccessibleScopes,
 const IncludeInserter ,
 llvm::StringRef FileName,
 CodeCompletionContext::Kind ContextKind,
@@ -361,7 +361,7 @@
   // avoids unneeded qualifiers in cases like with `using ns::X`.
   if (Completion.RequiredQualifier.empty() && !C.SemaResult) {
 llvm::StringRef ShortestQualifier = C.IndexResult->Scope;
-for (llvm::StringRef Scope : QueryScopes) {
+for (llvm::StringRef Scope : AccessibleScopes) {
   llvm::StringRef Qualifier = C.IndexResult->Scope;
   if (Qualifier.consume_front(Scope) &&
   Qualifier.size() < ShortestQualifier.size())
@@ -638,21 +638,40 @@
   //
   // Examples of unqualified completion:
   //
-  //   "vec^"   => {""}
-  //   "using namespace std; vec^"  => {"", "std::"}
-  //   "using namespace std; namespace ns { vec^ }" => {"ns::", "std::", ""}
+  //   "vec^"=> {""}
+  //   "using namespace std; vec^"   => {"", "std::"}
+  //   "namespace ns {inline namespace ni { struct Foo {}}}
+  //using namespace ns::ni; Fo^ "=> {"", "ns::ni::"}
+  //   "using namespace std; namespace ns { vec^ }"  => {"ns::", "std::", ""}
   //
   // "" for global namespace, "ns::" for normal namespace.
   std::vector AccessibleScopes;
+  // This is an overestimate of AccessibleScopes, e.g. it ignores inline
+  // namespaces, to fetch more relevant symbols from index.
+  std::vector QueryScopes;
   // The full scope qualifier as typed by the user (without the leading "::").
   // Set if the qualifier is not fully resolved by Sema.
   llvm::Optional UnresolvedQualifier;
 
+  std::optional EnclosingNamespace;
+
+  bool AllowAllScopes = false;
+
+  // Scopes that are accessible from current context. Used for dropping
+  // unnecessary namespecifiers.
+  std::vector scopesForQualification() {
+std::set Results;
+for (llvm::StringRef AS : AccessibleScopes)
+  Results.insert(
+  (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
+return {Results.begin(), Results.end()};
+  }
+
   // Construct scopes being queried in indexes. The results are deduplicated.
   // This method format the scopes to match the index request representation.
   std::vector scopesForIndexQuery() {
 std::set Results;
-for (llvm::StringRef AS : AccessibleScopes)
+for (llvm::StringRef AS : QueryScopes)
   Results.insert(
   (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
 return {Results.begin(), Results.end()};
@@ -662,16 +681,19 @@
 // Get all scopes that will be queried in indexes and whether symbols from
 // any scope is allowed. The first scope in the list is the preferred scope
 // (e.g. enclosing namespace).
-std::pair, bool>
-getQueryScopes(CodeCompletionContext , const Sema ,
-   const CompletionPrefix ,
-   const CodeCompleteOptions ) {
+SpecifiedScope getQueryScopes(CodeCompletionContext ,
+  const Sema ,
+ 

[PATCH] D142014: [clangd] fix wrong CalleeArgInfo in the hover

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



Comment at: clang-tools-extra/clangd/Hover.cpp:1035
 } else if (const auto *MTE =
CastNode->ASTNode.get()) {
 } else { // Unknown implicit node, assume type conversion.

v1nh1shungry wrote:
> tom-anders wrote:
> > This branch is now empty, do we still need it? 
> I keep this branch because the original implementation doesn't want to mark 
> `Converted` in this branch. Yeah I can modify the following `else` to `else 
> if (const ...; !MTE)` (or something cleaner), but I think the two are the 
> same ugly :(
Ah I see, what about just adding `PassType.Converted = false` here (even though 
it has no effect, but just to make this more clear)? 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D142014

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


[PATCH] D142014: [clangd] fix wrong CalleeArgInfo in the hover

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



Comment at: clang-tools-extra/clangd/Hover.cpp:1035
 } else if (const auto *MTE =
CastNode->ASTNode.get()) {
 } else { // Unknown implicit node, assume type conversion.

This branch is now empty, do we still need it? 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D142014

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


[PATCH] D141800: [clangd] Fix qualifier not being dropped for using declaration referring to scoped enum

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



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1993
 Builder.emplace(Recorder ? >CCSema->getASTContext() : 
nullptr,
-Item, SemaCCS, QueryScopes, *Inserter, FileName,
+Recorder ? Recorder->CCSema->CurContext : nullptr, 
Item,
+SemaCCS, QueryScopes, *Inserter, FileName,

tom-anders wrote:
> kadircet wrote:
> > instead of passing it here, can we just do the traversal as part of 
> > `getQueryScopes` and let these be handled uniformly by the shortest 
> > qualifier logic ?
> Yeah that was my initial idea, however the problem is that it looses the 
> information about whether the enum is scoped or not:
> 1) QueryScopes only stores strings
> 2) The index has no flag for indicating whether an EnumConstant belongs to a 
> scoped or unscoped enum
> 
> Thus, we get a small problem, consider the following code:
> 
> ```
> namespace ns {
> enum class Scoped { Foo };
> enum class Unscoped { Bar };
> }
> 
> int main() {
> using ns::Scoped;
> using ns::Unscoped;
> 
> Foo^
> Bar^
> }
> ```
> Here we want to complete Foo^ to ns::Scoped::Foo, but for Bar^ we want only 
> ns::Bar. To resolve this, the scoped/unscoped information needs to be 
> available when building the completion candidate. 
> 
> Hope this was clear, maybe I missed something.
Sorry, I meant the completion for Foo^ should be Scoped::Foo here, not 
ns::Scoped::Foo.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141800

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


[PATCH] D141800: [clangd] Fix qualifier not being dropped for using declaration referring to scoped enum

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



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:1993
 Builder.emplace(Recorder ? >CCSema->getASTContext() : 
nullptr,
-Item, SemaCCS, QueryScopes, *Inserter, FileName,
+Recorder ? Recorder->CCSema->CurContext : nullptr, 
Item,
+SemaCCS, QueryScopes, *Inserter, FileName,

kadircet wrote:
> instead of passing it here, can we just do the traversal as part of 
> `getQueryScopes` and let these be handled uniformly by the shortest qualifier 
> logic ?
Yeah that was my initial idea, however the problem is that it looses the 
information about whether the enum is scoped or not:
1) QueryScopes only stores strings
2) The index has no flag for indicating whether an EnumConstant belongs to a 
scoped or unscoped enum

Thus, we get a small problem, consider the following code:

```
namespace ns {
enum class Scoped { Foo };
enum class Unscoped { Bar };
}

int main() {
using ns::Scoped;
using ns::Unscoped;

Foo^
Bar^
}
```
Here we want to complete Foo^ to ns::Scoped::Foo, but for Bar^ we want only 
ns::Bar. To resolve this, the scoped/unscoped information needs to be available 
when building the completion candidate. 

Hope this was clear, maybe I missed something.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141800

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


[PATCH] D141800: [clangd] Fix qualifier not being dropped for using declaration referring to scoped enum

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

Factor out logic into helper function


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141800

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
@@ -3063,6 +3063,25 @@
   AllOf(qualifier(""), scope("na::"), named("ClangdA";
 }
 
+// https://github.com/clangd/clangd/issues/1361
+TEST(CompletionTest, ScopedEnumUsingDecl) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(
+  R"cpp(
+namespace ns { enum class Scoped { FooBar }; }
+using ns::Scoped;
+void f() { 
+Foo^ 
+}
+  )cpp",
+  {enmConstant("ns::Scoped::FooBar")}, Opts);
+  EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
+   qualifier("Scoped::"), named("FooBar"),
+   kind(CompletionItemKind::EnumMember;
+}
+
 TEST(CompletionTest, AllScopesCompletion) {
   clangd::CodeCompleteOptions Opts = {};
   Opts.AllScopes = true;
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -311,7 +311,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 ,
+  CodeCompletionBuilder(ASTContext *ASTCtx, DeclContext *SemaDeclCtx,
+const CompletionCandidate ,
 CodeCompletionString *SemaCCS,
 llvm::ArrayRef QueryScopes,
 const IncludeInserter ,
@@ -374,6 +375,8 @@
 ShortestQualifier = Qualifier;
 }
 Completion.RequiredQualifier = std::string(ShortestQualifier);
+
+stripNamespaceForEnumConstantIfUsingDecl(*C.IndexResult, SemaDeclCtx);
   }
 }
 if (C.IdentifierResult) {
@@ -430,6 +433,30 @@
   });
   }
 
+  // With all-scopes-completion, we can complete enum constants of scoped
+  // enums, in which case the completion might not be visible to Sema.
+  // So, if there's a using declaration for the enum class, manually
+  // drop the qualifiers.
+  void stripNamespaceForEnumConstantIfUsingDecl(const Symbol ,
+DeclContext *SemaDeclCtx) {
+if (IndexResult.SymInfo.Kind != index::SymbolKind::EnumConstant)
+  return;
+for (auto *Ctx = SemaDeclCtx; Ctx; Ctx = Ctx->getParent())
+  for (auto *D : Ctx->decls()) {
+const auto *UD = dyn_cast(D);
+if (!UD)
+  continue;
+const auto *ED = dyn_cast(UD->getTargetDecl());
+if (!ED || !ED->isScoped())
+  continue;
+auto EnumName = printQualifiedName(*ED) + "::";
+if (EnumName == IndexResult.Scope) {
+  Completion.RequiredQualifier = ED->getName().str() + "::";
+  return;
+}
+  }
+  }
+
   void add(const CompletionCandidate , CodeCompletionString *SemaCCS) {
 assert(bool(C.SemaResult) == bool(SemaCCS));
 Bundled.emplace_back();
@@ -1963,7 +1990,8 @@
   : nullptr;
   if (!Builder)
 Builder.emplace(Recorder ? >CCSema->getASTContext() : 
nullptr,
-Item, SemaCCS, QueryScopes, *Inserter, FileName,
+Recorder ? Recorder->CCSema->CurContext : nullptr, 
Item,
+SemaCCS, QueryScopes, *Inserter, FileName,
 CCContextKind, Opts, IsUsingDeclaration, 
NextTokenKind);
   else
 Builder->add(Item, SemaCCS);


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3063,6 +3063,25 @@
   AllOf(qualifier(""), scope("na::"), named("ClangdA";
 }
 
+// https://github.com/clangd/clangd/issues/1361
+TEST(CompletionTest, ScopedEnumUsingDecl) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(
+  R"cpp(
+namespace ns { enum class Scoped { FooBar }; }
+using ns::Scoped;
+void f() { 
+Foo^ 
+}
+  )cpp",
+  {enmConstant("ns::Scoped::FooBar")}, Opts);
+  EXPECT_THAT(Results.Completions, 

[PATCH] D141800: [clangd] Fix qualifier not being dropped for using declaration referring to scoped enum

2023-01-15 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.

Relevant issue: https://github.com/clangd/clangd/issues/1361

The problem here was that writing something like `using ns::ScopedEnum`
does not cause Sema to visit this scope, to it won't be added into
`CodeCompletionBuilder`'s `AccessibleScopes`, leading to the qualifier not
being dropped.

To detect this, walk up the DeclContext to check if we have a matching
using declaration. If so, drop the qualifiers.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D141800

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
@@ -3059,6 +3059,25 @@
   AllOf(qualifier(""), scope("na::"), named("ClangdA";
 }
 
+// https://github.com/clangd/clangd/issues/1361
+TEST(CompletionTest, ScopedEnumUsingDecl) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.AllScopes = true;
+
+  auto Results = completions(
+  R"cpp(
+namespace ns { enum class Scoped { FooBar }; }
+using ns::Scoped;
+void f() { 
+Foo^ 
+}
+  )cpp",
+  {enmConstant("ns::Scoped::FooBar")}, Opts);
+  EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
+   qualifier("Scoped::"), named("FooBar"),
+   kind(CompletionItemKind::EnumMember;
+}
+
 TEST(CompletionTest, AllScopesCompletion) {
   clangd::CodeCompleteOptions Opts = {};
   Opts.AllScopes = true;
Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -305,7 +305,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 ,
+  CodeCompletionBuilder(ASTContext *ASTCtx, DeclContext *SemaDeclCtx,
+const CompletionCandidate ,
 CodeCompletionString *SemaCCS,
 llvm::ArrayRef AccessibleScopes,
 const IncludeInserter ,
@@ -360,14 +361,39 @@
   // If the completion was visible to Sema, no qualifier is needed. This
   // avoids unneeded qualifiers in cases like with `using ns::X`.
   if (Completion.RequiredQualifier.empty() && !C.SemaResult) {
-llvm::StringRef ShortestQualifier = C.IndexResult->Scope;
-for (llvm::StringRef Scope : AccessibleScopes) {
-  llvm::StringRef Qualifier = C.IndexResult->Scope;
-  if (Qualifier.consume_front(Scope) &&
-  Qualifier.size() < ShortestQualifier.size())
-ShortestQualifier = Qualifier;
+// With all-scopes-completion, we can complete enum constants of scoped
+// enums, in which case the completion might not be visible to Sema.
+// So, if there's a using declaration for the enum class, manually
+// drop the qualifiers.
+if (C.IndexResult->SymInfo.Kind == index::SymbolKind::EnumConstant &&
+SemaDeclCtx && ASTCtx) {
+  for (auto *Ctx = SemaDeclCtx; Ctx; Ctx = Ctx->getParent()) {
+auto MatchingUsingDecl = llvm::find_if(Ctx->decls(), [](Decl *D) {
+  if (const auto *UD = dyn_cast(D))
+if (const auto *ED = dyn_cast(UD->getTargetDecl()))
+  if (ED->isScoped() &&
+  printQualifiedName(*ED) + "::" == C.IndexResult->Scope)
+return true;
+  return false;
+});
+if (MatchingUsingDecl != Ctx->decls_end()) {
+  assert(MatchingUsingDecl->isNamed());
+  Completion.RequiredQualifier =
+  dyn_cast(*MatchingUsingDecl)->getName().str() +
+  "::";
+  break;
+}
+  }
+} else {
+  llvm::StringRef ShortestQualifier = C.IndexResult->Scope;
+  for (llvm::StringRef Scope : AccessibleScopes) {
+llvm::StringRef Qualifier = C.IndexResult->Scope;
+if (Qualifier.consume_front(Scope) &&
+Qualifier.size() < ShortestQualifier.size())
+  ShortestQualifier = Qualifier;
+  }
+  Completion.RequiredQualifier = std::string(ShortestQualifier);
 }
-Completion.RequiredQualifier = 

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

2023-01-14 Thread Tom Praschan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG343b1ae3622a: [clangd] Hover: show CalleeArgInfo for 
literals and expressions (authored by tom-anders).

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 _b) {};
+  void code() {
+int a = 1;
+fun(a, [[^2]]);
+  }
+  )cpp",
+   [](HoverInfo ) {
+ 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 _b) {};
+  void code() {
+int a = 1;
+fun(a, 1 [[^+]] 2);
+  }
+  )cpp",
+   [](HoverInfo ) {
+ 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.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 ) {
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 ,
+   const PrintingPolicy );
+
 // Generates hover info for `this` and evaluatable expressions.
 // FIXME: Support hover for literals (esp user-defined)
-std::optional getHoverContents(const Expr *E, ParsedAST ,
+std::optional getHoverContents(const SelectionTree::Node *N,
+  const Expr *E, ParsedAST ,
   const PrintingPolicy ,
   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-14 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:
> > > 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.
> sorry for the long and confusing answer :D
> 
> I was talking about `CodeCompleteFlow` class specifically, inside 
> `CodeComplete.cpp`. Currently it only has `QueryScopes`, derived from the 
> visible contexts reported by Sema. Unfortunately it loses some granularity to 
> fetch more symbols from index hence it should not be used when picking the 
> required qualifier.
> My suggestion is to add a new field in `CodeCompleteFlow` called 
> `AccessibleScope`, which is derived at the same stage as `QueryScopes`, while 
> preserving inline namespaces, and used when creating `CodeCompletionBuilder` 
> in `CodeCompleteFlow::toCodeCompletion` (instead of `QueryScopes`).
Ok, think I got it - To make this a bit less confusing, I first renamed 
SpecifiedScope::AccessibleScopes to SpecifiedScope::QueryScopes (that's the 
number under which it is (and was) stored in CodeCompleteFlow anyway) and then 
added a back a new field AccessibleScopes, that keeps the inline namespaces. 
This is then stored in CodeCompleteFlow:AccessibleScopes and passed to the 
CodeCompletionBuilder instead of QueryScopes.

This now still passes all existing tests and I verified in my editor that it 
also fixes the original issue. 

I couldn't figure out how to write a regression test for this now though :(


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-14 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 489284.
tom-anders added a comment.

Address review comment: Introduce new AccessibleScopes variable


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D140915

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

Index: clang-tools-extra/clangd/CodeComplete.cpp
===
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -307,7 +307,7 @@
 struct CodeCompletionBuilder {
   CodeCompletionBuilder(ASTContext *ASTCtx, const CompletionCandidate ,
 CodeCompletionString *SemaCCS,
-llvm::ArrayRef QueryScopes,
+llvm::ArrayRef AccessibleScopes,
 const IncludeInserter ,
 llvm::StringRef FileName,
 CodeCompletionContext::Kind ContextKind,
@@ -361,7 +361,7 @@
   // avoids unneeded qualifiers in cases like with `using ns::X`.
   if (Completion.RequiredQualifier.empty() && !C.SemaResult) {
 llvm::StringRef ShortestQualifier = C.IndexResult->Scope;
-for (llvm::StringRef Scope : QueryScopes) {
+for (llvm::StringRef Scope : AccessibleScopes) {
   llvm::StringRef Qualifier = C.IndexResult->Scope;
   if (Qualifier.consume_front(Scope) &&
   Qualifier.size() < ShortestQualifier.size())
@@ -643,16 +643,27 @@
   //   "using namespace std; namespace ns { vec^ }" => {"ns::", "std::", ""}
   //
   // "" for global namespace, "ns::" for normal namespace.
+  std::vector QueryScopes;
+  // Like QueryScopes, but also contains inline namespaces.
   std::vector AccessibleScopes;
   // The full scope qualifier as typed by the user (without the leading "::").
   // Set if the qualifier is not fully resolved by Sema.
   llvm::Optional UnresolvedQualifier;
 
+  // Construct scopes to use for code completion. The results are deduplicated.
+  std::vector scopesForCodeCompletion() {
+std::set Results;
+for (llvm::StringRef AS : AccessibleScopes)
+  Results.insert(
+  (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
+return {Results.begin(), Results.end()};
+  }
+
   // Construct scopes being queried in indexes. The results are deduplicated.
   // This method format the scopes to match the index request representation.
   std::vector scopesForIndexQuery() {
 std::set Results;
-for (llvm::StringRef AS : AccessibleScopes)
+for (llvm::StringRef AS : QueryScopes)
   Results.insert(
   (AS + (UnresolvedQualifier ? *UnresolvedQualifier : "")).str());
 return {Results.begin(), Results.end()};
@@ -662,16 +673,19 @@
 // Get all scopes that will be queried in indexes and whether symbols from
 // any scope is allowed. The first scope in the list is the preferred scope
 // (e.g. enclosing namespace).
-std::pair, bool>
+std::tuple, std::vector, bool>
 getQueryScopes(CodeCompletionContext , const Sema ,
const CompletionPrefix ,
const CodeCompleteOptions ) {
   SpecifiedScope Scopes;
   for (auto *Context : CCContext.getVisitedContexts()) {
-if (isa(Context))
-  Scopes.AccessibleScopes.push_back(""); // global namespace
-else if (isa(Context))
-  Scopes.AccessibleScopes.push_back(printNamespaceScope(*Context));
+if (isa(Context)) {
+  Scopes.QueryScopes.push_back("");
+  Scopes.AccessibleScopes.push_back("");
+} else if (const auto *ND = dyn_cast(Context)) {
+  Scopes.QueryScopes.push_back(printNamespaceScope(*Context));
+  Scopes.AccessibleScopes.push_back(printQualifiedName(*ND) + "::");
+}
   }
 
   const CXXScopeSpec *SemaSpecifier =
@@ -684,39 +698,52 @@
   vlog("Sema said no scope specifier, but we saw {0} in the source code",
HeuristicPrefix.Qualifier);
   StringRef SpelledSpecifier = HeuristicPrefix.Qualifier;
-  if (SpelledSpecifier.consume_front("::"))
+  if (SpelledSpecifier.consume_front("::")) {
 Scopes.AccessibleScopes = {""};
+Scopes.QueryScopes = {""};
+  }
   Scopes.UnresolvedQualifier = std::string(SpelledSpecifier);
-  return {Scopes.scopesForIndexQuery(), false};
+  return {Scopes.scopesForIndexQuery(), Scopes.scopesForCodeCompletion(),
+  false};
 }
 // The enclosing namespace must be first, it gets a quality boost.
-std::vector EnclosingAtFront;
+std::vector EnclosingAtFrontForIndex;
+std::vector EnclosingAtFrontForCompletion;
 std::string EnclosingScope = printNamespaceScope(*CCSema.CurContext);
-EnclosingAtFront.push_back(EnclosingScope);
+EnclosingAtFrontForIndex.push_back(EnclosingScope);
+EnclosingAtFrontForCompletion.push_back(EnclosingScope);
 for (auto  : Scopes.scopesForIndexQuery()) {
   if (EnclosingScope != S)
-

[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] 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-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(
-  ::Scopes,
-  UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::";
+  EXPECT_THAT(
+  Requests,
+  ElementsAre(Field(::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(
-  ::Scopes,
-  UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::";
+  EXPECT_THAT(
+  Requests,
+  ElementsAre(Field(::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] 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 _b) {};
+  void code() {
+int a = 1;
+fun(a, [[^2]]);
+  }
+  )cpp",
+   [](HoverInfo ) {
+ 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 _b) {};
+  void code() {
+int a = 1;
+fun(a, 1 [[^+]] 2);
+  }
+  )cpp",
+   [](HoverInfo ) {
+ 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.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 ) {
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 ,
+   const PrintingPolicy );
+
 // Generates hover info for `this` and evaluatable expressions.
 // FIXME: Support hover for literals (esp user-defined)
-std::optional getHoverContents(const Expr *E, ParsedAST ,
+std::optional getHoverContents(const SelectionTree::Node *N,
+  const Expr *E, ParsedAST ,
   const PrintingPolicy ,
   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);
+ 

[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] 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  : 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  : T.ranges("def"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Definition |
-   ReferencesResult::Declaration)));
-  for (const auto  : T.ranges("decl"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration)));
-  for (const auto  : 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  : 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  : 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]] 

[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] 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 ) {
-  HoverInfo HI;
-
+void addStringLiteralContents(const StringLiteral *SL, const PrintingPolicy 
,
+  HoverInfo ) {

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] 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 _b) {};
+  void code() {
+int a = 1;
+fun(a, [[^2]]);
+  }
+  )cpp",
+   [](HoverInfo ) {
+ 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 ,
+   const PrintingPolicy );
+
 // Generates hover info for `this` and evaluatable expressions.
 // FIXME: Support hover for literals (esp user-defined)
-std::optional getHoverContents(const Expr *E, ParsedAST ,
+std::optional getHoverContents(const SelectionTree::Node *N,
+  const Expr *E, ParsedAST ,
   const PrintingPolicy ,
   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 (const PredefinedExpr *PE 

[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 ,
+   const PrintingPolicy );

(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-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 _b) {};
+  void code() {
+int a = 1;
+fun(a, [[^2]]);
+  }
+  )cpp",
+   [](HoverInfo ) {
+ 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 ) {
-  HoverInfo HI;
-
+void addStringLiteralContents(const StringLiteral *SL, const PrintingPolicy ,
+  HoverInfo ) {
   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 ,
+   const PrintingPolicy );
+
 // Generates hover info for `this` and evaluatable expressions.
 // FIXME: Support hover for literals (esp user-defined)
-std::optional getHoverContents(const Expr *E, ParsedAST ,
+std::optional getHoverContents(const SelectionTree::Node *N,
+  const Expr *E, ParsedAST ,
   const PrintingPolicy ,
   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 literals
-  if (const 

[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 ) {
@@ -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 ) {
@@ -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, 

[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  : 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  : T.ranges("def"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Definition |
-   ReferencesResult::Declaration)));
-  for (const auto  : T.ranges("decl"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration)));
-  for (const auto  : 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  : 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  : 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() {
-  auto *X = 

[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 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  : 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  : T.ranges("def"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Definition |
-   ReferencesResult::Declaration)));
-  for (const auto  : T.ranges("decl"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration)));
-  for (const auto  : 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  : 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  : 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] 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 ) {

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  : 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] D134130: [clangd] Add doxygen parsing for Hover [1/3]

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

Thanks for the detailed feedback! Unfortunately, I’m sick right now, so I 
probably won’t be able to give a detailed answer until after Christmas.

In D134130#3992116 , @kadircet wrote:

> Happy to move the discussion to some other medium as well, if you would like 
> to have them in discourse/github etc.

Yeah let’s maybe copy your comment back to the GitHub Issue and discuss over 
there, it seems the issue has lots of subscribers already who perhaps also have 
some more ideas/usecases.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134130

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


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

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



Comment at: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp:93
+// Return true if `LHS` is declared in `RHS`
+bool declareIn(const NamedDecl *LHS, const DeclContext *RHS) {
+  const auto *D = LHS->getDeclContext();





Comment at: 
clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp:212
   // Produce replacements to add the qualifiers.
   std::string Qualifier = printUsingNamespaceName(Ctx, *TargetDirective) + 
"::";
   for (auto Loc : IdentsToQualify) {

v1nh1shungry wrote:
> v1nh1shungry wrote:
> > tom-anders wrote:
> > > v1nh1shungry wrote:
> > > > We can replace `printUsingNamespaceName` with `printNamespaceScope` 
> > > > here so that we can get `a::foobar()` in the test. 
> > > > 
> > > > However, it can sometimes cause redundancy such as in the 10th test. 
> > > > 
> > > > And I don't know whether it is worth it. WDYT?
> > > Just making sure I understood this correctly:
> > > 
> > > If you replace `printUsingNamespaceName` with `printNamespaceScope`, 
> > > then...
> > > 
> > > - ...in the test you added it would result in `a::foobar()` instead of 
> > > `a::b::foobar()` (which is better)
> > > - ... but in this test (which is the 10th test if I counted correctly):
> > >  
> > > ```
> > >  namespace a::b { struct Foo {}; }
> > >   using namespace a;
> > >   using namespace a::[[b]];
> > >   using namespace b;
> > >   int main() { Foo F;}
> > > ```
> > > what would be the result..? would you get `a::Foo` instead of `a::b::Foo`?
> > > 
> > Sorry, I mean the next test. I read `10` from the inlay hint but I forgot 
> > the index starts from `0` :(
> > 
> > The test I want to mention:
> > ```
> > namespace a::b { struct Foo {}; }
> > using namespace a;
> > using namespace a::b;
> > using namespace [[b]];
> > int main() { Foo F;}
> > ```
> > 
> > We will get `a::b::Foo` in both the 10th and 11th tests. So in the 10th 
> > test, we don't get any benefits and don't sacrifice anything. In the 11th 
> > test, we get more redundancy than the existing version.
> > 
> > Apologize again for my mistake.
> FYI, we have a discussion left here.
Ok I’d say let’s just go with printUsingNamespaceName here for now. When your 
other patch is merged as well, maybe we could have a look at this again.


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] D138028: [clangd] Fix action `RemoveUsingNamespace` for inline namespace

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

In D138028#3957139 , @v1nh1shungry 
wrote:

> A gentle ping? Sorry if it bothers you.

Sorry! I thought you’d probably first wanted to address the remaining comments 
in https://reviews.llvm.org/D137817 because they might also affect this patch 
here..?


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-11-23 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 477566.
tom-anders added a comment.

Add end-to-end test


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
@@ -302,6 +302,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  : 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  : T.ranges("def"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Definition |
-   ReferencesResult::Declaration)));
-  for (const auto  : T.ranges("decl"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration)));
-  for (const auto  : 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  : 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  : 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() {
-  auto *X = &[[^foo]];
-  [[foo]](42);

[PATCH] D138425: [clangd] Parameter hints for template specialization

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

In D138425#3941206 , @sammccall wrote:

> In D138425#3941183 , @v1nh1shungry 
> wrote:
>
>> Yes, there is a common situation where people use a meaningless template 
>> parameter name, but I think the same for functions.
>
> I don't think it's the same: my wild guess would be 30% of function params 
> have useless names, and 90% of template params do.
> If this were accurate, it seems function param hints are usually 
> (potentially) useful, while template params are almost always useless.

I agree that is usually useless and too much noise, especially for container 
like types. But, it could maybe be useful for template parameters that have a 
default value? For example, I'll never need an inlay hint for something like 
`std::map, but when passing a custom comparator and allocator as the 3rd 
and 4th template type, inlay hints might actually be helpful there.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D138425

___
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-11-21 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

In D137894#3940600 , @sammccall wrote:

> Since this is a protocol extension, you might want to add an end-to-end test: 
> variant of `clang-tools-extra/clangd/test/xrefs.test` 
> (`xrefs-container.test`? to avoid complicating all the existing tests).

I'll look into adding this, but I'm not familiar with with these kind of tests 
yet, so I'll might need some time to figure it out - I already uploaded an 
updated version of the patch anyway to get some more feedback in the meantime.

> And one this lands, one of us should update 
> https://github.com/llvm/clangd-www/blob/main/extensions.md

Yeah I could do that, I think I can even commit directly to that repo? Or 
should I open a review on github/phabricator for this anyway?




Comment at: clang-tools-extra/clangd/Protocol.h:244
+
+  friend bool operator!=(const ReferenceLocation ,
+ const ReferenceLocation ) {

sammccall wrote:
> are these operators actually needed? especially `operator<` we usually get 
> away without
Correct, they are indeed not needed as of now.



Comment at: clang-tools-extra/clangd/XRefs.cpp:1307
+llvm::Optional
+getContextStringForMainFileRef(const DeclContext *DeclCtx) {
+  for (auto *Ctx = DeclCtx; Ctx; Ctx = Ctx->getParent()) {

sammccall wrote:
> a few things to consider here:
>  - for e.g. lambdas, do you want `foo::bar::(anonymous class)::operator()`, 
> or `foo::bar`, or something else?
>  - there are a few other function-like decls, see Decl::isFunctionOrMethod().
>  - only functions? suppose you have `struct S { T member; };` and you're 
> looking up xrefs for T. Don't we want to return `S` as the context/container 
> name
>  - in general, I think want to get the same container for the index vs AST 
> path here. This suggests we should be sharing `getRefContainer` from 
> `SymbolCollector.cpp` rather than implementing something ifferent
Changed this to use `SymbolCollector::getRefContainer`, this should address 
most of the things you mentioned. Now AST and Index results should be 
consistent here



Comment at: clang-tools-extra/clangd/XRefs.cpp:1310
+if (const auto *FD = llvm::dyn_cast(Ctx))
+  return FD->getQualifiedNameAsString();
+if (const auto *RD = llvm::dyn_cast(Ctx))

sammccall wrote:
> again for stringifying, I think we want the index/non-index cases to be the 
> same, which suggests the logic to generate Scope+Name (i.e. 
> clangd::printQualifiedName)+Signature and then concatenating them.
> 
> Generating the signature is a bit complicated, so maybe leave it out (from 
> both AST + index codepath) from initial patch?
There's `CodeCompletionString::getSignature`, we could use that one probably?

But anyway, the `Signature` field for index container results is actually empty 
right now for some reason (not sure if this a bug or a feature), so I removed 
Signature from index container results as well for now. Let's look into this in 
a follow-up patch.



Comment at: clang-tools-extra/clangd/XRefs.cpp:1458
+  assert(Ref != RefIndexForContainer.end());
+  // Name is not useful here, because it's just gonna be the name of 
the
+  // function the cursor is on. Scope is interesting though, since this

sammccall wrote:
> To me, this doesn't seem like a sufficient reason to have irregular behavior 
> for different refs.
Ok, changed it to Scope + Name here as well. If users complain about this, we 
can still change it later.


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-11-21 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 476918.
tom-anders marked 7 inline comments as done.
tom-anders added a comment.

Address 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/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
@@ -302,6 +302,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  : 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  : T.ranges("def"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Definition |
-   ReferencesResult::Declaration)));
-  for (const auto  : T.ranges("decl"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration)));
-  for (const auto  : 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  : 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  : 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() {
-  auto *X = &[[^foo]];
-  [[foo]](42);
+  auto 

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

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



Comment at: clang-tools-extra/clangd/unittests/XRefsTests.cpp:1939
 int main() {
-  int $def[[foo]];
-  [[^foo]] = 2;
-  int test1 = [[foo]];
+  int $def(main)[[foo]];
+  $(main)[[^foo]] = 2;

@nridge See https://reviews.llvm.org/D137909 for this new syntax


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-11-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 updated this revision to Diff 476438.
tom-anders added a comment.
tom-anders retitled this revision from "[clangd] Prototype for adding enclosing 
function in references results" to "[clangd] Add extension for adding context 
(enclosing function or class) in references results".
tom-anders published this revision for review.
tom-anders marked 2 inline comments as done.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Add tests, add client capability, add new ReferenceLocation type




Comment at: clang-tools-extra/clangd/Protocol.h:218
+  /// reference occurs
+  std::string container;
+

Location is a common vocabulary type.
If we're going to add an extension that relates to a particular method, we 
should define a new type that's wire-compatible if that's at all feasible. 
Could be a subclass of Location or just a clone.

(If this is just a shortcut taken while drafting this patch, please ignore me!)



Comment at: clang-tools-extra/clangd/XRefs.cpp:1479
+
+Index->lookup(ContainerLookup, [&](const Symbol ) {
+  auto Ref = RefIndexForContainer.find(Container.ID);

Being able to get all the containers in one ~constant-time index query is 
great! May still not want to have this on-by-default when the client doesn't 
advertise support, as it's a fixed nontrivial latency hit for remote index.

Also we should skip this query when the set of IDs is empty. That can go here 
or (maybe better) in the remote index client.



Comment at: clang-tools-extra/clangd/XRefs.cpp:1479
+
+Index->lookup(ContainerLookup, [&](const Symbol ) {
+  auto Ref = RefIndexForContainer.find(Container.ID);

sammccall wrote:
> Being able to get all the containers in one ~constant-time index query is 
> great! May still not want to have this on-by-default when the client doesn't 
> advertise support, as it's a fixed nontrivial latency hit for remote index.
> 
> Also we should skip this query when the set of IDs is empty. That can go here 
> or (maybe better) in the remote index client.
> Being able to get all the containers in one ~constant-time index query is 
> great! May still not want to have this on-by-default when the client doesn't 
> advertise support, as it's a fixed nontrivial latency hit for remote index.
Makes sense, we could either add a ClientCapability for this (Looks like we 
already have some capabilities related to extensions, so this wouldn't be a 
novelty), or it could just be a command line flag. Any preferences? 

> Also we should skip this query when the set of IDs is empty. That can go here 
> or (maybe better) in the remote index client.
Agreed, probably more foolproof to let the index do this (otherwise the next 
person will forget about that as well probably)


Relevant issue: https://github.com/clangd/clangd/issues/177


Repository:
  rG LLVM Github Monorepo

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/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
@@ -302,6 +302,7 @@
 MATCHER_P(sym, Name, "") { return arg.Name == Name; }
 
 MATCHER_P(rangeIs, R, "") { return arg.Loc.range == R; }
+MATCHER_P(contextIs, C, "") { return arg.Loc.context.value_or("") == C; }
 MATCHER_P(attrsAre, A, "") { return arg.Attributes == A; }
 MATCHER_P(hasID, ID, "") { return arg.ID == ID; }
 
@@ -1900,28 +1901,30 @@
 
   auto AST = TU.build();
   std::vector> ExpectedLocations;
-  for (const auto  : T.ranges())
-ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));
+  for (const auto &[R, Context] : T.rangesWithPayload())
+ExpectedLocations.push_back(
+AllOf(rangeIs(R), contextIs(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  : T.ranges("def"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Definition |
-   ReferencesResult::Declaration)));
-  for (const auto  : T.ranges("decl"))
-ExpectedLocations.push_back(
-AllOf(rangeIs(R), attrsAre(ReferencesResult::Declaration)));
-  for (const auto  : T.ranges("overridedecl"))
+  for (const auto &[R, Context] : 

[PATCH] D137909: [Support] Allow complex names for annotation points and ranges via ${}

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

Thanks again! Landed this with your suggestions incorporated.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137909

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


[PATCH] D137909: [Support] Allow complex names for annotation points and ranges via ${}

2022-11-18 Thread Tom Praschan via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
tom-anders marked 6 inline comments as done.
Closed by commit rG3cf14a7bdce0: [Support] Add support for attaching payloads 
to points and ranges (authored by tom-anders).

Changed prior to commit:
  https://reviews.llvm.org/D137909?vs=476230=476429#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137909

Files:
  clang-tools-extra/clangd/unittests/Annotations.cpp
  clang-tools-extra/clangd/unittests/Annotations.h
  llvm/include/llvm/Testing/Support/Annotations.h
  llvm/lib/Testing/Support/Annotations.cpp
  llvm/unittests/Support/AnnotationsTest.cpp

Index: llvm/unittests/Support/AnnotationsTest.cpp
===
--- llvm/unittests/Support/AnnotationsTest.cpp
+++ llvm/unittests/Support/AnnotationsTest.cpp
@@ -12,6 +12,7 @@
 using ::testing::AllOf;
 using ::testing::ElementsAre;
 using ::testing::IsEmpty;
+using ::testing::Pair;
 using ::testing::ResultOf;
 using ::testing::UnorderedElementsAre;
 
@@ -105,6 +106,38 @@
   ElementsAre(range(8, 9), range(7, 10), range(1, 10)));
 }
 
+TEST(AnnotationsTest, Payload) {
+  // // A single unnamed point or range with unspecified payload
+  EXPECT_THAT(llvm::Annotations("a$^b").pointWithPayload(), Pair(1u, ""));
+  EXPECT_THAT(llvm::Annotations("a$[[b]]cdef").rangeWithPayload(),
+  Pair(range(1, 2), ""));
+
+  // A single unnamed point or range with empty payload
+  EXPECT_THAT(llvm::Annotations("a$()^b").pointWithPayload(), Pair(1u, ""));
+  EXPECT_THAT(llvm::Annotations("a$()[[b]]cdef").rangeWithPayload(),
+  Pair(range(1, 2), ""));
+
+  // A single unnamed point or range with payload.
+  EXPECT_THAT(llvm::Annotations("a$(foo)^b").pointWithPayload(),
+  Pair(1u, "foo"));
+  EXPECT_THAT(llvm::Annotations("a$(foo)[[b]]cdef").rangeWithPayload(),
+  Pair(range(1, 2), "foo"));
+
+  // A single named point or range with payload
+  EXPECT_THAT(llvm::Annotations("a$name(foo)^b").pointWithPayload("name"),
+  Pair(1u, "foo"));
+  EXPECT_THAT(
+  llvm::Annotations("a$name(foo)[[b]]cdef").rangeWithPayload("name"),
+  Pair(range(1, 2), "foo"));
+
+  // Multiple named points with payload.
+  llvm::Annotations Annotated("a$p1(p1)^bcd$p2(p2)^123$p1^345");
+  EXPECT_THAT(Annotated.points(), IsEmpty());
+  EXPECT_THAT(Annotated.pointsWithPayload("p1"),
+  ElementsAre(Pair(1u, "p1"), Pair(7u, "")));
+  EXPECT_THAT(Annotated.pointWithPayload("p2"), Pair(4u, "p2"));
+}
+
 TEST(AnnotationsTest, Named) {
   // A single named point or range.
   EXPECT_EQ(llvm::Annotations("a$foo^b").point("foo"), 1u);
@@ -144,6 +177,8 @@
   EXPECT_DEATH(llvm::Annotations("ff[[fdfd"), "unmatched \\[\\[");
   EXPECT_DEATH(llvm::Annotations("ff[[fdjsfjd]]xxx]]"), "unmatched \\]\\]");
   EXPECT_DEATH(llvm::Annotations("ff$fdsfd"), "unterminated \\$name");
+  EXPECT_DEATH(llvm::Annotations("ff$("), "unterminated payload");
+  EXPECT_DEATH(llvm::Annotations("ff$name("), "unterminated payload");
 #endif
 }
 } // namespace
Index: llvm/lib/Testing/Support/Annotations.cpp
===
--- llvm/lib/Testing/Support/Annotations.cpp
+++ llvm/lib/Testing/Support/Annotations.cpp
@@ -28,27 +28,35 @@
 require(Assertion, Msg, Text);
   };
   llvm::Optional Name;
-  llvm::SmallVector, 8> OpenRanges;
+  llvm::Optional Payload;
+  llvm::SmallVector OpenRanges;
 
   Code.reserve(Text.size());
   while (!Text.empty()) {
 if (Text.consume_front("^")) {
-  Points[Name.value_or("")].push_back(Code.size());
+  All.push_back(
+  {Code.size(), size_t(-1), Name.value_or(""), Payload.value_or("")});
+  Points[Name.value_or("")].push_back(All.size() - 1);
   Name = llvm::None;
+  Payload = llvm::None;
   continue;
 }
 if (Text.consume_front("[[")) {
-  OpenRanges.emplace_back(Name.value_or(""), Code.size());
+  OpenRanges.push_back(
+  {Code.size(), size_t(-1), Name.value_or(""), Payload.value_or("")});
   Name = llvm::None;
+  Payload = llvm::None;
   continue;
 }
 Require(!Name, "$name should be followed by ^ or [[");
 if (Text.consume_front("]]")) {
   Require(!OpenRanges.empty(), "unmatched ]]");
-  Range R;
-  R.Begin = OpenRanges.back().second;
-  R.End = Code.size();
-  Ranges[OpenRanges.back().first].push_back(R);
+
+  const Annotation  = OpenRanges.back();
+  All.push_back(
+  {NewRange.Begin, Code.size(), NewRange.Name, NewRange.Payload});
+  Ranges[NewRange.Name].push_back(All.size() - 1);
+
   OpenRanges.pop_back();
   continue;
 }
@@ -56,6 +64,13 @@
   Name =
   Text.take_while([](char C) { return llvm::isAlnum(C) || C == '_'; });
   Text = Text.drop_front(Name->size());
+
+  if (Text.consume_front("(")) {
+ 

[PATCH] D137909: [Support] Allow complex names for annotation points and ranges via ${}

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

In D137909#3933730 , @sammccall wrote:

> Thanks! sorry about continuing to drift this patch, but this looks like a 
> great improvement.

No problem! I wasn't quite happy yet with the previous version of this patch 
either, really appreciate the continuous feedback!




Comment at: llvm/include/llvm/Testing/Support/Annotations.h:58
   /// represents a half-open range.
   struct Range {
 size_t Begin = 0;

sammccall wrote:
> this patch takes too many different approaches to attaching the payloads to 
> the points:
>  - adding it to an existing struct that is already returned
>  - defining a new wrapping struct for the andPayload version
>  - defining a new inheriting struct for the andPayload version
> 
> I think we should keep it simple, and use `pair` for all the 
> `andPayload` versions. This isn't optimal in isolation, but it keeps things 
> coherent, avoiding:
>  - confusion around clever type-system features (inheritance, implicit 
> conversions, smart-pointer like types, templates)
>  - introducing new structs whose names we have to remember
>  - inconsistency between how payloads are accessed between 
> ranges/points/clangd/llvm versions
> 
> In many cases structured bindings make using the `pair` versions less 
> cumbersome than they would have been in the past.
Yeah structured bindings help a lot here. Also, gtest has a `Pair` matcher 
which is really nice to use for this stuff



Comment at: llvm/include/llvm/Testing/Support/Annotations.h:108
+  const llvm::StringMap> &
+  all_points_and_payloads() const;
 

sammccall wrote:
> I hadn't seen these context on these `all_` functions, I reached out to the 
> authors to find out about them (they're used out-of-tree).
> 
> Basically the use case is to use llvm::Annotations to do the parsing, but 
> dump out the data into some external test helper which lookups/assertions 
> will run on.
> So instead of adding extra variants, we just need to expose the parse results 
> in some convenient way.
Ok, got rid of `all_points_and_payloads()` and kept `all_points()` as-is for now



Comment at: llvm/lib/Testing/Support/Annotations.cpp:30
   };
   llvm::Optional Name;
+  llvm::Optional Payload;

sammccall wrote:
> (If using the `Annotation` struct I mentioned before, an instance of it could 
> cover Name+Payload and it could also be the elements of OpenRanges)
Felt a bit less readable to me, so I kept the two optionals for name and payload


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137909

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


[PATCH] D137909: [Support] Allow complex names for annotation points and ranges via ${}

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

Use std::pair for returning payloads along with points/ranges. Also, refactor 
internal logic.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137909

Files:
  clang-tools-extra/clangd/unittests/Annotations.cpp
  clang-tools-extra/clangd/unittests/Annotations.h
  llvm/include/llvm/Testing/Support/Annotations.h
  llvm/lib/Testing/Support/Annotations.cpp
  llvm/unittests/Support/AnnotationsTest.cpp

Index: llvm/unittests/Support/AnnotationsTest.cpp
===
--- llvm/unittests/Support/AnnotationsTest.cpp
+++ llvm/unittests/Support/AnnotationsTest.cpp
@@ -12,6 +12,7 @@
 using ::testing::AllOf;
 using ::testing::ElementsAre;
 using ::testing::IsEmpty;
+using ::testing::Pair;
 using ::testing::ResultOf;
 using ::testing::UnorderedElementsAre;
 
@@ -105,6 +106,38 @@
   ElementsAre(range(8, 9), range(7, 10), range(1, 10)));
 }
 
+TEST(AnnotationsTest, Payload) {
+  // // A single unnamed point or range with unspecified payload
+  EXPECT_THAT(llvm::Annotations("a$^b").pointWithPayload(), Pair(1u, ""));
+  EXPECT_THAT(llvm::Annotations("a$[[b]]cdef").rangeWithPayload(),
+  Pair(range(1, 2), ""));
+
+  // A single unnamed point or range with empty payload
+  EXPECT_THAT(llvm::Annotations("a$()^b").pointWithPayload(), Pair(1u, ""));
+  EXPECT_THAT(llvm::Annotations("a$()[[b]]cdef").rangeWithPayload(),
+  Pair(range(1, 2), ""));
+
+  // A single unnamed point or range with payload.
+  EXPECT_THAT(llvm::Annotations("a$(foo)^b").pointWithPayload(),
+  Pair(1u, "foo"));
+  EXPECT_THAT(llvm::Annotations("a$(foo)[[b]]cdef").rangeWithPayload(),
+  Pair(range(1, 2), "foo"));
+
+  // A single named point or range with payload
+  EXPECT_THAT(llvm::Annotations("a$name(foo)^b").pointWithPayload("name"),
+  Pair(1u, "foo"));
+  EXPECT_THAT(
+  llvm::Annotations("a$name(foo)[[b]]cdef").rangeWithPayload("name"),
+  Pair(range(1, 2), "foo"));
+
+  // Multiple named points with payload.
+  llvm::Annotations Annotated("a$p1(p1)^bcd$p2(p2)^123$p1^345");
+  EXPECT_THAT(Annotated.points(), IsEmpty());
+  EXPECT_THAT(Annotated.pointsWithPayload("p1"),
+  ElementsAre(Pair(1u, "p1"), Pair(7u, "")));
+  EXPECT_THAT(Annotated.pointWithPayload("p2"), Pair(4u, "p2"));
+}
+
 TEST(AnnotationsTest, Named) {
   // A single named point or range.
   EXPECT_EQ(llvm::Annotations("a$foo^b").point("foo"), 1u);
@@ -144,6 +177,8 @@
   EXPECT_DEATH(llvm::Annotations("ff[[fdfd"), "unmatched \\[\\[");
   EXPECT_DEATH(llvm::Annotations("ff[[fdjsfjd]]xxx]]"), "unmatched \\]\\]");
   EXPECT_DEATH(llvm::Annotations("ff$fdsfd"), "unterminated \\$name");
+  EXPECT_DEATH(llvm::Annotations("ff$("), "unterminated payload");
+  EXPECT_DEATH(llvm::Annotations("ff$name("), "unterminated payload");
 #endif
 }
 } // namespace
Index: llvm/lib/Testing/Support/Annotations.cpp
===
--- llvm/lib/Testing/Support/Annotations.cpp
+++ llvm/lib/Testing/Support/Annotations.cpp
@@ -28,27 +28,35 @@
 require(Assertion, Msg, Text);
   };
   llvm::Optional Name;
-  llvm::SmallVector, 8> OpenRanges;
+  llvm::Optional Payload;
+  llvm::SmallVector OpenRanges;
 
   Code.reserve(Text.size());
   while (!Text.empty()) {
 if (Text.consume_front("^")) {
-  Points[Name.value_or("")].push_back(Code.size());
+  All.push_back(
+  {Code.size(), size_t(-1), Name.value_or(""), Payload.value_or("")});
+  Points[Name.value_or("")].push_back(All.size() - 1);
   Name = llvm::None;
+  Payload = llvm::None;
   continue;
 }
 if (Text.consume_front("[[")) {
-  OpenRanges.emplace_back(Name.value_or(""), Code.size());
+  OpenRanges.push_back(
+  {Code.size(), size_t(-1), Name.value_or(""), Payload.value_or("")});
   Name = llvm::None;
+  Payload = llvm::None;
   continue;
 }
 Require(!Name, "$name should be followed by ^ or [[");
 if (Text.consume_front("]]")) {
   Require(!OpenRanges.empty(), "unmatched ]]");
-  Range R;
-  R.Begin = OpenRanges.back().second;
-  R.End = Code.size();
-  Ranges[OpenRanges.back().first].push_back(R);
+
+  const Annotation  = OpenRanges.back();
+  All.push_back(
+  {NewRange.Begin, Code.size(), NewRange.Name, NewRange.Payload});
+  Ranges[NewRange.Name].push_back(All.size() - 1);
+
   OpenRanges.pop_back();
   continue;
 }
@@ -56,6 +64,13 @@
   Name =
   Text.take_while([](char C) { return llvm::isAlnum(C) || C == '_'; });
   Text = Text.drop_front(Name->size());
+
+  if (Text.consume_front("(")) {
+Payload = Text.take_while([](char C) { return C != ')'; });
+Require(Text.size() > 

[PATCH] D137909: [Support] Allow complex names for annotation points and ranges via ${}

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



Comment at: clang-tools-extra/clangd/unittests/Annotations.h:30
 
+  struct Position : clangd::Position {
+llvm::Optional Payload;

tom-anders wrote:
> I thought about just using `std::pair llvm::Optional> instead, but that is pretty verbose and 
> unreadable here IMO. Another nice thing about subclassing here is that we can 
> keep the API stable and don't have to introduce  an additional 
> `pointWithPayload()` getter like in the base class.
Ok the part about not needing API changes was a total lie, I had a typo so that 
ninja would only build clang but not clangd tests - I now kept the struct but 
added the same `withPayload` methods like in llvm::Annotations


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137909

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


[PATCH] D137909: [Support] Allow complex names for annotation points and ranges via ${}

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

Fix clangd::Annotations interface, now also has pointWithPayload etc.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137909

Files:
  clang-tools-extra/clangd/unittests/Annotations.cpp
  clang-tools-extra/clangd/unittests/Annotations.h
  clang-tools-extra/clangd/unittests/tweaks/TweakTesting.cpp
  clang-tools-extra/clangd/unittests/tweaks/TweakTesting.h
  llvm/include/llvm/Testing/Support/Annotations.h
  llvm/lib/Testing/Support/Annotations.cpp
  llvm/unittests/Support/AnnotationsTest.cpp

Index: llvm/unittests/Support/AnnotationsTest.cpp
===
--- llvm/unittests/Support/AnnotationsTest.cpp
+++ llvm/unittests/Support/AnnotationsTest.cpp
@@ -25,10 +25,21 @@
   arg, result_listener);
 }
 
-llvm::Annotations::Range range(size_t Begin, size_t End) {
+llvm::Annotations::Point
+point(size_t Position, llvm::Optional Payload = llvm::None) {
+  llvm::Annotations::Point P;
+  P.Position = Position;
+  P.Payload = Payload;
+  return P;
+}
+
+llvm::Annotations::Range
+range(size_t Begin, size_t End,
+  llvm::Optional Payload = llvm::None) {
   llvm::Annotations::Range R;
   R.Begin = Begin;
   R.End = End;
+  R.Payload = Payload;
   return R;
 }
 
@@ -105,6 +116,32 @@
   ElementsAre(range(8, 9), range(7, 10), range(1, 10)));
 }
 
+TEST(AnnotationsTest, Payload) {
+  // A single unnamed point or range with empty payload
+  EXPECT_EQ(llvm::Annotations("a$^b").pointWithPayload(),
+point(1u, llvm::None));
+  EXPECT_EQ(llvm::Annotations("a$[[b]]cdef").range(), range(1, 2, llvm::None));
+
+  // A single unnamed point or range with payload.
+  EXPECT_EQ(llvm::Annotations("a$(foo)^b").pointWithPayload(),
+point(1u, {"foo"}));
+  EXPECT_EQ(llvm::Annotations("a$(foo)[[b]]cdef").range(),
+range(1, 2, {"foo"}));
+
+  // A single named point or range with payload
+  EXPECT_EQ(llvm::Annotations("a$name(foo)^b").pointWithPayload("name"),
+point(1u, {"foo"}));
+  EXPECT_EQ(llvm::Annotations("a$name(foo)[[b]]cdef").range("name"),
+range(1, 2, {"foo"}));
+
+  // Multiple named points with payload.
+  llvm::Annotations Annotated("a$p1(p1)^bcd$p2(p2)^123$p1^345");
+  EXPECT_THAT(Annotated.points(), IsEmpty());
+  EXPECT_THAT(Annotated.pointsWithPayload("p1"),
+  ElementsAre(point(1u, {"p1"}), point(7u, llvm::None)));
+  EXPECT_EQ(Annotated.pointWithPayload("p2"), point(4u, {"p2"}));
+}
+
 TEST(AnnotationsTest, Named) {
   // A single named point or range.
   EXPECT_EQ(llvm::Annotations("a$foo^b").point("foo"), 1u);
@@ -144,6 +181,8 @@
   EXPECT_DEATH(llvm::Annotations("ff[[fdfd"), "unmatched \\[\\[");
   EXPECT_DEATH(llvm::Annotations("ff[[fdjsfjd]]xxx]]"), "unmatched \\]\\]");
   EXPECT_DEATH(llvm::Annotations("ff$fdsfd"), "unterminated \\$name");
+  EXPECT_DEATH(llvm::Annotations("ff$("), "unterminated payload");
+  EXPECT_DEATH(llvm::Annotations("ff$name("), "unterminated payload");
 #endif
 }
 } // namespace
Index: llvm/lib/Testing/Support/Annotations.cpp
===
--- llvm/lib/Testing/Support/Annotations.cpp
+++ llvm/lib/Testing/Support/Annotations.cpp
@@ -28,27 +28,36 @@
 require(Assertion, Msg, Text);
   };
   llvm::Optional Name;
-  llvm::SmallVector, 8> OpenRanges;
+  llvm::Optional Payload;
+  struct OpenRange {
+llvm::StringRef Name;
+size_t Begin;
+llvm::Optional Payload;
+  };
+  llvm::SmallVector OpenRanges;
 
   Code.reserve(Text.size());
   while (!Text.empty()) {
 if (Text.consume_front("^")) {
-  Points[Name.value_or("")].push_back(Code.size());
+  Points[Name.value_or("")].push_back({Code.size(), Payload});
   Name = llvm::None;
+  Payload = llvm::None;
   continue;
 }
 if (Text.consume_front("[[")) {
-  OpenRanges.emplace_back(Name.value_or(""), Code.size());
+  OpenRanges.push_back({Name.value_or(""), Code.size(), Payload});
   Name = llvm::None;
+  Payload = llvm::None;
   continue;
 }
 Require(!Name, "$name should be followed by ^ or [[");
 if (Text.consume_front("]]")) {
   Require(!OpenRanges.empty(), "unmatched ]]");
   Range R;
-  R.Begin = OpenRanges.back().second;
+  R.Begin = OpenRanges.back().Begin;
   R.End = Code.size();
-  Ranges[OpenRanges.back().first].push_back(R);
+  R.Payload = OpenRanges.back().Payload;
+  Ranges[OpenRanges.back().Name].push_back(R);
   OpenRanges.pop_back();
   continue;
 }
@@ -56,6 +65,13 @@
   Name =
   Text.take_while([](char C) { return llvm::isAlnum(C) || C == '_'; });
   Text = Text.drop_front(Name->size());
+
+  if (Text.consume_front("(")) {
+Payload = Text.take_while([](char C) { return C != ')'; });
+Require(Text.size() > Payload->size(), 

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

2022-11-16 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 rG0e00611cbc2b: [clangd] Add heuristic for dropping snippet 
when completing member function… (authored by tom-anders).

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,6 +23,8 @@
 
 using namespace clang;
 using namespace clang::tooling;
+using ::testing::AllOf;
+using ::testing::Contains;
 using ::testing::Each;
 using ::testing::UnorderedElementsAre;
 
@@ -36,6 +38,51 @@
   std::string PtrDiffType;
 };
 
+struct CompletedFunctionDecl {
+  std::string Name;
+  bool IsStatic;
+  bool CanBeCall;
+};
+MATCHER_P(named, name, "") { return arg.Name == name; }
+MATCHER_P(isStatic, value, "") { return arg.IsStatic == value; }
+MATCHER_P(canBeCall, value, "") { return arg.CanBeCall == value; }
+
+class SaveCompletedFunctions : public CodeCompleteConsumer {
+public:
+  SaveCompletedFunctions(std::vector )
+  : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}),
+CompletedFuncDecls(CompletedFuncDecls),
+CCTUInfo(std::make_shared()) {}
+
+  void ProcessCodeCompleteResults(Sema , 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 () override {
+return CCTUInfo.getAllocator();
+  }
+
+  CodeCompletionTUInfo () override { return CCTUInfo; }
+
+  std::vector 
+
+  CodeCompletionTUInfo CCTUInfo;
+};
+
 class VisitedContextFinder : public CodeCompleteConsumer {
 public:
   VisitedContextFinder(CompletionContext )
@@ -74,19 +121,19 @@
 
 class CodeCompleteAction : public SyntaxOnlyAction {
 public:
-  CodeCompleteAction(ParsedSourceLocation P, CompletionContext )
-  : CompletePosition(std::move(P)), ResultCtx(ResultCtx) {}
+  CodeCompleteAction(ParsedSourceLocation P, CodeCompleteConsumer *Consumer)
+  : CompletePosition(std::move(P)), Consumer(Consumer) {}
 
   bool BeginInvocation(CompilerInstance ) override {
 CI.getFrontendOpts().CodeCompletionAt = CompletePosition;
-CI.setCodeCompletionConsumer(new VisitedContextFinder(ResultCtx));
+CI.setCodeCompletionConsumer(Consumer);
 return true;
   }
 
 private:
   // 1-based code complete position ;
   ParsedSourceLocation CompletePosition;
-  CompletionContext 
+  CodeCompleteConsumer *Consumer;
 };
 
 ParsedSourceLocation offsetToPosition(llvm::StringRef Code, size_t Offset) {
@@ -103,7 +150,7 @@
   CompletionContext ResultCtx;
   clang::tooling::runToolOnCodeWithArgs(
   std::make_unique(offsetToPosition(Code, Offset),
-   ResultCtx),
+   new VisitedContextFinder(ResultCtx)),
   Code, {"-std=c++11"}, TestCCName);
   return ResultCtx;
 }
@@ -129,6 +176,69 @@
   return Types;
 }
 
+std::vector
+CollectCompletedFunctions(StringRef Code, std::size_t Point) {
+  std::vector Result;
+  clang::tooling::runToolOnCodeWithArgs(
+  std::make_unique(offsetToPosition(Code, Point),
+   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^
+::$cannotBeCall^
+  }
+};
+
+int main() {
+  Foo f;
+  f.$canBeCall^
+  ::$cannotBeCall^
+}
+)cpp");
+
+  for (const auto  : Code.points("canBeCall")) {
+auto Results = CollectCompletedFunctions(Code.code(), P);
+EXPECT_THAT(Results, 

[PATCH] D137909: [Support] Allow complex names for annotation points and ranges via ${}

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

In D137909#3930043 , @sammccall wrote:

> What do you think about `$name(payload)^` for the general case, with 
> `$(payload)^`, `$name`, and `^` as abbreviated forms? I don't think the lack 
> of brackets on **names** hurts a lot if they stay simple, and if they're 
> "just labels" that don't have to carry arbitrary payloads then they can be 
> simple.

Thanks for the detailed feedback, I think this looks perfect! I adapted the 
code and docs accordingly (I added some comments to the parts I'm not sure 
about)

In D137909#3930047 , @sammccall wrote:

>> D137894 
>
> this looks cool! I left a couple of comments, mentioning here because phab 
> won't notify for comments on drafts.

Thanks! I replied to one of them :)




Comment at: clang-tools-extra/clangd/unittests/Annotations.h:30
 
+  struct Position : clangd::Position {
+llvm::Optional Payload;

I thought about just using `std::pair> instead, but that is pretty verbose and 
unreadable here IMO. Another nice thing about subclassing here is that we can 
keep the API stable and don't have to introduce  an additional 
`pointWithPayload()` getter like in the base class.



Comment at: llvm/include/llvm/Testing/Support/Annotations.h:61
 size_t End = 0;
+llvm::Optional Payload;
 

One could argue that this should just be `llvm::StringRef`. Right now, `$name^` 
results in `llvm::None` for the payload, while `$name()^` will yield an empty 
string.

Do you think they should just both be empty strings instead?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137909

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


[PATCH] D137909: [Support] Allow complex names for annotation points and ranges via ${}

2022-11-16 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 475922.
tom-anders added a comment.
Herald added subscribers: cfe-commits, arphaman.
Herald added a project: clang-tools-extra.

Keep name syntax, add optional payload instead


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137909

Files:
  clang-tools-extra/clangd/unittests/Annotations.cpp
  clang-tools-extra/clangd/unittests/Annotations.h
  clang-tools-extra/clangd/unittests/tweaks/TweakTesting.cpp
  clang-tools-extra/clangd/unittests/tweaks/TweakTesting.h
  llvm/include/llvm/Testing/Support/Annotations.h
  llvm/lib/Testing/Support/Annotations.cpp
  llvm/unittests/Support/AnnotationsTest.cpp

Index: llvm/unittests/Support/AnnotationsTest.cpp
===
--- llvm/unittests/Support/AnnotationsTest.cpp
+++ llvm/unittests/Support/AnnotationsTest.cpp
@@ -25,10 +25,21 @@
   arg, result_listener);
 }
 
-llvm::Annotations::Range range(size_t Begin, size_t End) {
+llvm::Annotations::Point
+point(size_t Position, llvm::Optional Payload = llvm::None) {
+  llvm::Annotations::Point P;
+  P.Position = Position;
+  P.Payload = Payload;
+  return P;
+}
+
+llvm::Annotations::Range
+range(size_t Begin, size_t End,
+  llvm::Optional Payload = llvm::None) {
   llvm::Annotations::Range R;
   R.Begin = Begin;
   R.End = End;
+  R.Payload = Payload;
   return R;
 }
 
@@ -105,6 +116,32 @@
   ElementsAre(range(8, 9), range(7, 10), range(1, 10)));
 }
 
+TEST(AnnotationsTest, Payload) {
+  // A single unnamed point or range with empty payload
+  EXPECT_EQ(llvm::Annotations("a$^b").pointWithPayload(),
+point(1u, llvm::None));
+  EXPECT_EQ(llvm::Annotations("a$[[b]]cdef").range(), range(1, 2, llvm::None));
+
+  // A single unnamed point or range with payload.
+  EXPECT_EQ(llvm::Annotations("a$(foo)^b").pointWithPayload(),
+point(1u, {"foo"}));
+  EXPECT_EQ(llvm::Annotations("a$(foo)[[b]]cdef").range(),
+range(1, 2, {"foo"}));
+
+  // A single named point or range with payload
+  EXPECT_EQ(llvm::Annotations("a$name(foo)^b").pointWithPayload("name"),
+point(1u, {"foo"}));
+  EXPECT_EQ(llvm::Annotations("a$name(foo)[[b]]cdef").range("name"),
+range(1, 2, {"foo"}));
+
+  // Multiple named points with payload.
+  llvm::Annotations Annotated("a$p1(p1)^bcd$p2(p2)^123$p1^345");
+  EXPECT_THAT(Annotated.points(), IsEmpty());
+  EXPECT_THAT(Annotated.pointsWithPayload("p1"),
+  ElementsAre(point(1u, {"p1"}), point(7u, llvm::None)));
+  EXPECT_EQ(Annotated.pointWithPayload("p2"), point(4u, {"p2"}));
+}
+
 TEST(AnnotationsTest, Named) {
   // A single named point or range.
   EXPECT_EQ(llvm::Annotations("a$foo^b").point("foo"), 1u);
@@ -144,6 +181,8 @@
   EXPECT_DEATH(llvm::Annotations("ff[[fdfd"), "unmatched \\[\\[");
   EXPECT_DEATH(llvm::Annotations("ff[[fdjsfjd]]xxx]]"), "unmatched \\]\\]");
   EXPECT_DEATH(llvm::Annotations("ff$fdsfd"), "unterminated \\$name");
+  EXPECT_DEATH(llvm::Annotations("ff$("), "unterminated payload");
+  EXPECT_DEATH(llvm::Annotations("ff$name("), "unterminated payload");
 #endif
 }
 } // namespace
Index: llvm/lib/Testing/Support/Annotations.cpp
===
--- llvm/lib/Testing/Support/Annotations.cpp
+++ llvm/lib/Testing/Support/Annotations.cpp
@@ -28,27 +28,36 @@
 require(Assertion, Msg, Text);
   };
   llvm::Optional Name;
-  llvm::SmallVector, 8> OpenRanges;
+  llvm::Optional Payload;
+  struct OpenRange {
+llvm::StringRef Name;
+size_t Begin;
+llvm::Optional Payload;
+  };
+  llvm::SmallVector OpenRanges;
 
   Code.reserve(Text.size());
   while (!Text.empty()) {
 if (Text.consume_front("^")) {
-  Points[Name.value_or("")].push_back(Code.size());
+  Points[Name.value_or("")].push_back({Code.size(), Payload});
   Name = llvm::None;
+  Payload = llvm::None;
   continue;
 }
 if (Text.consume_front("[[")) {
-  OpenRanges.emplace_back(Name.value_or(""), Code.size());
+  OpenRanges.push_back({Name.value_or(""), Code.size(), Payload});
   Name = llvm::None;
+  Payload = llvm::None;
   continue;
 }
 Require(!Name, "$name should be followed by ^ or [[");
 if (Text.consume_front("]]")) {
   Require(!OpenRanges.empty(), "unmatched ]]");
   Range R;
-  R.Begin = OpenRanges.back().second;
+  R.Begin = OpenRanges.back().Begin;
   R.End = Code.size();
-  Ranges[OpenRanges.back().first].push_back(R);
+  R.Payload = OpenRanges.back().Payload;
+  Ranges[OpenRanges.back().Name].push_back(R);
   OpenRanges.pop_back();
   continue;
 }
@@ -56,6 +65,13 @@
   Name =
   Text.take_while([](char C) { return llvm::isAlnum(C) || C == '_'; });
   Text = Text.drop_front(Name->size());
+
+  if (Text.consume_front("(")) {
+Payload = Text.take_while([](char C) { 

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

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



Comment at: 
clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp:212
   // Produce replacements to add the qualifiers.
   std::string Qualifier = printUsingNamespaceName(Ctx, *TargetDirective) + 
"::";
   for (auto Loc : IdentsToQualify) {

v1nh1shungry wrote:
> We can replace `printUsingNamespaceName` with `printNamespaceScope` here so 
> that we can get `a::foobar()` in the test. 
> 
> However, it can sometimes cause redundancy such as in the 10th test. 
> 
> And I don't know whether it is worth it. WDYT?
Just making sure I understood this correctly:

If you replace `printUsingNamespaceName` with `printNamespaceScope`, then...

- ...in the test you added it would result in `a::foobar()` instead of 
`a::b::foobar()` (which is better)
- ... but in this test (which is the 10th test if I counted correctly):
 
```
 namespace a::b { struct Foo {}; }
  using namespace a;
  using namespace a::[[b]];
  using namespace b;
  int main() { Foo F;}
```
what would be the result..? would you get `a::Foo` instead of `a::b::Foo`?



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] D137817: [clangd] Improve action `RemoveUsingNamespace` for user-defined literals

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

LGTM, but I'll give @kadircet a chance to review as well


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137817

___
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-14 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders added a comment.

In D137040#3924115 , @nridge wrote:

> Thanks!

Thanks for the review!


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-13 Thread Tom Praschan via Phabricator via cfe-commits
tom-anders updated this revision to Diff 474990.
tom-anders added a comment.

Clean up test


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,6 +23,8 @@
 
 using namespace clang;
 using namespace clang::tooling;
+using ::testing::AllOf;
+using ::testing::Contains;
 using ::testing::Each;
 using ::testing::UnorderedElementsAre;
 
@@ -36,6 +38,51 @@
   std::string PtrDiffType;
 };
 
+struct CompletedFunctionDecl {
+  std::string Name;
+  bool IsStatic;
+  bool CanBeCall;
+};
+MATCHER_P(named, name, "") { return arg.Name == name; }
+MATCHER_P(isStatic, value, "") { return arg.IsStatic == value; }
+MATCHER_P(canBeCall, value, "") { return arg.CanBeCall == value; }
+
+class SaveCompletedFunctions : public CodeCompleteConsumer {
+public:
+  SaveCompletedFunctions(std::vector )
+  : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}),
+CompletedFuncDecls(CompletedFuncDecls),
+CCTUInfo(std::make_shared()) {}
+
+  void ProcessCodeCompleteResults(Sema , 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 () override {
+return CCTUInfo.getAllocator();
+  }
+
+  CodeCompletionTUInfo () override { return CCTUInfo; }
+
+  std::vector 
+
+  CodeCompletionTUInfo CCTUInfo;
+};
+
 class VisitedContextFinder : public CodeCompleteConsumer {
 public:
   VisitedContextFinder(CompletionContext )
@@ -74,19 +121,19 @@
 
 class CodeCompleteAction : public SyntaxOnlyAction {
 public:
-  CodeCompleteAction(ParsedSourceLocation P, CompletionContext )
-  : CompletePosition(std::move(P)), ResultCtx(ResultCtx) {}
+  CodeCompleteAction(ParsedSourceLocation P, CodeCompleteConsumer *Consumer)
+  : CompletePosition(std::move(P)), Consumer(Consumer) {}
 
   bool BeginInvocation(CompilerInstance ) override {
 CI.getFrontendOpts().CodeCompletionAt = CompletePosition;
-CI.setCodeCompletionConsumer(new VisitedContextFinder(ResultCtx));
+CI.setCodeCompletionConsumer(Consumer);
 return true;
   }
 
 private:
   // 1-based code complete position ;
   ParsedSourceLocation CompletePosition;
-  CompletionContext 
+  CodeCompleteConsumer *Consumer;
 };
 
 ParsedSourceLocation offsetToPosition(llvm::StringRef Code, size_t Offset) {
@@ -103,7 +150,7 @@
   CompletionContext ResultCtx;
   clang::tooling::runToolOnCodeWithArgs(
   std::make_unique(offsetToPosition(Code, Offset),
-   ResultCtx),
+   new VisitedContextFinder(ResultCtx)),
   Code, {"-std=c++11"}, TestCCName);
   return ResultCtx;
 }
@@ -129,6 +176,69 @@
   return Types;
 }
 
+std::vector
+CollectCompletedFunctions(StringRef Code, std::size_t Point) {
+  std::vector Result;
+  clang::tooling::runToolOnCodeWithArgs(
+  std::make_unique(offsetToPosition(Code, Point),
+   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^
+::$cannotBeCall^
+  }
+};
+
+int main() {
+  Foo f;
+  f.$canBeCall^
+  ::$cannotBeCall^
+}
+)cpp");
+
+  for (const auto  : Code.points("canBeCall")) {
+auto Results = CollectCompletedFunctions(Code.code(), P);
+EXPECT_THAT(Results, Contains(AllOf(named("method"), isStatic(false),
+canBeCall(true;
+  }
+
+  for (const auto  : Code.points("cannotBeCall")) {
+auto Results = 

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

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

Fix test


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 )
+  : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}),
+CompletedFuncDecls(CompletedFuncDecls),
+CCTUInfo(std::make_shared()) {}
+
+  void ProcessCodeCompleteResults(Sema , 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 () override {
+return CCTUInfo.getAllocator();
+  }
+
+  CodeCompletionTUInfo () override { return CCTUInfo; }
+
+  std::vector 
+
+  CodeCompletionTUInfo CCTUInfo;
+};
+
 class VisitedContextFinder : public CodeCompleteConsumer {
 public:
   VisitedContextFinder(CompletionContext )
@@ -74,12 +119,15 @@
 
 class CodeCompleteAction : public SyntaxOnlyAction {
 public:
-  CodeCompleteAction(ParsedSourceLocation P, CompletionContext )
-  : CompletePosition(std::move(P)), ResultCtx(ResultCtx) {}
+  CodeCompleteAction(ParsedSourceLocation P, CompletionContext ,
+ CodeCompleteConsumer *Consumer = nullptr)
+  : CompletePosition(std::move(P)), ResultCtx(ResultCtx),
+Consumer(Consumer) {}
 
   bool BeginInvocation(CompilerInstance ) 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 
+  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^
+::$cannotBeCall^
+  }
+};
+
+int main() {
+  Foo f;
+  f.$canBeCall^
+  ::$cannotBeCall^
+}
+)cpp");
+
+  for (const auto  : Code.points("canBeCall")) {
+auto Results = CollectCompletedFunctions(Code.code(), P);
+EXPECT_THAT(
+Results,
+Contains(AllOf(
+Field("Name", ::Name, "method"),
+Field("IsStatic", ::IsStatic, false),
+Field("CanBeCall", ::CanBeCall, true;
+  }
+
+  for (const auto  : Code.points("cannotBeCall")) {
+auto Results = CollectCompletedFunctions(Code.code(), P);
+EXPECT_THAT(
+Results,
+Contains(AllOf(
+Field("Name", ::Name, "method"),
+

[PATCH] D137817: [clangd] Improve action `RemoveUsingNamespace` for user-defined literals

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

This looks really cool :)




Comment at: 
clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp:133
+  std::string Directives;
+  for (auto  : UsingToAdd)
+Directives += llvm::formatv("using namespace {0};\n", Using);

nit: `const auto`



Comment at: 
clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp:249
 
+  llvm::sort(UsingToAdd);
+  UsingToAdd.erase(std::unique(UsingToAdd.begin(), UsingToAdd.end()),

If you're sorting and removing duplicates in the end anyway, maybe [[ 
https://llvm.org/doxygen/classllvm_1_1StringSet.html | llvm::StringSet ]] would 
be a better fit instead of `vector`?



Comment at: 
clang-tools-extra/clangd/unittests/tweaks/RemoveUsingNamespaceTests.cpp:286
+  using namespace ns1::ns2;
   int main() { 1.5_w; }
 )cpp"}};

Your code also handles cases where there are multiple inline namespaces 
involved, right? If so, it would be a good idea also test this here (i.e. add 
ns3 with another user-defined literal)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D137817

___
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 string literals

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

In D137650#3919089 , @kadircet wrote:

> sure i am happy to land, @tom-anders do you have anything else to add ?

LGTM!


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] 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 added a comment.

Hmm I added the test for the flag to Sema, but now we kinda have the same test 
case duplicated in sema and clangd tests - I guess for clangd we now actually 
only have to test that the SnippetSuffix is cleared when FunctionCanBeCall is 
true, but I don't see an easy way to somehow inject fake Sema results into 
CodeComplete.cpp


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-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 )
+  : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}),
+CompletedFuncDecls(CompletedFuncDecls),
+CCTUInfo(std::make_shared()) {}
+
+  void ProcessCodeCompleteResults(Sema , 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 () override {
+return CCTUInfo.getAllocator();
+  }
+
+  CodeCompletionTUInfo () override { return CCTUInfo; }
+
+  std::vector 
+
+  CodeCompletionTUInfo CCTUInfo;
+};
+
 class VisitedContextFinder : public CodeCompleteConsumer {
 public:
   VisitedContextFinder(CompletionContext )
@@ -74,12 +119,15 @@
 
 class CodeCompleteAction : public SyntaxOnlyAction {
 public:
-  CodeCompleteAction(ParsedSourceLocation P, CompletionContext )
-  : CompletePosition(std::move(P)), ResultCtx(ResultCtx) {}
+  CodeCompleteAction(ParsedSourceLocation P, CompletionContext ,
+ CodeCompleteConsumer *Consumer = nullptr)
+  : CompletePosition(std::move(P)), ResultCtx(ResultCtx),
+Consumer(Consumer) {}
 
   bool BeginInvocation(CompilerInstance ) 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 
+  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^
+::$cannotBeCall^
+  }
+};
+
+int main() {
+  Foo f;
+  f.$canBeCall^
+  ::$cannotBeCall^
+}
+)cpp");
+
+  for (const auto  : Code.points("canBeCall")) {
+auto Results = CollectCompletedFunctions(Code.code(), P);
+EXPECT_THAT(
+Results,
+Contains(AllOf(
+Field("Name", ::Name, "method"),
+Field("IsStatic", ::IsStatic, false),
+Field("CanBeCall", ::CanBeCall, true;
+  }
+
+  for (const auto  : Code.points("keepSnippet")) {
+auto Results = CollectCompletedFunctions(Code.code(), P);
+EXPECT_THAT(
+Results,
+Contains(AllOf(
+Field("Name", ::Name, "method"),
+

[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 

[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-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] 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] 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-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] 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
, 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] 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: 

[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] 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
+++ 

[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
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 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] 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] 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-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-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] 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 ) {
-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())
@@ -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 ) {
-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 

[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 = 

[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 ) {
-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())
@@ -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 ) {
-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] 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] 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 

[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^
+  ::$noSnippet^
+}
+  };
+
+  int main() {
+Foo f;
+f.$keepSnippet^
+::$noSnippet^
+  }
+  )cpp");
+  auto TU = TestTU::withCode(Code.code());
+
+  for (const auto  : Code.points("noSnippet")) {
+auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
+EXPECT_THAT(Results.Completions,
+Contains(AllOf(named("method"), snippetSuffix("";
+  }
+
+  for (const auto  : 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  : 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 ,
+  CodeCompletionBuilder(ASTContext *ASTCtx, DeclContext *SemaDeclCtx,
+const CompletionCandidate ,
 CodeCompletionString *SemaCCS,
 llvm::ArrayRef QueryScopes,
 const IncludeInserter ,
@@ -299,13 +300,15 @@
 CodeCompletionContext::Kind ContextKind,
 const CodeCompleteOptions ,
 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, , ,
, 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 @@
 return "(…)";
   }
 
+  // Clear snippet when completing a non-static member function (and 

[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] 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] 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] 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


  1   2   >