[PATCH] D43303: [Format] Fix for bug 35641

2018-02-14 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added reviewers: rsmith, djasper.
kadircet added a project: clang.
Herald added a subscriber: cfe-commits.

Bug was caused due to comments at the start of scope. For a code like:

  int func() { //
int b;
int c;
  }

the comment at the first line gets IndentAndNestingLevel (1,1) whereas 
the following declarations get only (0,1) which prevents them from insertion
of a new scope. So, I changed the AlignTokenSequence to look at previous 
*non-comment* token when deciding whether to introduce a new scope into
stack or not.


Repository:
  rC Clang

https://reviews.llvm.org/D43303

Files:
  lib/Format/WhitespaceManager.cpp
  unittests/Format/FormatTest.cpp


Index: unittests/Format/FormatTest.cpp
===
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -9449,6 +9449,14 @@
   "});\n",
   Alignment);
   Alignment.PointerAlignment = FormatStyle::PAS_Right;
+
+  // Bug 35641
+  Alignment.AlignConsecutiveDeclarations = true;
+  verifyFormat("int func() { //\n"
+   "  int b;\n"
+   "  int c;\n"
+   "}",
+   Alignment);
 }
 
 TEST_F(FormatTest, LinuxBraceBreaking) {
Index: lib/Format/WhitespaceManager.cpp
===
--- lib/Format/WhitespaceManager.cpp
+++ lib/Format/WhitespaceManager.cpp
@@ -255,8 +255,14 @@
 Changes[ScopeStack.back()].indentAndNestingLevel())
   ScopeStack.pop_back();
 
+// Compare current token to previous non-comment token to ensure whether
+// it is in a deeper scope or not.
+unsigned PreviousNonComment = i - 1;
+while (PreviousNonComment > Start &&
+   Changes[PreviousNonComment].Tok->is(tok::comment))
+  PreviousNonComment--;
 if (i != Start && Changes[i].indentAndNestingLevel() >
-  Changes[i - 1].indentAndNestingLevel())
+  Changes[PreviousNonComment].indentAndNestingLevel())
   ScopeStack.push_back(i);
 
 bool InsideNestedScope = ScopeStack.size() != 0;


Index: unittests/Format/FormatTest.cpp
===
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -9449,6 +9449,14 @@
   "});\n",
   Alignment);
   Alignment.PointerAlignment = FormatStyle::PAS_Right;
+
+  // Bug 35641
+  Alignment.AlignConsecutiveDeclarations = true;
+  verifyFormat("int func() { //\n"
+   "  int b;\n"
+   "  int c;\n"
+   "}",
+   Alignment);
 }
 
 TEST_F(FormatTest, LinuxBraceBreaking) {
Index: lib/Format/WhitespaceManager.cpp
===
--- lib/Format/WhitespaceManager.cpp
+++ lib/Format/WhitespaceManager.cpp
@@ -255,8 +255,14 @@
 Changes[ScopeStack.back()].indentAndNestingLevel())
   ScopeStack.pop_back();
 
+// Compare current token to previous non-comment token to ensure whether
+// it is in a deeper scope or not.
+unsigned PreviousNonComment = i - 1;
+while (PreviousNonComment > Start &&
+   Changes[PreviousNonComment].Tok->is(tok::comment))
+  PreviousNonComment--;
 if (i != Start && Changes[i].indentAndNestingLevel() >
-  Changes[i - 1].indentAndNestingLevel())
+  Changes[PreviousNonComment].indentAndNestingLevel())
   ScopeStack.push_back(i);
 
 bool InsideNestedScope = ScopeStack.size() != 0;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D43303: [Format] Fix for bug 35641

2018-02-15 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 134414.
kadircet added a comment.

Changed description of unit test to include direct link to bug.
Used different variable types to make sure alignment happens.


Repository:
  rC Clang

https://reviews.llvm.org/D43303

Files:
  unittests/Format/FormatTest.cpp


Index: unittests/Format/FormatTest.cpp
===
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -9450,11 +9450,11 @@
   Alignment);
   Alignment.PointerAlignment = FormatStyle::PAS_Right;
 
-  // Bug 35641
+  // See llvm.org/PR35641
   Alignment.AlignConsecutiveDeclarations = true;
   verifyFormat("int func() { //\n"
-   "  int b;\n"
-   "  int c;\n"
+   "  int  b;\n"
+   "  unsigned c;\n"
"}",
Alignment);
 }


Index: unittests/Format/FormatTest.cpp
===
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -9450,11 +9450,11 @@
   Alignment);
   Alignment.PointerAlignment = FormatStyle::PAS_Right;
 
-  // Bug 35641
+  // See llvm.org/PR35641
   Alignment.AlignConsecutiveDeclarations = true;
   verifyFormat("int func() { //\n"
-   "  int b;\n"
-   "  int c;\n"
+   "  int  b;\n"
+   "  unsigned c;\n"
"}",
Alignment);
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D43303: [Format] Fix for bug 35641

2018-02-18 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added a comment.

Btw, I cannot commit the change myself, don't have commit rights.


Repository:
  rC Clang

https://reviews.llvm.org/D43303



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


[PATCH] D43303: [Format] Fix for bug 35641

2018-02-18 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 134830.
kadircet added a comment.

Rebased and uploaded diff to the master. Sorry for the inconvenience.


Repository:
  rC Clang

https://reviews.llvm.org/D43303

Files:
  lib/Format/WhitespaceManager.cpp
  unittests/Format/FormatTest.cpp


Index: unittests/Format/FormatTest.cpp
===
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -9449,6 +9449,14 @@
   "});\n",
   Alignment);
   Alignment.PointerAlignment = FormatStyle::PAS_Right;
+
+  // See llvm.org/PR35641
+  Alignment.AlignConsecutiveDeclarations = true;
+  verifyFormat("int func() { //\n"
+   "  int  b;\n"
+   "  unsigned c;\n"
+   "}",
+   Alignment);
 }
 
 TEST_F(FormatTest, LinuxBraceBreaking) {
Index: lib/Format/WhitespaceManager.cpp
===
--- lib/Format/WhitespaceManager.cpp
+++ lib/Format/WhitespaceManager.cpp
@@ -255,8 +255,14 @@
 Changes[ScopeStack.back()].indentAndNestingLevel())
   ScopeStack.pop_back();
 
+// Compare current token to previous non-comment token to ensure whether
+// it is in a deeper scope or not.
+unsigned PreviousNonComment = i - 1;
+while (PreviousNonComment > Start &&
+   Changes[PreviousNonComment].Tok->is(tok::comment))
+  PreviousNonComment--;
 if (i != Start && Changes[i].indentAndNestingLevel() >
-  Changes[i - 1].indentAndNestingLevel())
+  Changes[PreviousNonComment].indentAndNestingLevel())
   ScopeStack.push_back(i);
 
 bool InsideNestedScope = ScopeStack.size() != 0;


Index: unittests/Format/FormatTest.cpp
===
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -9449,6 +9449,14 @@
   "});\n",
   Alignment);
   Alignment.PointerAlignment = FormatStyle::PAS_Right;
+
+  // See llvm.org/PR35641
+  Alignment.AlignConsecutiveDeclarations = true;
+  verifyFormat("int func() { //\n"
+   "  int  b;\n"
+   "  unsigned c;\n"
+   "}",
+   Alignment);
 }
 
 TEST_F(FormatTest, LinuxBraceBreaking) {
Index: lib/Format/WhitespaceManager.cpp
===
--- lib/Format/WhitespaceManager.cpp
+++ lib/Format/WhitespaceManager.cpp
@@ -255,8 +255,14 @@
 Changes[ScopeStack.back()].indentAndNestingLevel())
   ScopeStack.pop_back();
 
+// Compare current token to previous non-comment token to ensure whether
+// it is in a deeper scope or not.
+unsigned PreviousNonComment = i - 1;
+while (PreviousNonComment > Start &&
+   Changes[PreviousNonComment].Tok->is(tok::comment))
+  PreviousNonComment--;
 if (i != Start && Changes[i].indentAndNestingLevel() >
-  Changes[i - 1].indentAndNestingLevel())
+  Changes[PreviousNonComment].indentAndNestingLevel())
   ScopeStack.push_back(i);
 
 bool InsideNestedScope = ScopeStack.size() != 0;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50193: Added functionality to suggest FixIts for conversion of '->' to '.' and vice versa.

2018-08-02 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added a reviewer: ilya-biryukov.
Herald added subscribers: cfe-commits, arphaman, jkorous, ioeric.

Added functionality to suggest FixIts for conversion of '->' to '.' and vice 
versa.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50193

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/Diagnostics.cpp
  clangd/Protocol.h
  clangd/SourceCode.cpp
  clangd/SourceCode.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -477,7 +477,8 @@
 
 TEST(CompletionTest, ReferencesAffectRanking) {
   auto Results = completions("int main() { abs^ }", {ns("absl"), func("absb")});
-  EXPECT_THAT(Results.Completions, HasSubsequence(Named("absb"), Named("absl")));
+  EXPECT_THAT(Results.Completions,
+  HasSubsequence(Named("absb"), Named("absl")));
   Results = completions("int main() { abs^ }",
 {withReferences(1, ns("absl")), func("absb")});
   EXPECT_THAT(Results.Completions,
@@ -1338,6 +1339,78 @@
   EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
 }
 
+TEST(CompletionTest, FixItForArrowToDot) {
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  auto Results = completions(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const { return Aux; }
+ private:
+  Auxilary* Aux;
+};
+namespace ns {
+  void f() {
+ClassWithPtr x;
+x->MemberFunction^;
+  }
+}
+  )cpp",
+  {}, Opts);
+  EXPECT_EQ(Results.Completions.size(), 1u);
+
+  TextEdit ReplacementEdit;
+  ReplacementEdit.range.start.line = 15;
+  ReplacementEdit.range.start.character = 13;
+  ReplacementEdit.range.end.line = 15;
+  ReplacementEdit.range.end.character = 15;
+  ReplacementEdit.newText = ".";
+  const auto  = Results.Completions.front();
+  EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
+}
+
+TEST(CompletionTest, FixItForDotToArrow) {
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  auto Results = completions(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const { return Aux; }
+ private:
+  Auxilary* Aux;
+};
+namespace ns {
+  void f() {
+ClassWithPtr x;
+x.AuxFunction^;
+  }
+}
+  )cpp",
+  {}, Opts);
+  EXPECT_EQ(Results.Completions.size(), 1u);
+
+  TextEdit ReplacementEdit;
+  ReplacementEdit.range.start.line = 15;
+  ReplacementEdit.range.start.character = 13;
+  ReplacementEdit.range.end.line = 15;
+  ReplacementEdit.range.end.character = 14;
+  ReplacementEdit.newText = "->";
+  const auto  = Results.Completions.front();
+  EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/SourceCode.h
===
--- clangd/SourceCode.h
+++ clangd/SourceCode.h
@@ -13,6 +13,7 @@
 //===--===//
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
+#include "Diagnostics.h"
 #include "Protocol.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Tooling/Core/Replacement.h"
@@ -64,6 +65,10 @@
 /// Get the absolute file path of a given file entry.
 llvm::Optional getAbsoluteFilePath(const FileEntry *F,
 const SourceManager );
+
+TextEdit toTextEdit(const FixItHint , const SourceManager ,
+const LangOptions );
+
 } // namespace clangd
 } // namespace clang
 #endif
Index: clangd/SourceCode.cpp
===
--- clangd/SourceCode.cpp
+++ clangd/SourceCode.cpp
@@ -8,6 +8,7 @@
 //===--===//
 #include "SourceCode.h"
 
+#include "Diagnostics.h"
 #include "Logger.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/Basic/SourceManager.h"
@@ -199,5 +200,14 @@
   return FilePath.str().str();
 }
 
+TextEdit toTextEdit(const FixItHint , const SourceManager ,
+const LangOptions ) {
+  TextEdit Result;
+  Result.range =
+  halfOpenToRange(M, Lexer::makeFileCharRange(FixIt.RemoveRange, M, L));
+  Result.newText = FixIt.CodeToInsert;
+  return Result;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/Protocol.h

[PATCH] D50193: Added functionality to suggest FixIts for conversion of '->' to '.' and vice versa.

2018-08-03 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 159000.
kadircet marked 8 inline comments as done.
kadircet added a comment.

Fixed discussions


https://reviews.llvm.org/D50193

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/Diagnostics.cpp
  clangd/Protocol.h
  clangd/SourceCode.cpp
  clangd/SourceCode.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -79,7 +79,7 @@
   return MemIndex::build(std::move(Slab).build());
 }
 
-CodeCompleteResult completions(ClangdServer , StringRef Text,
+CodeCompleteResult completions(ClangdServer , Annotations Test,
std::vector IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {}) {
   std::unique_ptr OverrideIndex;
@@ -90,23 +90,35 @@
   }
 
   auto File = testPath("foo.cpp");
-  Annotations Test(Text);
   runAddDocument(Server, File, Test.code());
   auto CompletionList =
   cantFail(runCodeComplete(Server, File, Test.point(), Opts));
   return CompletionList;
 }
 
+CodeCompleteResult completions(ClangdServer , StringRef Text,
+   std::vector IndexSymbols = {},
+   clangd::CodeCompleteOptions Opts = {}) {
+  return completions(Server, Annotations(Text), IndexSymbols, Opts);
+}
+
 // Builds a server and runs code completion.
 // If IndexSymbols is non-empty, an index will be built and passed to opts.
-CodeCompleteResult completions(StringRef Text,
+CodeCompleteResult completions(Annotations Test,
std::vector IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {}) {
   MockFSProvider FS;
   MockCompilationDatabase CDB;
   IgnoreDiagnostics DiagConsumer;
   ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
-  return completions(Server, Text, std::move(IndexSymbols), std::move(Opts));
+  return completions(Server, Test, std::move(IndexSymbols), std::move(Opts));
+}
+
+CodeCompleteResult completions(StringRef Text,
+   std::vector IndexSymbols = {},
+   clangd::CodeCompleteOptions Opts = {}) {
+  return completions(Annotations(Text), std::move(IndexSymbols),
+ std::move(Opts));
 }
 
 std::string replace(StringRef Haystack, StringRef Needle, StringRef Repl) {
@@ -1338,6 +1350,74 @@
   EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
 }
 
+TEST(CompletionTest, FixItForArrowToDot) {
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  Annotations TestCode(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const;
+  Auxilary* Aux;
+};
+void f() {
+  ClassWithPtr x;
+  x[[->]]^;
+}
+  )cpp");
+  auto Results = completions(TestCode, {}, Opts);
+  EXPECT_EQ(Results.Completions.size(), 3u);
+
+  TextEdit ReplacementEdit;
+  ReplacementEdit.range = TestCode.range();
+  ReplacementEdit.newText = ".";
+  for (const auto  : Results.Completions) {
+EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
+if (!C.FixIts.empty()) {
+  EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
+}
+  }
+}
+
+TEST(CompletionTest, FixItForDotToArrow) {
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  Annotations TestCode(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const;
+  Auxilary* Aux;
+};
+void f() {
+  ClassWithPtr x;
+  x[[.]]^;
+}
+  )cpp");
+  auto Results = completions(TestCode, {}, Opts);
+  EXPECT_EQ(Results.Completions.size(), 3u);
+
+  TextEdit ReplacementEdit;
+  ReplacementEdit.range = TestCode.range();
+  ReplacementEdit.newText = "->";
+  for (const auto  : Results.Completions) {
+EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
+if (!C.FixIts.empty()) {
+  EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
+}
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/SourceCode.h
===
--- clangd/SourceCode.h
+++ clangd/SourceCode.h
@@ -13,6 +13,7 @@
 //===--===//
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
+#include "Diagnostics.h"
 #include "Protocol.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Tooling/Core/Replacement.h"
@@ -64,6 

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-09 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added a reviewer: ilya-biryukov.
Herald added subscribers: cfe-commits, jfb, arphaman, jkorous, MaskRay, ioeric, 
mgorny.

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,34 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  {
+std::shared_ptr> CancellationToken =
+std::make_shared>();
+WithContext ContextWithCancellation(
+CancellationHandler::SetCurrentCancellationToken(CancellationToken));
+*CancellationToken = true;
+EXPECT_TRUE(CancellationHandler::HasCancelled());
+  }
+  EXPECT_FALSE(CancellationHandler::HasCancelled());
+}
+
+TEST(CancellationTest, CheckForError) {
+  llvm::Error e = handleErrors(CancellationHandler::GetCancellationError(),
+   [](const TaskCancelledError &) {});
+  EXPECT_TRUE(!e);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -846,6 +846,13 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Protocol.cpp
===
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -605,5 +605,31 @@
  O.map("compilationDatabaseChanges", CCPC.compilationDatabaseChanges);
 }
 
+json::Value toJSON(const CancelParams ) {
+  return json::Object{{"id", CP.ID}};
+}
+
+llvm::raw_ostream <<(llvm::raw_ostream , const CancelParams ) {
+  O << toJSON(CP);
+  return O;
+}
+
+bool fromJSON(const json::Value , CancelParams ) {
+  elog("Cancel params: {0}", Params);
+  json::ObjectMapper O(Params);
+  if (!O)
+return false;
+  // ID is either a number or a string, check for both.
+  if (O.map("id", CP.ID))
+return true;
+
+  int64_t id_number;
+  if (O.map("id", id_number)) {
+CP.ID = utostr(id_number);
+return true;
+  }
+  return false;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/JSONRPCDispatcher.h
===
--- clangd/JSONRPCDispatcher.h
+++ clangd/JSONRPCDispatcher.h
@@ -111,6 +111,7 @@
JSONStreamStyle InputStyle,
JSONRPCDispatcher , bool );
 
+const llvm::json::Value *GetRequestId();
 } // namespace clangd
 } // namespace clang
 
Index: clangd/JSONRPCDispatcher.cpp
===
--- clangd/JSONRPCDispatcher.cpp
+++ clangd/JSONRPCDispatcher.cpp
@@ -8,6 +8,7 @@
 //===--===//
 
 

[PATCH] D50449: [clangd] Support textEdit in addition to insertText.

2018-08-08 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added a reviewer: ilya-biryukov.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, ioeric.

Completion replies contains textEdits as well. Note that this change
relies on https://reviews.llvm.org/D50443.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50449

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/SourceCode.cpp
  clangd/SourceCode.h
  unittests/clangd/CodeCompleteTests.cpp
  unittests/clangd/SourceCodeTests.cpp

Index: unittests/clangd/SourceCodeTests.cpp
===
--- unittests/clangd/SourceCodeTests.cpp
+++ unittests/clangd/SourceCodeTests.cpp
@@ -37,6 +37,14 @@
   return Pos;
 }
 
+Range range(const std::pair p1,
+const std::pair p2) {
+  Range range;
+  range.start = position(p1.first, p1.second);
+  range.end = position(p2.first, p2.second);
+  return range;
+}
+
 TEST(SourceCodeTests, PositionToOffset) {
   // line out of bounds
   EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), Failed());
@@ -119,6 +127,14 @@
   EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 9)) << "out of bounds";
 }
 
+TEST(SourceCodeTests, IsRangeConsecutive) {
+  EXPECT_TRUE(IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 3}, {2, 4})));
+  EXPECT_FALSE(
+  IsRangeConsecutive(range({0, 2}, {0, 3}), range({2, 3}, {2, 4})));
+  EXPECT_FALSE(
+  IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 4}, {2, 5})));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1438,6 +1438,82 @@
   }
 }
 
+TEST(CompletionTest, RenderWithFixItMerged) {
+  TextEdit FixIt;
+  FixIt.range.end.character = 5;
+  FixIt.newText = "->";
+
+  CodeCompletion C;
+  C.Name = "x";
+  C.RequiredQualifier = "Foo::";
+  C.FixIts = {FixIt};
+  C.textEdit.range.start.character = 5;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto R = C.render(Opts);
+  EXPECT_TRUE(R.textEdit);
+  EXPECT_EQ(R.textEdit->newText, "->Foo::x");
+  EXPECT_TRUE(R.additionalTextEdits.empty());
+}
+
+TEST(CompletionTest, RenderWithFixItNonMerged) {
+  TextEdit FixIt;
+  FixIt.range.end.character = 4;
+  FixIt.newText = "->";
+
+  CodeCompletion C;
+  C.Name = "x";
+  C.RequiredQualifier = "Foo::";
+  C.FixIts = {FixIt};
+  C.textEdit.range.start.character = 5;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto R = C.render(Opts);
+  EXPECT_TRUE(R.textEdit);
+  EXPECT_EQ(R.textEdit->newText, "Foo::x");
+  EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
+}
+
+TEST(CompletionTest, CompletionTokenRange) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  constexpr const char *TestCodes[] = {
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+void f() {
+  Auxilary x;
+  x.[[Aux]]^;
+}
+  )cpp",
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+void f() {
+  Auxilary x;
+  x.[[]]^;
+}
+  )cpp"};
+  for (const auto  : TestCodes) {
+Annotations TestCode(Text);
+auto Results = completions(Server, TestCode.code(), TestCode.point());
+
+EXPECT_EQ(Results.Completions.size(), 1u);
+EXPECT_THAT(Results.Completions.front().textEdit.range, TestCode.range());
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/SourceCode.h
===
--- clangd/SourceCode.h
+++ clangd/SourceCode.h
@@ -69,6 +69,7 @@
 TextEdit toTextEdit(const FixItHint , const SourceManager ,
 const LangOptions );
 
+bool IsRangeConsecutive(const Range , const Range );
 } // namespace clangd
 } // namespace clang
 #endif
Index: clangd/SourceCode.cpp
===
--- clangd/SourceCode.cpp
+++ clangd/SourceCode.cpp
@@ -208,5 +208,10 @@
   return Result;
 }
 
+bool IsRangeConsecutive(const Range , const Range ) {
+  return Left.end.line == Right.start.line &&
+ Left.end.character == Right.start.character;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -123,6 +123,8 @@
   /// converting '->' to '.' on member access.
   std::vector FixIts;
 
+  TextEdit textEdit;
+
   // Scores are used to rank completion items.
   struct Scores {
 // The score that items are ranked by.
Index: clangd/CodeComplete.cpp

[PATCH] D50193: Added functionality to suggest FixIts for conversion of '->' to '.' and vice versa.

2018-08-08 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCTE339224: Added functionality to suggest FixIts for 
conversion of - to . and viceā€¦ (authored by 
kadircet, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D50193?vs=159648=159655#toc

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50193

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/Diagnostics.cpp
  clangd/Protocol.h
  clangd/Quality.cpp
  clangd/Quality.h
  clangd/SourceCode.cpp
  clangd/SourceCode.h
  unittests/clangd/CodeCompleteTests.cpp
  unittests/clangd/QualityTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -79,6 +79,23 @@
   return MemIndex::build(std::move(Slab).build());
 }
 
+CodeCompleteResult completions(ClangdServer , StringRef TestCode,
+   Position point,
+   std::vector IndexSymbols = {},
+   clangd::CodeCompleteOptions Opts = {}) {
+  std::unique_ptr OverrideIndex;
+  if (!IndexSymbols.empty()) {
+assert(!Opts.Index && "both Index and IndexSymbols given!");
+OverrideIndex = memIndex(std::move(IndexSymbols));
+Opts.Index = OverrideIndex.get();
+  }
+
+  auto File = testPath("foo.cpp");
+  runAddDocument(Server, File, TestCode);
+  auto CompletionList = cantFail(runCodeComplete(Server, File, point, Opts));
+  return CompletionList;
+}
+
 CodeCompleteResult completions(ClangdServer , StringRef Text,
std::vector IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {}) {
@@ -1342,6 +1359,85 @@
   EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
 }
 
+TEST(CompletionTest, FixItForArrowToDot) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  Annotations TestCode(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const;
+  Auxilary* Aux;
+};
+void f() {
+  ClassWithPtr x;
+  x[[->]]^;
+}
+  )cpp");
+  auto Results =
+  completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
+  EXPECT_EQ(Results.Completions.size(), 3u);
+
+  TextEdit ReplacementEdit;
+  ReplacementEdit.range = TestCode.range();
+  ReplacementEdit.newText = ".";
+  for (const auto  : Results.Completions) {
+EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
+if (!C.FixIts.empty())
+  EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
+  }
+}
+
+TEST(CompletionTest, FixItForDotToArrow) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  Annotations TestCode(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const;
+  Auxilary* Aux;
+};
+void f() {
+  ClassWithPtr x;
+  x[[.]]^;
+}
+  )cpp");
+  auto Results =
+  completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
+  EXPECT_EQ(Results.Completions.size(), 3u);
+
+  TextEdit ReplacementEdit;
+  ReplacementEdit.range = TestCode.range();
+  ReplacementEdit.newText = "->";
+  for (const auto  : Results.Completions) {
+EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
+if (!C.FixIts.empty()) {
+  EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
+}
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: unittests/clangd/QualityTests.cpp
===
--- unittests/clangd/QualityTests.cpp
+++ unittests/clangd/QualityTests.cpp
@@ -346,6 +346,28 @@
   EXPECT_EQ(Q.Category, SymbolQualitySignals::Constructor);
 }
 
+TEST(QualityTests, ItemWithFixItsRankedDown) {
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto Header = TestTU::withHeaderCode(R"cpp(
+int x;
+  )cpp");
+  auto AST = Header.build();
+
+  SymbolRelevanceSignals RelevanceWithFixIt;
+  RelevanceWithFixIt.merge(CodeCompletionResult((AST, "x"), 0, nullptr,
+false, true, {FixItHint{}}));
+  EXPECT_TRUE(RelevanceWithFixIt.NeedsFixIts);
+
+  SymbolRelevanceSignals RelevanceWithoutFixIt;
+  RelevanceWithoutFixIt.merge(
+ 

[PATCH] D50193: Added functionality to suggest FixIts for conversion of '->' to '.' and vice versa.

2018-08-08 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 159648.
kadircet marked 3 inline comments as done.
kadircet added a comment.

- Resolve some more discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50193

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/Diagnostics.cpp
  clangd/Protocol.h
  clangd/Quality.cpp
  clangd/Quality.h
  clangd/SourceCode.cpp
  clangd/SourceCode.h
  unittests/clangd/CodeCompleteTests.cpp
  unittests/clangd/QualityTests.cpp

Index: unittests/clangd/QualityTests.cpp
===
--- unittests/clangd/QualityTests.cpp
+++ unittests/clangd/QualityTests.cpp
@@ -346,6 +346,28 @@
   EXPECT_EQ(Q.Category, SymbolQualitySignals::Constructor);
 }
 
+TEST(QualityTests, ItemWithFixItsRankedDown) {
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto Header = TestTU::withHeaderCode(R"cpp(
+int x;
+  )cpp");
+  auto AST = Header.build();
+
+  SymbolRelevanceSignals RelevanceWithFixIt;
+  RelevanceWithFixIt.merge(CodeCompletionResult((AST, "x"), 0, nullptr,
+false, true, {FixItHint{}}));
+  EXPECT_TRUE(RelevanceWithFixIt.NeedsFixIts);
+
+  SymbolRelevanceSignals RelevanceWithoutFixIt;
+  RelevanceWithoutFixIt.merge(
+  CodeCompletionResult((AST, "x"), 0, nullptr, false, true, {}));
+  EXPECT_FALSE(RelevanceWithoutFixIt.NeedsFixIts);
+
+  EXPECT_LT(RelevanceWithFixIt.evaluate(), RelevanceWithoutFixIt.evaluate());
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -79,6 +79,23 @@
   return MemIndex::build(std::move(Slab).build());
 }
 
+CodeCompleteResult completions(ClangdServer , StringRef TestCode,
+   Position point,
+   std::vector IndexSymbols = {},
+   clangd::CodeCompleteOptions Opts = {}) {
+  std::unique_ptr OverrideIndex;
+  if (!IndexSymbols.empty()) {
+assert(!Opts.Index && "both Index and IndexSymbols given!");
+OverrideIndex = memIndex(std::move(IndexSymbols));
+Opts.Index = OverrideIndex.get();
+  }
+
+  auto File = testPath("foo.cpp");
+  runAddDocument(Server, File, TestCode);
+  auto CompletionList = cantFail(runCodeComplete(Server, File, point, Opts));
+  return CompletionList;
+}
+
 CodeCompleteResult completions(ClangdServer , StringRef Text,
std::vector IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {}) {
@@ -1338,6 +1355,85 @@
   EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
 }
 
+TEST(CompletionTest, FixItForArrowToDot) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  Annotations TestCode(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const;
+  Auxilary* Aux;
+};
+void f() {
+  ClassWithPtr x;
+  x[[->]]^;
+}
+  )cpp");
+  auto Results =
+  completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
+  EXPECT_EQ(Results.Completions.size(), 3u);
+
+  TextEdit ReplacementEdit;
+  ReplacementEdit.range = TestCode.range();
+  ReplacementEdit.newText = ".";
+  for (const auto  : Results.Completions) {
+EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
+if (!C.FixIts.empty())
+  EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
+  }
+}
+
+TEST(CompletionTest, FixItForDotToArrow) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  Annotations TestCode(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const;
+  Auxilary* Aux;
+};
+void f() {
+  ClassWithPtr x;
+  x[[.]]^;
+}
+  )cpp");
+  auto Results =
+  completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
+  EXPECT_EQ(Results.Completions.size(), 3u);
+
+  TextEdit ReplacementEdit;
+  ReplacementEdit.range = TestCode.range();
+  ReplacementEdit.newText = "->";
+  for (const auto  : Results.Completions) {
+EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");
+if (!C.FixIts.empty()) {
+  

[PATCH] D50727: [clangd] Fetch documentation from the Index during signature help

2018-08-16 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet accepted this revision.
kadircet added a comment.
This revision is now accepted and ready to land.

LGTM


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50727



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


[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-16 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 160986.
kadircet added a comment.

- Made TaskHandle move-only. Since it is costly and most likely unnecessary to 
copy it other than to move it into Context.
- Provided an explicit clone method for copying.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,68 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  {
+TaskHandle TH = TaskHandle::create();
+WithContext ContextWithCancellation(
+setCurrentCancellationToken(TH.clone()));
+EXPECT_FALSE(isCancelled());
+TH.cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_FALSE(isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+auto CancellableTaskHandle = TaskHandle::create();
+ContextWithCancellation.emplace(
+setCurrentCancellationToken(CancellableTaskHandle.clone()));
+EXPECT_FALSE(isCancelled());
+CancellableTaskHandle.cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+  ContextWithCancellation.reset();
+  EXPECT_FALSE(isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleContextDiesHandleLives) {
+  {
+auto CancellableTaskHandle = TaskHandle::create();
+{
+  WithContext ContextWithCancellation(
+  setCurrentCancellationToken(CancellableTaskHandle.clone()));
+  EXPECT_FALSE(isCancelled());
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(isCancelled());
+}
+  }
+  EXPECT_FALSE(isCancelled());
+}
+
+TEST(CancellationTest, CancellationToken) {
+  auto CancellableTaskHandle = TaskHandle::create();
+  WithContext ContextWithCancellation(
+  setCurrentCancellationToken(CancellableTaskHandle.clone()));
+  auto CT = isCancelled();
+  EXPECT_FALSE(CT);
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(CT);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -867,6 +867,13 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Protocol.cpp
===
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -615,5 +615,30 @@
  O.map("compilationDatabaseChanges", CCPC.compilationDatabaseChanges);
 }
 
+json::Value toJSON(const CancelParams ) {
+  return json::Object{{"id", CP.ID}};
+}
+
+llvm::raw_ostream <<(llvm::raw_ostream , const CancelParams ) {
+  O << toJSON(CP);
+  return O;
+}
+
+bool fromJSON(const json::Value , CancelParams ) {
+  

[PATCH] D50835: [clangd] Add parantheses while auto-completing functions.

2018-08-16 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added reviewers: ioeric, ilya-biryukov, hokein.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay.

Currently we only add parantheses to the functions if snippets are
enabled, which also inserts snippets for parameters into parantheses. Adding a
new option to put only parantheses. Also it moves the cursor within parantheses
or at the end of them by looking at whether completion item has any parameters
or not. Still requires snippets support on the client side.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50835

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  unittests/clangd/CodeCompleteTests.cpp


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1590,6 +1590,44 @@
   ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
 }
 
+TEST(CompletionTest, RenderWithCursorRelocation) {
+  CodeCompleteOptions Opts;
+  Opts.EnableCursorRelocation = true;
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x()");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "(${0:bool})";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -81,6 +81,12 @@
   /// Include completions that require small corrections, e.g. change '.' to
   /// '->' on member access etc.
   bool IncludeFixIts = false;
+
+  /// Enables cursor to be moved around according to completions needs even 
when
+  /// snippets are disabled. For example selecting a function with parameters 
as
+  /// completion item moves the cursor within the parameters, whereas without
+  /// parameters moves to after closing parantheses.
+  bool EnableCursorRelocation = false;
 };
 
 // Semi-structured representation of a code-complete suggestion for our C++ 
API.
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -1373,11 +1373,21 @@
   }
   if (Opts.EnableSnippets)
 LSP.textEdit->newText += SnippetSuffix;
+  // Check if we have cursor relocation enabled and completing a function.
+  else if (SnippetSuffix.size() && Opts.EnableCursorRelocation) {
+// Check whether function has any parameters or not.
+if (SnippetSuffix.size() > 2)
+  LSP.textEdit->newText += "(${0})";
+else
+  LSP.textEdit->newText += "()";
+  }
+
   // FIXME(kadircet): Do not even fill insertText after making sure textEdit is
   // compatible with most of the editors.
   LSP.insertText = LSP.textEdit->newText;
-  LSP.insertTextFormat = Opts.EnableSnippets ? InsertTextFormat::Snippet
- : InsertTextFormat::PlainText;
+  LSP.insertTextFormat = Opts.EnableSnippets || Opts.EnableCursorRelocation
+ ? InsertTextFormat::Snippet
+ : InsertTextFormat::PlainText;
   if (HeaderInsertion)
 LSP.additionalTextEdits.push_back(*HeaderInsertion);
   return LSP;


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1590,6 +1590,44 @@
   ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
 }
 
+TEST(CompletionTest, RenderWithCursorRelocation) {
+  CodeCompleteOptions Opts;
+  Opts.EnableCursorRelocation = true;
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x()");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "(${0:bool})";
+
+auto R = 

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-14 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 160636.
kadircet marked 4 inline comments as done.
kadircet added a comment.

- Get rid of getCancellationError.
- Add replyError helper.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,70 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  {
+TaskHandle TH = TaskHandle::createCancellableTaskHandle();
+WithContext ContextWithCancellation(
+CancellationHandler::setCurrentCancellationToken(TH));
+EXPECT_FALSE(CancellationHandler::isCancelled());
+TH.cancel();
+EXPECT_TRUE(CancellationHandler::isCancelled());
+  }
+  EXPECT_FALSE(CancellationHandler::isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+auto CancellableTaskHandle = TaskHandle::createCancellableTaskHandle();
+ContextWithCancellation.emplace(
+CancellationHandler::setCurrentCancellationToken(
+CancellableTaskHandle));
+EXPECT_FALSE(CancellationHandler::isCancelled());
+CancellableTaskHandle.cancel();
+EXPECT_TRUE(CancellationHandler::isCancelled());
+  }
+  EXPECT_TRUE(CancellationHandler::isCancelled());
+  ContextWithCancellation.reset();
+  EXPECT_FALSE(CancellationHandler::isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleContextDiesHandleLives) {
+  {
+auto CancellableTaskHandle = TaskHandle::createCancellableTaskHandle();
+{
+  WithContext ContextWithCancellation(
+  CancellationHandler::setCurrentCancellationToken(
+  CancellableTaskHandle));
+  EXPECT_FALSE(CancellationHandler::isCancelled());
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(CancellationHandler::isCancelled());
+}
+  }
+  EXPECT_FALSE(CancellationHandler::isCancelled());
+}
+
+TEST(CancellationTest, CancellationToken) {
+  auto CancellableTaskHandle = TaskHandle::createCancellableTaskHandle();
+  WithContext ContextWithCancellation(
+  CancellationHandler::setCurrentCancellationToken(CancellableTaskHandle));
+  auto CT = CancellationHandler::isCancelled();
+  EXPECT_FALSE(CT);
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(CT);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -861,6 +861,13 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Protocol.cpp
===
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -615,5 +615,30 @@
   

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-14 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/Cancellation.cpp:17
+namespace {
+static Key>> CancellationTokenKey;
+} // namespace

ilya-biryukov wrote:
> Having a `shared_ptr` key in the Context can cause data races (e.g. if we 
> copy it concurrently from multiple threads).
> I suggest we make `CancellationToken` move-only (i.e. disallow copies) and 
> return `const CancellationToken&` when getting it from the context.
As talked offline, copying std::shared_ptr is thread safe.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502



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


[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-14 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 160652.
kadircet marked 8 inline comments as done.
kadircet added a comment.

- Resolve discussions.
- Get rid of CancellationHandler class.
- Change error class name.
- Improve documentation.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,67 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  {
+TaskHandle TH = TaskHandle::create();
+WithContext ContextWithCancellation(setCurrentCancellationToken(TH));
+EXPECT_FALSE(isCancelled());
+TH.cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_FALSE(isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+auto CancellableTaskHandle = TaskHandle::create();
+ContextWithCancellation.emplace(
+setCurrentCancellationToken(CancellableTaskHandle));
+EXPECT_FALSE(isCancelled());
+CancellableTaskHandle.cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+  ContextWithCancellation.reset();
+  EXPECT_FALSE(isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleContextDiesHandleLives) {
+  {
+auto CancellableTaskHandle = TaskHandle::create();
+{
+  WithContext ContextWithCancellation(
+  setCurrentCancellationToken(CancellableTaskHandle));
+  EXPECT_FALSE(isCancelled());
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(isCancelled());
+}
+  }
+  EXPECT_FALSE(isCancelled());
+}
+
+TEST(CancellationTest, CancellationToken) {
+  auto CancellableTaskHandle = TaskHandle::create();
+  WithContext ContextWithCancellation(
+  setCurrentCancellationToken(CancellableTaskHandle));
+  auto CT = isCancelled();
+  EXPECT_FALSE(CT);
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(CT);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -861,6 +861,13 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Protocol.cpp
===
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -615,5 +615,30 @@
  O.map("compilationDatabaseChanges", CCPC.compilationDatabaseChanges);
 }
 
+json::Value toJSON(const CancelParams ) {
+  return json::Object{{"id", CP.ID}};
+}
+
+llvm::raw_ostream <<(llvm::raw_ostream , const CancelParams ) {
+  O << toJSON(CP);
+  return O;
+}
+
+bool fromJSON(const json::Value , CancelParams ) {
+  json::ObjectMapper O(Params);
+  if (!O)
+return false;

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-14 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 160531.
kadircet marked 7 inline comments as done.
kadircet added a comment.

- Polished API.
- Resolved discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,76 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  {
+TaskHandle TH = TaskHandle::createCancellableTaskHandle();
+WithContext ContextWithCancellation(
+CancellationHandler::setCurrentCancellationToken(TH));
+EXPECT_FALSE(CancellationHandler::isCancelled());
+TH.cancel();
+EXPECT_TRUE(CancellationHandler::isCancelled());
+  }
+  EXPECT_FALSE(CancellationHandler::isCancelled());
+}
+
+TEST(CancellationTest, CheckForError) {
+  llvm::Error e = handleErrors(CancellationHandler::getCancellationError(),
+   [](const TaskCancelledError &) {});
+  EXPECT_FALSE(e);
+}
+
+TEST(CancellationTest, TaskHandleTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+auto CancellableTaskHandle = TaskHandle::createCancellableTaskHandle();
+ContextWithCancellation.emplace(
+CancellationHandler::setCurrentCancellationToken(
+CancellableTaskHandle));
+EXPECT_FALSE(CancellationHandler::isCancelled());
+CancellableTaskHandle.cancel();
+EXPECT_TRUE(CancellationHandler::isCancelled());
+  }
+  EXPECT_TRUE(CancellationHandler::isCancelled());
+  ContextWithCancellation.reset();
+  EXPECT_FALSE(CancellationHandler::isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleContextDiesHandleLives) {
+  {
+auto CancellableTaskHandle = TaskHandle::createCancellableTaskHandle();
+{
+  WithContext ContextWithCancellation(
+  CancellationHandler::setCurrentCancellationToken(
+  CancellableTaskHandle));
+  EXPECT_FALSE(CancellationHandler::isCancelled());
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(CancellationHandler::isCancelled());
+}
+  }
+  EXPECT_FALSE(CancellationHandler::isCancelled());
+}
+
+TEST(CancellationTest, CancellationToken) {
+  auto CancellableTaskHandle = TaskHandle::createCancellableTaskHandle();
+  WithContext ContextWithCancellation(
+  CancellationHandler::setCurrentCancellationToken(CancellableTaskHandle));
+  auto CT = CancellationHandler::isCancelled();
+  EXPECT_FALSE(CT);
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(CT);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -861,6 +861,13 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
 } // namespace clangd
 } 

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-14 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/Cancellation.h:71
+
+class TaskHandle {
+public:

ilya-biryukov wrote:
> I wonder if we should make `TaskHandle` move-only?
> 
> The reasoning is that is can be easily used from multiple threads (since it's 
> used by code dealing with async tasks anyway) and copying it concurrently is 
> a data race.
> On the other hand, calling `cancel()` is perfectly thread-safe and shouldn't 
> cause any problems.
As similar to above mentioned case copying doesn't introduce any data races.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502



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


[PATCH] D50835: [clangd] Add parantheses while auto-completing functions.

2018-08-16 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/CodeComplete.h:85
+
+  /// Enables cursor to be moved around according to completions needs even 
when
+  /// snippets are disabled. For example selecting a function with parameters 
as

ioeric wrote:
> IIRC, the goal of this patch is to allow disabling snippet templates for 
> function parameters while still allow appending `()` or `($0)` to function 
> candidates. If that's still the case, I think what we want is probably an 
> option like `DisableSnippetTemplateForFunctionArgs`? 
Yeah, that makes totally more sense. Thanks!


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50835



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


[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-16 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161018.
kadircet marked 21 inline comments as done.
kadircet added a comment.

- Resolve discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,79 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "Threading.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  TaskHandle TH = TaskHandle::create();
+  WithContext ContextWithCancellation(
+  setCurrentCancellationToken(TH.createCancellationToken()));
+  EXPECT_FALSE(isCancelled());
+  TH.cancel();
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+auto CancellableTaskHandle = TaskHandle::create();
+ContextWithCancellation.emplace(setCurrentCancellationToken(
+CancellableTaskHandle.createCancellationToken()));
+EXPECT_FALSE(isCancelled());
+CancellableTaskHandle.cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleContextDiesHandleLives) {
+  auto CancellableTaskHandle = TaskHandle::create();
+  {
+WithContext ContextWithCancellation(setCurrentCancellationToken(
+CancellableTaskHandle.createCancellationToken()));
+EXPECT_FALSE(isCancelled());
+CancellableTaskHandle.cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  // Still should be able to cancel without any problems.
+  CancellableTaskHandle.cancel();
+}
+
+TEST(CancellationTest, CancellationToken) {
+  auto CancellableTaskHandle = TaskHandle::create();
+  WithContext ContextWithCancellation(setCurrentCancellationToken(
+  CancellableTaskHandle.createCancellationToken()));
+  const auto  = getCurrentCancellationToken();
+  EXPECT_FALSE(CT);
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(CT);
+}
+
+TEST(CancellationTest, AsynCancellationTest) {
+  std::atomic HasCancelled(false);
+  Notification Cancelled;
+  auto TaskToBeCancelled = [&](CancellationToken CT) {
+WithContext ContextGuard(setCurrentCancellationToken(std::move(CT)));
+Cancelled.wait();
+HasCancelled = isCancelled();
+  };
+  TaskHandle TH = TaskHandle::create();
+  std::thread AsyncTask(TaskToBeCancelled, TH.createCancellationToken());
+  TH.cancel();
+  Cancelled.notify();
+  AsyncTask.join();
+
+  EXPECT_TRUE(HasCancelled);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -867,6 +867,13 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Protocol.cpp

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-16 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/Cancellation.h:92
+  operator bool() const { return isCancelled(); }
+  friend CancellationToken isCancelled();
+

ilya-biryukov wrote:
> It's a bit confusing that this name clashes with a member function.
> We seem to optimize for making this work anywhere:
> ```
>   if (isCancelled())  // <-- get token from ctx, then use implicit conversion 
> to check if it was cancelled
> return llvm::makeError();
> ```
> 
> Which is probably a nice pattern. But we could have two functions that do the 
> same thing with less magic (i.e. implicit conversions) involved at the call 
> sites:
> ```
> CancellationToken getCurrentCancellation();
> void setCurrentCancellation(CancellationToken CT);
> 
> inline bool isCancelled() { return getCurrentCancellation().isCancelled(); }
> ```
> Would allow to get rid of implicit conversion and friend function with the 
> same signature as member. Would also make cases where we actually want to 
> stash the token somewhere cleaner, e.g. instead of `CancellationToken CT = 
> isCancelled()`, we'll have `CancellationToken CT = getCurrentCancellation()`.
> WDYT?
Totally agreed, actually, didn't even notice they had the same signature :D, 
thanks!
 But I still think implicit conversion of CancellationToken to bool seems like 
a good thing to have.



Comment at: clangd/ClangdLSPServer.h:179
+  // associated with only their thread.
+  void CleanupTaskHandle();
+  void StoreTaskHandle(TaskHandle TH);

ilya-biryukov wrote:
> These two methods look like a nice suit for better wrapped in a RAII-object. 
> It would add the value to the associated map on construction and remove on 
> destruction.
> One problem is that all operations calls would become weird, because we'll 
> have to move this RAII object around and moving into lambdas is not fun 
> without C++14 (which allows `[x=std::move(y)]() {}`..
> 
> Maybe add a comment that calls to this function should always be paired and a 
> FIXME that we should have an API that enforces this?
> 
Yeah that would be really nice to have them in a RAII object, but the thing is 
cleanup can occur only after the task dies. Which we don't directly know since 
threads are being detached. So the only way to trigger destruction is at the 
callback, which is where I call cleanup currently. Maybe we can store the 
object within context to trigger destructor at the end of the thread, but still 
don't think it would look any better or ease the job of the caller.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502



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


[PATCH] D50835: [clangd] Add parantheses while auto-completing functions.

2018-08-16 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161023.
kadircet marked an inline comment as done.
kadircet added a comment.

- Change option name.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50835

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  unittests/clangd/CodeCompleteTests.cpp


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1590,6 +1590,55 @@
   ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
 }
 
+TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) {
+  CodeCompleteOptions Opts;
+  Opts.DisableSnippetTemplateForFunctionArgs = true;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  }
+
+  Opts.EnableSnippets = true;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x()");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "(${0:bool})";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -82,6 +82,10 @@
   /// Include completions that require small corrections, e.g. change '.' to
   /// '->' on member access etc.
   bool IncludeFixIts = false;
+
+  /// Disables snippet generation for function arguments. Does nothing if
+  /// snippets are not enabled.
+  bool DisableSnippetTemplateForFunctionArgs = false;
 };
 
 // Semi-structured representation of a code-complete suggestion for our C++ 
API.
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -1371,8 +1371,14 @@
   LSP.additionalTextEdits.push_back(FixIt);
 }
   }
-  if (Opts.EnableSnippets)
-LSP.textEdit->newText += SnippetSuffix;
+  if (Opts.EnableSnippets && !SnippetSuffix.empty()) {
+if (Opts.DisableSnippetTemplateForFunctionArgs)
+  // Check whether function has any parameters or not.
+  LSP.textEdit->newText += SnippetSuffix.size() > 2 ? "(${0})" : "()";
+else
+  LSP.textEdit->newText += SnippetSuffix;
+  }
+
   // FIXME(kadircet): Do not even fill insertText after making sure textEdit is
   // compatible with most of the editors.
   LSP.insertText = LSP.textEdit->newText;


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1590,6 +1590,55 @@
   ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
 }
 
+TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) {
+  CodeCompleteOptions Opts;
+  Opts.DisableSnippetTemplateForFunctionArgs = true;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  }
+
+  Opts.EnableSnippets = true;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x()");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "(${0:bool})";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ 

[PATCH] D50193: Added functionality to suggest FixIts for conversion of '->' to '.' and vice versa.

2018-08-06 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 159261.
kadircet marked 4 inline comments as done.
kadircet added a comment.

Added functionality to suggest FixIts for conversion of '->' to '.' and vice 
versa.

- Fixes for comments.
- Take unnecessary patches back
- Second pass for comments.
- Add downranking for scores of fixit elements.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50193

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/Diagnostics.cpp
  clangd/Protocol.h
  clangd/Quality.cpp
  clangd/Quality.h
  clangd/SourceCode.cpp
  clangd/SourceCode.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -79,7 +79,8 @@
   return MemIndex::build(std::move(Slab).build());
 }
 
-CodeCompleteResult completions(ClangdServer , StringRef Text,
+CodeCompleteResult completions(ClangdServer , StringRef TestCode,
+   Position point,
std::vector IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {}) {
   std::unique_ptr OverrideIndex;
@@ -90,23 +91,50 @@
   }
 
   auto File = testPath("foo.cpp");
-  Annotations Test(Text);
-  runAddDocument(Server, File, Test.code());
-  auto CompletionList =
-  cantFail(runCodeComplete(Server, File, Test.point(), Opts));
+  runAddDocument(Server, File, TestCode);
+  auto CompletionList = cantFail(runCodeComplete(Server, File, point, Opts));
   return CompletionList;
 }
 
 // Builds a server and runs code completion.
 // If IndexSymbols is non-empty, an index will be built and passed to opts.
-CodeCompleteResult completions(StringRef Text,
+CodeCompleteResult completions(StringRef Text, Position point,
std::vector IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {}) {
   MockFSProvider FS;
   MockCompilationDatabase CDB;
   IgnoreDiagnostics DiagConsumer;
   ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
-  return completions(Server, Text, std::move(IndexSymbols), std::move(Opts));
+  return completions(Server, Text, point, std::move(IndexSymbols),
+ std::move(Opts));
+}
+
+CodeCompleteResult completions(ClangdServer , Annotations Test,
+   std::vector IndexSymbols = {},
+   clangd::CodeCompleteOptions Opts = {}) {
+  return completions(Server, Test.code(), Test.point(), std::move(IndexSymbols),
+ std::move(Opts));
+}
+
+CodeCompleteResult completions(ClangdServer , StringRef Text,
+   std::vector IndexSymbols = {},
+   clangd::CodeCompleteOptions Opts = {}) {
+  return completions(Server, Annotations(Text), std::move(IndexSymbols),
+ std::move(Opts));
+}
+
+CodeCompleteResult completions(Annotations Test,
+   std::vector IndexSymbols = {},
+   clangd::CodeCompleteOptions Opts = {}) {
+  return completions(Test.code(), Test.point(), std::move(IndexSymbols),
+ std::move(Opts));
+}
+
+CodeCompleteResult completions(StringRef Text,
+   std::vector IndexSymbols = {},
+   clangd::CodeCompleteOptions Opts = {}) {
+  return completions(Annotations(Text), std::move(IndexSymbols),
+ std::move(Opts));
 }
 
 std::string replace(StringRef Haystack, StringRef Needle, StringRef Repl) {
@@ -1338,6 +1366,99 @@
   EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
 }
 
+TEST(CompletionTest, FixItForArrowToDot) {
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  Annotations TestCode(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const;
+  Auxilary* Aux;
+};
+void f() {
+  ClassWithPtr x;
+  x[[->]]^;
+}
+  )cpp");
+  auto Results = completions(TestCode, {}, Opts);
+  EXPECT_EQ(Results.Completions.size(), 3u);
+
+  TextEdit ReplacementEdit;
+  ReplacementEdit.range = TestCode.range();
+  ReplacementEdit.newText = ".";
+  for (const auto  : Results.Completions) {
+EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
+if (!C.FixIts.empty()) {
+  EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
+}
+  }
+}
+
+TEST(CompletionTest, FixItForDotToArrow) {
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  Annotations TestCode(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  

[PATCH] D50193: Added functionality to suggest FixIts for conversion of '->' to '.' and vice versa.

2018-08-07 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 159510.
kadircet marked 6 inline comments as done.
kadircet added a comment.

- Resolve discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50193

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/Diagnostics.cpp
  clangd/Protocol.h
  clangd/Quality.cpp
  clangd/Quality.h
  clangd/SourceCode.cpp
  clangd/SourceCode.h
  unittests/clangd/CodeCompleteTests.cpp
  unittests/clangd/QualityTests.cpp

Index: unittests/clangd/QualityTests.cpp
===
--- unittests/clangd/QualityTests.cpp
+++ unittests/clangd/QualityTests.cpp
@@ -346,6 +346,28 @@
   EXPECT_EQ(Q.Category, SymbolQualitySignals::Constructor);
 }
 
+TEST(QualityTests, ItemWithFixItsRankedDown) {
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto Header = TestTU::withHeaderCode(R"cpp(
+int x;
+  )cpp");
+  auto AST = Header.build();
+
+  SymbolRelevanceSignals RelevanceWithFixIt;
+  RelevanceWithFixIt.merge(
+  CodeCompletionResult((AST, "x"), 0, nullptr, false, true, {{}}));
+  EXPECT_TRUE(RelevanceWithFixIt.NeedsFixIts);
+
+  SymbolRelevanceSignals RelevanceWithoutFixIt;
+  RelevanceWithoutFixIt.merge(
+  CodeCompletionResult((AST, "x"), 0, nullptr, false, true, {}));
+  EXPECT_FALSE(RelevanceWithoutFixIt.NeedsFixIts);
+
+  EXPECT_LT(RelevanceWithFixIt.evaluate(), RelevanceWithoutFixIt.evaluate());
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -79,6 +79,25 @@
   return MemIndex::build(std::move(Slab).build());
 }
 
+CodeCompleteResult completions(ClangdServer , StringRef TestCode,
+   Position point,
+   std::vector IndexSymbols = {},
+   clangd::CodeCompleteOptions Opts = {}) {
+  std::unique_ptr OverrideIndex;
+  if (!IndexSymbols.empty()) {
+assert(!Opts.Index && "both Index and IndexSymbols given!");
+OverrideIndex = memIndex(std::move(IndexSymbols));
+Opts.Index = OverrideIndex.get();
+  }
+
+  auto File = testPath("foo.cpp");
+  runAddDocument(Server, File, TestCode);
+  auto CompletionList = cantFail(runCodeComplete(Server, File, point, Opts));
+  return CompletionList;
+}
+
+// Builds a server and runs code completion.
+// If IndexSymbols is non-empty, an index will be built and passed to opts.
 CodeCompleteResult completions(ClangdServer , StringRef Text,
std::vector IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {}) {
@@ -97,8 +116,6 @@
   return CompletionList;
 }
 
-// Builds a server and runs code completion.
-// If IndexSymbols is non-empty, an index will be built and passed to opts.
 CodeCompleteResult completions(StringRef Text,
std::vector IndexSymbols = {},
clangd::CodeCompleteOptions Opts = {}) {
@@ -1338,6 +1355,85 @@
   EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);
 }
 
+TEST(CompletionTest, FixItForArrowToDot) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  Annotations TestCode(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const;
+  Auxilary* Aux;
+};
+void f() {
+  ClassWithPtr x;
+  x[[->]]^;
+}
+  )cpp");
+  auto Results =
+  completions(Server, TestCode.code(), TestCode.point(), {}, Opts);
+  EXPECT_EQ(Results.Completions.size(), 3u);
+
+  TextEdit ReplacementEdit;
+  ReplacementEdit.range = TestCode.range();
+  ReplacementEdit.newText = ".";
+  for (const auto  : Results.Completions) {
+EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");
+if (!C.FixIts.empty())
+  EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));
+  }
+}
+
+TEST(CompletionTest, FixItForDotToArrow) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+  Annotations TestCode(
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+class ClassWithPtr {
+ public:
+  void MemberFunction();
+  Auxilary* operator->() const;
+  Auxilary* Aux;
+};
+void f() {
+  ClassWithPtr x;
+  x[[.]]^;
+}
+ 

[PATCH] D50443: [clang] Store code completion token range in preprocessor.

2018-08-13 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 160299.
kadircet added a comment.

- Resolve discussions.
- Fix typo.


Repository:
  rC Clang

https://reviews.llvm.org/D50443

Files:
  include/clang/Lex/Preprocessor.h
  lib/Lex/Preprocessor.cpp


Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -868,6 +868,7 @@
   if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
 // Remember the identifier before code completion token.
 setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+setCodeCompletionTokenRange(Result.getLocation(), Result.getEndLoc());
 // Set IdenfitierInfo to null to avoid confusing code that handles both
 // identifiers and completion tokens.
 Result.setIdentifierInfo(nullptr);
Index: include/clang/Lex/Preprocessor.h
===
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -310,6 +310,9 @@
   /// on the stem that is to be code completed.
   IdentifierInfo *CodeCompletionII = nullptr;
 
+  /// Range for the code completion token.
+  SourceRange CodeCompletionTokenRange;
+
   /// The directory that the main file should be considered to occupy,
   /// if it does not correspond to a real file (as happens when building a
   /// module).
@@ -1131,6 +1134,16 @@
 CodeCompletionII = Filter;
   }
 
+  /// Set the code completion token range for detecting replacement range later
+  /// on.
+  void setCodeCompletionTokenRange(const SourceLocation Start,
+   const SourceLocation End) {
+CodeCompletionTokenRange = {Start, End};
+  }
+  SourceRange getCodeCompletionTokenRange() const {
+return CodeCompletionTokenRange;
+  }
+
   /// Get the code completion token for filtering purposes.
   StringRef getCodeCompletionFilter() {
 if (CodeCompletionII)


Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -868,6 +868,7 @@
   if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
 // Remember the identifier before code completion token.
 setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+setCodeCompletionTokenRange(Result.getLocation(), Result.getEndLoc());
 // Set IdenfitierInfo to null to avoid confusing code that handles both
 // identifiers and completion tokens.
 Result.setIdentifierInfo(nullptr);
Index: include/clang/Lex/Preprocessor.h
===
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -310,6 +310,9 @@
   /// on the stem that is to be code completed.
   IdentifierInfo *CodeCompletionII = nullptr;
 
+  /// Range for the code completion token.
+  SourceRange CodeCompletionTokenRange;
+
   /// The directory that the main file should be considered to occupy,
   /// if it does not correspond to a real file (as happens when building a
   /// module).
@@ -1131,6 +1134,16 @@
 CodeCompletionII = Filter;
   }
 
+  /// Set the code completion token range for detecting replacement range later
+  /// on.
+  void setCodeCompletionTokenRange(const SourceLocation Start,
+   const SourceLocation End) {
+CodeCompletionTokenRange = {Start, End};
+  }
+  SourceRange getCodeCompletionTokenRange() const {
+return CodeCompletionTokenRange;
+  }
+
   /// Get the code completion token for filtering purposes.
   StringRef getCodeCompletionFilter() {
 if (CodeCompletionII)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50443: [clang] Store code completion token range in preprocessor.

2018-08-13 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL339540: [clang] Store code completion token range in 
preprocessor. (authored by kadircet, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D50443

Files:
  cfe/trunk/include/clang/Lex/Preprocessor.h
  cfe/trunk/lib/Lex/Preprocessor.cpp


Index: cfe/trunk/lib/Lex/Preprocessor.cpp
===
--- cfe/trunk/lib/Lex/Preprocessor.cpp
+++ cfe/trunk/lib/Lex/Preprocessor.cpp
@@ -868,6 +868,7 @@
   if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
 // Remember the identifier before code completion token.
 setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+setCodeCompletionTokenRange(Result.getLocation(), Result.getEndLoc());
 // Set IdenfitierInfo to null to avoid confusing code that handles both
 // identifiers and completion tokens.
 Result.setIdentifierInfo(nullptr);
Index: cfe/trunk/include/clang/Lex/Preprocessor.h
===
--- cfe/trunk/include/clang/Lex/Preprocessor.h
+++ cfe/trunk/include/clang/Lex/Preprocessor.h
@@ -310,6 +310,9 @@
   /// on the stem that is to be code completed.
   IdentifierInfo *CodeCompletionII = nullptr;
 
+  /// Range for the code completion token.
+  SourceRange CodeCompletionTokenRange;
+
   /// The directory that the main file should be considered to occupy,
   /// if it does not correspond to a real file (as happens when building a
   /// module).
@@ -1131,6 +1134,16 @@
 CodeCompletionII = Filter;
   }
 
+  /// Set the code completion token range for detecting replacement range later
+  /// on.
+  void setCodeCompletionTokenRange(const SourceLocation Start,
+   const SourceLocation End) {
+CodeCompletionTokenRange = {Start, End};
+  }
+  SourceRange getCodeCompletionTokenRange() const {
+return CodeCompletionTokenRange;
+  }
+
   /// Get the code completion token for filtering purposes.
   StringRef getCodeCompletionFilter() {
 if (CodeCompletionII)


Index: cfe/trunk/lib/Lex/Preprocessor.cpp
===
--- cfe/trunk/lib/Lex/Preprocessor.cpp
+++ cfe/trunk/lib/Lex/Preprocessor.cpp
@@ -868,6 +868,7 @@
   if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
 // Remember the identifier before code completion token.
 setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+setCodeCompletionTokenRange(Result.getLocation(), Result.getEndLoc());
 // Set IdenfitierInfo to null to avoid confusing code that handles both
 // identifiers and completion tokens.
 Result.setIdentifierInfo(nullptr);
Index: cfe/trunk/include/clang/Lex/Preprocessor.h
===
--- cfe/trunk/include/clang/Lex/Preprocessor.h
+++ cfe/trunk/include/clang/Lex/Preprocessor.h
@@ -310,6 +310,9 @@
   /// on the stem that is to be code completed.
   IdentifierInfo *CodeCompletionII = nullptr;
 
+  /// Range for the code completion token.
+  SourceRange CodeCompletionTokenRange;
+
   /// The directory that the main file should be considered to occupy,
   /// if it does not correspond to a real file (as happens when building a
   /// module).
@@ -1131,6 +1134,16 @@
 CodeCompletionII = Filter;
   }
 
+  /// Set the code completion token range for detecting replacement range later
+  /// on.
+  void setCodeCompletionTokenRange(const SourceLocation Start,
+   const SourceLocation End) {
+CodeCompletionTokenRange = {Start, End};
+  }
+  SourceRange getCodeCompletionTokenRange() const {
+return CodeCompletionTokenRange;
+  }
+
   /// Get the code completion token for filtering purposes.
   StringRef getCodeCompletionFilter() {
 if (CodeCompletionII)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50555: [clangd] Introduce scoring mechanism for SignatureInformations.

2018-08-13 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 160306.
kadircet marked 2 inline comments as done.
kadircet added a comment.

- Rebase & Resolve discussions.
- Resolve discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50555

Files:
  clangd/CodeComplete.cpp
  clangd/Quality.cpp
  clangd/Quality.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1515,6 +1515,28 @@
   }
 }
 
+TEST(SignatureHelpTest, OverloadsOrdering) {
+  const auto Results = signatures(R"cpp(
+void foo(int x);
+void foo(int x, float y);
+void foo(float x, int y);
+void foo(float x, float y);
+void foo(int x, int y = 0);
+int main() { foo(^); }
+  )cpp");
+  EXPECT_THAT(
+  Results.signatures,
+  ElementsAre(
+  Sig("foo(int x) -> void", {"int x"}),
+  Sig("foo(int x, int y = 0) -> void", {"int x", "int y = 0"}),
+  Sig("foo(float x, int y) -> void", {"float x", "int y"}),
+  Sig("foo(int x, float y) -> void", {"int x", "float y"}),
+  Sig("foo(float x, float y) -> void", {"float x", "float y"})));
+  // We always prefer the first signature.
+  EXPECT_EQ(0, Results.activeSignature);
+  EXPECT_EQ(0, Results.activeParameter);
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/Quality.h
===
--- clangd/Quality.h
+++ clangd/Quality.h
@@ -163,6 +163,16 @@
 /// LSP. (The highest score compares smallest so it sorts at the top).
 std::string sortText(float Score, llvm::StringRef Tiebreak = "");
 
+struct SignatureQualitySignals {
+  uint32_t NumberOfParameters = 0;
+  uint32_t NumberOfOptionalParameters = 0;
+  bool ContainsActiveParameter = false;
+  CodeCompleteConsumer::OverloadCandidate::CandidateKind Kind =
+  CodeCompleteConsumer::OverloadCandidate::CandidateKind::CK_Function;
+};
+llvm::raw_ostream <<(llvm::raw_ostream &,
+  const SignatureQualitySignals &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Quality.cpp
===
--- clangd/Quality.cpp
+++ clangd/Quality.cpp
@@ -401,5 +401,17 @@
   return S;
 }
 
+llvm::raw_ostream <<(llvm::raw_ostream ,
+  const SignatureQualitySignals ) {
+  OS << formatv("=== Signature Quality:\n");
+  OS << formatv("\tNumber of parameters: {0}\n", S.NumberOfParameters);
+  OS << formatv("\tNumber of optional parameters: {0}\n",
+S.NumberOfOptionalParameters);
+  OS << formatv("\tContains active parameter: {0}\n",
+S.ContainsActiveParameter);
+  OS << formatv("\tKind: {0}\n", S.Kind);
+  return OS;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -129,16 +129,16 @@
 /// Get the optional chunk as a string. This function is possibly recursive.
 ///
 /// The parameter info for each parameter is appended to the Parameters.
-std::string
-getOptionalParameters(const CodeCompletionString ,
-  std::vector ) {
+std::string getOptionalParameters(const CodeCompletionString ,
+  std::vector ,
+  SignatureQualitySignals ) {
   std::string Result;
   for (const auto  : CCS) {
 switch (Chunk.Kind) {
 case CodeCompletionString::CK_Optional:
   assert(Chunk.Optional &&
  "Expected the optional code completion string to be non-null.");
-  Result += getOptionalParameters(*Chunk.Optional, Parameters);
+  Result += getOptionalParameters(*Chunk.Optional, Parameters, Signal);
   break;
 case CodeCompletionString::CK_VerticalSpace:
   break;
@@ -154,6 +154,8 @@
   ParameterInformation Info;
   Info.label = Chunk.Text;
   Parameters.push_back(std::move(Info));
+  Signal.ContainsActiveParameter = true;
+  Signal.NumberOfOptionalParameters++;
   break;
 }
 default:
@@ -685,6 +687,9 @@
   llvm::unique_function ResultsCallback;
 };
 
+using ScoredSignature =
+std::pair;
+
 class SignatureHelpCollector final : public CodeCompleteConsumer {
 
 public:
@@ -698,7 +703,9 @@
   void ProcessOverloadCandidates(Sema , unsigned CurrentArg,
  OverloadCandidate *Candidates,
  unsigned NumCandidates) override {
+std::vector ScoredSignatures;
 SigHelp.signatures.reserve(NumCandidates);
+ScoredSignatures.reserve(NumCandidates);
 // FIXME(rwols): How can we determine the "active overload candidate"?
 // Right now the overloaded candidates seem to be provided in a "best fit"
 // order, so I'm not too worried about 

[PATCH] D50449: [clangd] Support textEdit in addition to insertText.

2018-08-13 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL339543: [clangd] Support textEdit in addition to insertText. 
(authored by kadircet, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D50449

Files:
  clang-tools-extra/trunk/clangd/CodeComplete.cpp
  clang-tools-extra/trunk/clangd/CodeComplete.h
  clang-tools-extra/trunk/clangd/SourceCode.cpp
  clang-tools-extra/trunk/clangd/SourceCode.h
  clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
  clang-tools-extra/trunk/unittests/clangd/SourceCodeTests.cpp

Index: clang-tools-extra/trunk/unittests/clangd/SourceCodeTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/SourceCodeTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/SourceCodeTests.cpp
@@ -37,6 +37,13 @@
   return Pos;
 }
 
+Range range(const std::pair p1, const std::pair p2) {
+  Range range;
+  range.start = position(p1.first, p1.second);
+  range.end = position(p2.first, p2.second);
+  return range;
+}
+
 TEST(SourceCodeTests, PositionToOffset) {
   // line out of bounds
   EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), Failed());
@@ -119,6 +126,14 @@
   EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 9)) << "out of bounds";
 }
 
+TEST(SourceCodeTests, IsRangeConsecutive) {
+  EXPECT_TRUE(IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 3}, {2, 4})));
+  EXPECT_FALSE(
+  IsRangeConsecutive(range({0, 2}, {0, 3}), range({2, 3}, {2, 4})));
+  EXPECT_FALSE(
+  IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 4}, {2, 5})));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
@@ -1439,6 +1439,82 @@
   }
 }
 
+TEST(CompletionTest, RenderWithFixItMerged) {
+  TextEdit FixIt;
+  FixIt.range.end.character = 5;
+  FixIt.newText = "->";
+
+  CodeCompletion C;
+  C.Name = "x";
+  C.RequiredQualifier = "Foo::";
+  C.FixIts = {FixIt};
+  C.CompletionTokenRange.start.character = 5;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto R = C.render(Opts);
+  EXPECT_TRUE(R.textEdit);
+  EXPECT_EQ(R.textEdit->newText, "->Foo::x");
+  EXPECT_TRUE(R.additionalTextEdits.empty());
+}
+
+TEST(CompletionTest, RenderWithFixItNonMerged) {
+  TextEdit FixIt;
+  FixIt.range.end.character = 4;
+  FixIt.newText = "->";
+
+  CodeCompletion C;
+  C.Name = "x";
+  C.RequiredQualifier = "Foo::";
+  C.FixIts = {FixIt};
+  C.CompletionTokenRange.start.character = 5;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto R = C.render(Opts);
+  EXPECT_TRUE(R.textEdit);
+  EXPECT_EQ(R.textEdit->newText, "Foo::x");
+  EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
+}
+
+TEST(CompletionTest, CompletionTokenRange) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  constexpr const char *TestCodes[] = {
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+void f() {
+  Auxilary x;
+  x.[[Aux]]^;
+}
+  )cpp",
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+void f() {
+  Auxilary x;
+  x.[[]]^;
+}
+  )cpp"};
+  for (const auto  : TestCodes) {
+Annotations TestCode(Text);
+auto Results = completions(Server, TestCode.code(), TestCode.point());
+
+EXPECT_EQ(Results.Completions.size(), 1u);
+EXPECT_THAT(Results.Completions.front().CompletionTokenRange, TestCode.range());
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/trunk/clangd/CodeComplete.h
===
--- clang-tools-extra/trunk/clangd/CodeComplete.h
+++ clang-tools-extra/trunk/clangd/CodeComplete.h
@@ -123,6 +123,9 @@
   /// converting '->' to '.' on member access.
   std::vector FixIts;
 
+  /// Holds the range of the token we are going to replace with this completion.
+  Range CompletionTokenRange;
+
   // Scores are used to rank completion items.
   struct Scores {
 // The score that items are ranked by.
Index: clang-tools-extra/trunk/clangd/SourceCode.cpp
===
--- clang-tools-extra/trunk/clangd/SourceCode.cpp
+++ clang-tools-extra/trunk/clangd/SourceCode.cpp
@@ -224,5 +224,10 @@
   return Result;
 }
 
+bool IsRangeConsecutive(const Range , const Range ) {
+  return Left.end.line == Right.start.line &&
+ Left.end.character == Right.start.character;
+}
+
 } // 

[PATCH] D50555: [clangd] Introduce scoring mechanism for SignatureInformations.

2018-08-13 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCTE339547: [clangd] Introduce scoring mechanism for 
SignatureInformations. (authored by kadircet, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D50555?vs=160306=160307#toc

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50555

Files:
  clangd/CodeComplete.cpp
  clangd/Quality.cpp
  clangd/Quality.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1515,6 +1515,28 @@
   }
 }
 
+TEST(SignatureHelpTest, OverloadsOrdering) {
+  const auto Results = signatures(R"cpp(
+void foo(int x);
+void foo(int x, float y);
+void foo(float x, int y);
+void foo(float x, float y);
+void foo(int x, int y = 0);
+int main() { foo(^); }
+  )cpp");
+  EXPECT_THAT(
+  Results.signatures,
+  ElementsAre(
+  Sig("foo(int x) -> void", {"int x"}),
+  Sig("foo(int x, int y = 0) -> void", {"int x", "int y = 0"}),
+  Sig("foo(float x, int y) -> void", {"float x", "int y"}),
+  Sig("foo(int x, float y) -> void", {"int x", "float y"}),
+  Sig("foo(float x, float y) -> void", {"float x", "float y"})));
+  // We always prefer the first signature.
+  EXPECT_EQ(0, Results.activeSignature);
+  EXPECT_EQ(0, Results.activeParameter);
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -129,16 +129,16 @@
 /// Get the optional chunk as a string. This function is possibly recursive.
 ///
 /// The parameter info for each parameter is appended to the Parameters.
-std::string
-getOptionalParameters(const CodeCompletionString ,
-  std::vector ) {
+std::string getOptionalParameters(const CodeCompletionString ,
+  std::vector ,
+  SignatureQualitySignals ) {
   std::string Result;
   for (const auto  : CCS) {
 switch (Chunk.Kind) {
 case CodeCompletionString::CK_Optional:
   assert(Chunk.Optional &&
  "Expected the optional code completion string to be non-null.");
-  Result += getOptionalParameters(*Chunk.Optional, Parameters);
+  Result += getOptionalParameters(*Chunk.Optional, Parameters, Signal);
   break;
 case CodeCompletionString::CK_VerticalSpace:
   break;
@@ -154,6 +154,8 @@
   ParameterInformation Info;
   Info.label = Chunk.Text;
   Parameters.push_back(std::move(Info));
+  Signal.ContainsActiveParameter = true;
+  Signal.NumberOfOptionalParameters++;
   break;
 }
 default:
@@ -685,6 +687,9 @@
   llvm::unique_function ResultsCallback;
 };
 
+using ScoredSignature =
+std::pair;
+
 class SignatureHelpCollector final : public CodeCompleteConsumer {
 
 public:
@@ -698,7 +703,9 @@
   void ProcessOverloadCandidates(Sema , unsigned CurrentArg,
  OverloadCandidate *Candidates,
  unsigned NumCandidates) override {
+std::vector ScoredSignatures;
 SigHelp.signatures.reserve(NumCandidates);
+ScoredSignatures.reserve(NumCandidates);
 // FIXME(rwols): How can we determine the "active overload candidate"?
 // Right now the overloaded candidates seem to be provided in a "best fit"
 // order, so I'm not too worried about this.
@@ -712,11 +719,45 @@
   CurrentArg, S, *Allocator, CCTUInfo, true);
   assert(CCS && "Expected the CodeCompletionString to be non-null");
   // FIXME: for headers, we need to get a comment from the index.
-  SigHelp.signatures.push_back(processOverloadCandidate(
+  ScoredSignatures.push_back(processOverloadCandidate(
   Candidate, *CCS,
   getParameterDocComment(S.getASTContext(), Candidate, CurrentArg,
  /*CommentsFromHeaders=*/false)));
 }
+std::sort(ScoredSignatures.begin(), ScoredSignatures.end(),
+  [](const ScoredSignature , const ScoredSignature ) {
+// Ordering follows:
+// - Less number of parameters is better.
+// - Function is better than FunctionType which is better than
+// Function Template.
+// - High score is better.
+// - Shorter signature is better.
+// - Alphebatically smaller is better.
+if (L.first.NumberOfParameters != R.first.NumberOfParameters)
+  return L.first.NumberOfParameters <
+ R.first.NumberOfParameters;
+if (L.first.NumberOfOptionalParameters !=
+R.first.NumberOfOptionalParameters)
+  

[PATCH] D50449: [clangd] Support textEdit in addition to insertText.

2018-08-13 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 160303.
kadircet added a comment.

- Rebase.
- Resolve discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50449

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/SourceCode.cpp
  clangd/SourceCode.h
  unittests/clangd/CodeCompleteTests.cpp
  unittests/clangd/SourceCodeTests.cpp

Index: unittests/clangd/SourceCodeTests.cpp
===
--- unittests/clangd/SourceCodeTests.cpp
+++ unittests/clangd/SourceCodeTests.cpp
@@ -37,6 +37,13 @@
   return Pos;
 }
 
+Range range(const std::pair p1, const std::pair p2) {
+  Range range;
+  range.start = position(p1.first, p1.second);
+  range.end = position(p2.first, p2.second);
+  return range;
+}
+
 TEST(SourceCodeTests, PositionToOffset) {
   // line out of bounds
   EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), Failed());
@@ -119,6 +126,14 @@
   EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 9)) << "out of bounds";
 }
 
+TEST(SourceCodeTests, IsRangeConsecutive) {
+  EXPECT_TRUE(IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 3}, {2, 4})));
+  EXPECT_FALSE(
+  IsRangeConsecutive(range({0, 2}, {0, 3}), range({2, 3}, {2, 4})));
+  EXPECT_FALSE(
+  IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 4}, {2, 5})));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1439,6 +1439,82 @@
   }
 }
 
+TEST(CompletionTest, RenderWithFixItMerged) {
+  TextEdit FixIt;
+  FixIt.range.end.character = 5;
+  FixIt.newText = "->";
+
+  CodeCompletion C;
+  C.Name = "x";
+  C.RequiredQualifier = "Foo::";
+  C.FixIts = {FixIt};
+  C.CompletionTokenRange.start.character = 5;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto R = C.render(Opts);
+  EXPECT_TRUE(R.textEdit);
+  EXPECT_EQ(R.textEdit->newText, "->Foo::x");
+  EXPECT_TRUE(R.additionalTextEdits.empty());
+}
+
+TEST(CompletionTest, RenderWithFixItNonMerged) {
+  TextEdit FixIt;
+  FixIt.range.end.character = 4;
+  FixIt.newText = "->";
+
+  CodeCompletion C;
+  C.Name = "x";
+  C.RequiredQualifier = "Foo::";
+  C.FixIts = {FixIt};
+  C.CompletionTokenRange.start.character = 5;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto R = C.render(Opts);
+  EXPECT_TRUE(R.textEdit);
+  EXPECT_EQ(R.textEdit->newText, "Foo::x");
+  EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
+}
+
+TEST(CompletionTest, CompletionTokenRange) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  constexpr const char *TestCodes[] = {
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+void f() {
+  Auxilary x;
+  x.[[Aux]]^;
+}
+  )cpp",
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+void f() {
+  Auxilary x;
+  x.[[]]^;
+}
+  )cpp"};
+  for (const auto  : TestCodes) {
+Annotations TestCode(Text);
+auto Results = completions(Server, TestCode.code(), TestCode.point());
+
+EXPECT_EQ(Results.Completions.size(), 1u);
+EXPECT_THAT(Results.Completions.front().CompletionTokenRange, TestCode.range());
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/SourceCode.h
===
--- clangd/SourceCode.h
+++ clangd/SourceCode.h
@@ -76,6 +76,8 @@
 /// are normalized as much as possible.
 llvm::Optional getRealPath(const FileEntry *F,
 const SourceManager );
+
+bool IsRangeConsecutive(const Range , const Range );
 } // namespace clangd
 } // namespace clang
 #endif
Index: clangd/SourceCode.cpp
===
--- clangd/SourceCode.cpp
+++ clangd/SourceCode.cpp
@@ -224,5 +224,10 @@
   return Result;
 }
 
+bool IsRangeConsecutive(const Range , const Range ) {
+  return Left.end.line == Right.start.line &&
+ Left.end.character == Right.start.character;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -123,6 +123,9 @@
   /// converting '->' to '.' on member access.
   std::vector FixIts;
 
+  /// Holds the range of the token we are going to replace with this completion.
+  Range CompletionTokenRange;
+
   // Scores are used to rank completion items.
   struct Scores {
 // The score that items are ranked by.
Index: clangd/CodeComplete.cpp

[PATCH] D50635: Fix lint tests for D50449

2018-08-13 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added a reviewer: ilya-biryukov.
Herald added subscribers: cfe-commits, arphaman, jkorous, ioeric.

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50635

Files:
  test/clangd/completion-snippets.test
  test/clangd/completion.test


Index: test/clangd/completion.test
===
--- test/clangd/completion.test
+++ test/clangd/completion.test
@@ -18,6 +18,19 @@
 # CHECK-NEXT:  "kind": 5,
 # CHECK-NEXT:  "label": " a",
 # CHECK-NEXT:  "sortText": "{{.*}}a"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "a",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:  ]
 ---
@@ -38,6 +51,19 @@
 # CHECK-NEXT:  "kind": 5,
 # CHECK-NEXT:  "label": " b",
 # CHECK-NEXT:  "sortText": "{{.*}}b"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "b",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:  ]
 ---
Index: test/clangd/completion-snippets.test
===
--- test/clangd/completion-snippets.test
+++ test/clangd/completion-snippets.test
@@ -34,6 +34,19 @@
 # CHECK-NEXT:  "kind": 3,
 # CHECK-NEXT:  "label": " func_with_args(int a, int b)",
 # CHECK-NEXT:  "sortText": "{{.*}}func_with_args"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "func_with_args(${1:int a}, ${2:int b})",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 7,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 0,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:]
 # CHECK-NEXT:  }


Index: test/clangd/completion.test
===
--- test/clangd/completion.test
+++ test/clangd/completion.test
@@ -18,6 +18,19 @@
 # CHECK-NEXT:  "kind": 5,
 # CHECK-NEXT:  "label": " a",
 # CHECK-NEXT:  "sortText": "{{.*}}a"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "a",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:  ]
 ---
@@ -38,6 +51,19 @@
 # CHECK-NEXT:  "kind": 5,
 # CHECK-NEXT:  "label": " b",
 # CHECK-NEXT:  "sortText": "{{.*}}b"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "b",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:  ]
 ---
Index: test/clangd/completion-snippets.test
===
--- test/clangd/completion-snippets.test
+++ test/clangd/completion-snippets.test
@@ -34,6 +34,19 @@
 # CHECK-NEXT:  "kind": 3,
 # CHECK-NEXT:  "label": " func_with_args(int a, int b)",
 # CHECK-NEXT:  "sortText": "{{.*}}func_with_args"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "func_with_args(${1:int a}, ${2:int b})",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 7,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 0,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:]
 # CHECK-NEXT:  }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50635: Fix lint tests for D50449

2018-08-13 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL339572: Fix lint tests for D50449 (authored by kadircet, 
committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D50635

Files:
  clang-tools-extra/trunk/test/clangd/completion-snippets.test
  clang-tools-extra/trunk/test/clangd/completion.test


Index: clang-tools-extra/trunk/test/clangd/completion.test
===
--- clang-tools-extra/trunk/test/clangd/completion.test
+++ clang-tools-extra/trunk/test/clangd/completion.test
@@ -18,6 +18,19 @@
 # CHECK-NEXT:  "kind": 5,
 # CHECK-NEXT:  "label": " a",
 # CHECK-NEXT:  "sortText": "{{.*}}a"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "a",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:  ]
 ---
@@ -38,6 +51,19 @@
 # CHECK-NEXT:  "kind": 5,
 # CHECK-NEXT:  "label": " b",
 # CHECK-NEXT:  "sortText": "{{.*}}b"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "b",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:  ]
 ---
Index: clang-tools-extra/trunk/test/clangd/completion-snippets.test
===
--- clang-tools-extra/trunk/test/clangd/completion-snippets.test
+++ clang-tools-extra/trunk/test/clangd/completion-snippets.test
@@ -34,6 +34,19 @@
 # CHECK-NEXT:  "kind": 3,
 # CHECK-NEXT:  "label": " func_with_args(int a, int b)",
 # CHECK-NEXT:  "sortText": "{{.*}}func_with_args"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "func_with_args(${1:int a}, ${2:int b})",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 7,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 0,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:]
 # CHECK-NEXT:  }


Index: clang-tools-extra/trunk/test/clangd/completion.test
===
--- clang-tools-extra/trunk/test/clangd/completion.test
+++ clang-tools-extra/trunk/test/clangd/completion.test
@@ -18,6 +18,19 @@
 # CHECK-NEXT:  "kind": 5,
 # CHECK-NEXT:  "label": " a",
 # CHECK-NEXT:  "sortText": "{{.*}}a"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "a",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:  ]
 ---
@@ -38,6 +51,19 @@
 # CHECK-NEXT:  "kind": 5,
 # CHECK-NEXT:  "label": " b",
 # CHECK-NEXT:  "sortText": "{{.*}}b"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "b",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 4,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
 # CHECK-NEXT:}
 # CHECK-NEXT:  ]
 ---
Index: clang-tools-extra/trunk/test/clangd/completion-snippets.test
===
--- clang-tools-extra/trunk/test/clangd/completion-snippets.test
+++ clang-tools-extra/trunk/test/clangd/completion-snippets.test
@@ -34,6 +34,19 @@
 # CHECK-NEXT:  "kind": 3,
 # CHECK-NEXT:  "label": " func_with_args(int a, int b)",
 # CHECK-NEXT:  "sortText": "{{.*}}func_with_args"
+# CHECK-NEXT:  "textEdit": {
+# CHECK-NEXT:"newText": "func_with_args(${1:int a}, ${2:int b})",
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 7,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:

[PATCH] D50449: [clangd] Support textEdit in addition to insertText.

2018-08-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 160073.
kadircet marked 5 inline comments as done.
kadircet added a comment.
Herald added a subscriber: mgrang.

- Resolve discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50449

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/SourceCode.cpp
  clangd/SourceCode.h
  unittests/clangd/CodeCompleteTests.cpp
  unittests/clangd/SourceCodeTests.cpp

Index: unittests/clangd/SourceCodeTests.cpp
===
--- unittests/clangd/SourceCodeTests.cpp
+++ unittests/clangd/SourceCodeTests.cpp
@@ -37,6 +37,13 @@
   return Pos;
 }
 
+Range range(const std::pair p1, const std::pair p2) {
+  Range range;
+  range.start = position(p1.first, p1.second);
+  range.end = position(p2.first, p2.second);
+  return range;
+}
+
 TEST(SourceCodeTests, PositionToOffset) {
   // line out of bounds
   EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), Failed());
@@ -119,6 +126,14 @@
   EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 9)) << "out of bounds";
 }
 
+TEST(SourceCodeTests, IsRangeConsecutive) {
+  EXPECT_TRUE(IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 3}, {2, 4})));
+  EXPECT_FALSE(
+  IsRangeConsecutive(range({0, 2}, {0, 3}), range({2, 3}, {2, 4})));
+  EXPECT_FALSE(
+  IsRangeConsecutive(range({2, 2}, {2, 3}), range({2, 4}, {2, 5})));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1438,6 +1438,82 @@
   }
 }
 
+TEST(CompletionTest, RenderWithFixItMerged) {
+  TextEdit FixIt;
+  FixIt.range.end.character = 5;
+  FixIt.newText = "->";
+
+  CodeCompletion C;
+  C.Name = "x";
+  C.RequiredQualifier = "Foo::";
+  C.FixIts = {FixIt};
+  C.CompletionTokenRange.start.character = 5;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto R = C.render(Opts);
+  EXPECT_TRUE(R.textEdit);
+  EXPECT_EQ(R.textEdit->newText, "->Foo::x");
+  EXPECT_TRUE(R.additionalTextEdits.empty());
+}
+
+TEST(CompletionTest, RenderWithFixItNonMerged) {
+  TextEdit FixIt;
+  FixIt.range.end.character = 4;
+  FixIt.newText = "->";
+
+  CodeCompletion C;
+  C.Name = "x";
+  C.RequiredQualifier = "Foo::";
+  C.FixIts = {FixIt};
+  C.CompletionTokenRange.start.character = 5;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeFixIts = true;
+
+  auto R = C.render(Opts);
+  EXPECT_TRUE(R.textEdit);
+  EXPECT_EQ(R.textEdit->newText, "Foo::x");
+  EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));
+}
+
+TEST(CompletionTest, CompletionTokenRange) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB;
+  IgnoreDiagnostics DiagConsumer;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  constexpr const char *TestCodes[] = {
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+void f() {
+  Auxilary x;
+  x.[[Aux]]^;
+}
+  )cpp",
+  R"cpp(
+class Auxilary {
+ public:
+  void AuxFunction();
+};
+void f() {
+  Auxilary x;
+  x.[[]]^;
+}
+  )cpp"};
+  for (const auto  : TestCodes) {
+Annotations TestCode(Text);
+auto Results = completions(Server, TestCode.code(), TestCode.point());
+
+EXPECT_EQ(Results.Completions.size(), 1u);
+EXPECT_THAT(Results.Completions.front().CompletionTokenRange, TestCode.range());
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/SourceCode.h
===
--- clangd/SourceCode.h
+++ clangd/SourceCode.h
@@ -69,6 +69,7 @@
 TextEdit toTextEdit(const FixItHint , const SourceManager ,
 const LangOptions );
 
+bool IsRangeConsecutive(const Range , const Range );
 } // namespace clangd
 } // namespace clang
 #endif
Index: clangd/SourceCode.cpp
===
--- clangd/SourceCode.cpp
+++ clangd/SourceCode.cpp
@@ -208,5 +208,10 @@
   return Result;
 }
 
+bool IsRangeConsecutive(const Range , const Range ) {
+  return Left.end.line == Right.start.line &&
+ Left.end.character == Right.start.character;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -123,6 +123,9 @@
   /// converting '->' to '.' on member access.
   std::vector FixIts;
 
+  /// Holds the range of the token we are going to replace with this completion.
+  Range CompletionTokenRange;
+
   // Scores are used to rank completion items.
   struct Scores {
 // The score that items are ranked by.
Index: clangd/CodeComplete.cpp

[PATCH] D50555: [clangd] Introduce scoring mechanism for SignatureInformations.

2018-08-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added a reviewer: ilya-biryukov.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, ioeric.

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50555

Files:
  clangd/CodeComplete.cpp
  clangd/Quality.cpp
  clangd/Quality.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1438,6 +1438,28 @@
   }
 }
 
+TEST(SignatureHelpTest, OverloadsOrdering) {
+  const auto Results = signatures(R"cpp(
+void foo(int x);
+void foo(int x, float y);
+void foo(float x, int y);
+void foo(float x, float y);
+void foo(int x, int y = 0);
+int main() { foo(^); }
+  )cpp");
+  EXPECT_THAT(
+  Results.signatures,
+  ElementsAre(
+  Sig("foo(int x) -> void", {"int x"}),
+  Sig("foo(int x, int y = 0) -> void", {"int x", "int y = 0"}),
+  Sig("foo(float x, int y) -> void", {"float x", "int y"}),
+  Sig("foo(int x, float y) -> void", {"int x", "float y"}),
+  Sig("foo(float x, float y) -> void", {"float x", "float y"})));
+  // We always prefer the first signature.
+  EXPECT_EQ(0, Results.activeSignature);
+  EXPECT_EQ(0, Results.activeParameter);
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/Quality.h
===
--- clangd/Quality.h
+++ clangd/Quality.h
@@ -163,6 +163,17 @@
 /// LSP. (The highest score compares smallest so it sorts at the top).
 std::string sortText(float Score, llvm::StringRef Tiebreak = "");
 
+struct SignatureQualitySignals {
+  uint32_t NumberOfParameters = 0;
+  uint32_t NumberOfOptionalParameters = 0;
+  bool ContainsActiveParameter = false;
+  CodeCompleteConsumer::OverloadCandidate::CandidateKind Kind;
+
+  float evaluate() const;
+};
+llvm::raw_ostream <<(llvm::raw_ostream &,
+  const SignatureQualitySignals &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Quality.cpp
===
--- clangd/Quality.cpp
+++ clangd/Quality.cpp
@@ -401,5 +401,36 @@
   return S;
 }
 
+llvm::raw_ostream <<(llvm::raw_ostream ,
+  const SignatureQualitySignals ) {
+  OS << formatv("=== Signature Quality: {0}\n", S.evaluate());
+  OS << formatv("\tNumber of parameters: {0}\n", S.NumberOfParameters);
+  OS << formatv("\tNumber of optional parameters: {0}\n",
+S.NumberOfOptionalParameters);
+  OS << formatv("\tContains active parameter: {0}\n",
+S.ContainsActiveParameter);
+  OS << formatv("\tKind: {0}\n", S.Kind);
+  return OS;
+}
+
+float SignatureQualitySignals::evaluate() const {
+  using OC = CodeCompleteConsumer::OverloadCandidate;
+  float score = 1;
+  score /= NumberOfParameters + 1;
+  if (ContainsActiveParameter)
+score *= 10;
+  switch (Kind) {
+  case OC::CK_Function:
+score *= 10;
+break;
+  case OC::CK_FunctionType:
+score *= 5;
+break;
+  case OC::CK_FunctionTemplate:
+break;
+  }
+  return score;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -128,16 +128,16 @@
 /// Get the optional chunk as a string. This function is possibly recursive.
 ///
 /// The parameter info for each parameter is appended to the Parameters.
-std::string
-getOptionalParameters(const CodeCompletionString ,
-  std::vector ) {
+std::string getOptionalParameters(const CodeCompletionString ,
+  std::vector ,
+  SignatureQualitySignals ) {
   std::string Result;
   for (const auto  : CCS) {
 switch (Chunk.Kind) {
 case CodeCompletionString::CK_Optional:
   assert(Chunk.Optional &&
  "Expected the optional code completion string to be non-null.");
-  Result += getOptionalParameters(*Chunk.Optional, Parameters);
+  Result += getOptionalParameters(*Chunk.Optional, Parameters, Signal);
   break;
 case CodeCompletionString::CK_VerticalSpace:
   break;
@@ -153,6 +153,8 @@
   ParameterInformation Info;
   Info.label = Chunk.Text;
   Parameters.push_back(std::move(Info));
+  Signal.ContainsActiveParameter = true;
+  Signal.NumberOfOptionalParameters++;
   break;
 }
 default:
@@ -679,6 +681,24 @@
   llvm::unique_function ResultsCallback;
 };
 
+using SignatureInformationScore = float;
+using ScoredSignature =
+std::pair;
+struct ScoredSignatureGreater {
+  bool operator()(const ScoredSignature , const ScoredSignature ) {
+// Ordering follows:
+// - High score is better.
+// - Shorter signature is better.
+// - 

[PATCH] D50449: [clangd] Support textEdit in addition to insertText.

2018-08-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/CodeComplete.cpp:1310
+  // other.
+  for (const auto  : FixIts) {
+if (IsRangeConsecutive(FixIt.range, LSP.textEdit->range)) {

ilya-biryukov wrote:
> Maybe keep the `reserve` call? (we could reserve one extra element, but 
> that's fine)
Actually we could have much more than one extra element, not for the current 
situation but may be in the future when we have more fixit completions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50449



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


[PATCH] D50555: [clangd] Introduce scoring mechanism for SignatureInformations.

2018-08-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 160097.
kadircet marked 3 inline comments as done.
kadircet added a comment.
Herald added a subscriber: mgrang.

- Resolve discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50555

Files:
  clangd/CodeComplete.cpp
  clangd/Quality.cpp
  clangd/Quality.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1438,6 +1438,28 @@
   }
 }
 
+TEST(SignatureHelpTest, OverloadsOrdering) {
+  const auto Results = signatures(R"cpp(
+void foo(int x);
+void foo(int x, float y);
+void foo(float x, int y);
+void foo(float x, float y);
+void foo(int x, int y = 0);
+int main() { foo(^); }
+  )cpp");
+  EXPECT_THAT(
+  Results.signatures,
+  ElementsAre(
+  Sig("foo(int x) -> void", {"int x"}),
+  Sig("foo(int x, int y = 0) -> void", {"int x", "int y = 0"}),
+  Sig("foo(float x, int y) -> void", {"float x", "int y"}),
+  Sig("foo(int x, float y) -> void", {"int x", "float y"}),
+  Sig("foo(float x, float y) -> void", {"float x", "float y"})));
+  // We always prefer the first signature.
+  EXPECT_EQ(0, Results.activeSignature);
+  EXPECT_EQ(0, Results.activeParameter);
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/Quality.h
===
--- clangd/Quality.h
+++ clangd/Quality.h
@@ -163,6 +163,16 @@
 /// LSP. (The highest score compares smallest so it sorts at the top).
 std::string sortText(float Score, llvm::StringRef Tiebreak = "");
 
+struct SignatureQualitySignals {
+  uint32_t NumberOfParameters = 0;
+  uint32_t NumberOfOptionalParameters = 0;
+  bool ContainsActiveParameter = false;
+  CodeCompleteConsumer::OverloadCandidate::CandidateKind Kind =
+  CodeCompleteConsumer::OverloadCandidate::CandidateKind::CK_Function;
+};
+llvm::raw_ostream <<(llvm::raw_ostream &,
+  const SignatureQualitySignals &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Quality.cpp
===
--- clangd/Quality.cpp
+++ clangd/Quality.cpp
@@ -401,5 +401,17 @@
   return S;
 }
 
+llvm::raw_ostream <<(llvm::raw_ostream ,
+  const SignatureQualitySignals ) {
+  OS << formatv("=== Signature Quality:\n");
+  OS << formatv("\tNumber of parameters: {0}\n", S.NumberOfParameters);
+  OS << formatv("\tNumber of optional parameters: {0}\n",
+S.NumberOfOptionalParameters);
+  OS << formatv("\tContains active parameter: {0}\n",
+S.ContainsActiveParameter);
+  OS << formatv("\tKind: {0}\n", S.Kind);
+  return OS;
+}
+
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -128,16 +128,16 @@
 /// Get the optional chunk as a string. This function is possibly recursive.
 ///
 /// The parameter info for each parameter is appended to the Parameters.
-std::string
-getOptionalParameters(const CodeCompletionString ,
-  std::vector ) {
+std::string getOptionalParameters(const CodeCompletionString ,
+  std::vector ,
+  SignatureQualitySignals ) {
   std::string Result;
   for (const auto  : CCS) {
 switch (Chunk.Kind) {
 case CodeCompletionString::CK_Optional:
   assert(Chunk.Optional &&
  "Expected the optional code completion string to be non-null.");
-  Result += getOptionalParameters(*Chunk.Optional, Parameters);
+  Result += getOptionalParameters(*Chunk.Optional, Parameters, Signal);
   break;
 case CodeCompletionString::CK_VerticalSpace:
   break;
@@ -153,6 +153,8 @@
   ParameterInformation Info;
   Info.label = Chunk.Text;
   Parameters.push_back(std::move(Info));
+  Signal.ContainsActiveParameter = true;
+  Signal.NumberOfOptionalParameters++;
   break;
 }
 default:
@@ -679,6 +681,41 @@
   llvm::unique_function ResultsCallback;
 };
 
+using ScoredSignature =
+std::pair;
+struct ScoredSignatureGreater {
+  bool operator()(const ScoredSignature , const ScoredSignature ) {
+// Ordering follows:
+// - Less number of parameters is better.
+// - Function is better than FunctionType which is better than Function
+// Template.
+// - High score is better.
+// - Shorter signature is better.
+// - Alphebatically smaller is better.
+if (L.first.NumberOfParameters != R.first.NumberOfParameters)
+  return L.first.NumberOfParameters < R.first.NumberOfParameters;
+if (L.first.NumberOfOptionalParameters !=
+R.first.NumberOfOptionalParameters)
+  

[PATCH] D50443: [clang] Store code completion token range in preprocessor.This change is to support a new fature in clangd, tests will be send toclang-tools-extra with that change.

2018-08-08 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added a reviewer: ilya-biryukov.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, ioeric.

Repository:
  rC Clang

https://reviews.llvm.org/D50443

Files:
  include/clang/Lex/Preprocessor.h
  lib/Lex/Preprocessor.cpp


Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -868,6 +868,7 @@
   if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
 // Remember the identifier before code completion token.
 setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+setCodeCompletionTokenRange(Result.getLocation(), Result.getEndLoc());
 // Set IdenfitierInfo to null to avoid confusing code that handles both
 // identifiers and completion tokens.
 Result.setIdentifierInfo(nullptr);
Index: include/clang/Lex/Preprocessor.h
===
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -310,6 +310,9 @@
   /// on the stem that is to be code completed.
   IdentifierInfo *CodeCompletionII = nullptr;
 
+  /// Range for the code completion taken.
+  SourceRange CodeCompletionTokenRange;
+
   /// The directory that the main file should be considered to occupy,
   /// if it does not correspond to a real file (as happens when building a
   /// module).
@@ -1131,6 +1134,16 @@
 CodeCompletionII = Filter;
   }
 
+  /// Set the code completion token range for detecting replacement range later
+  /// on.
+  void setCodeCompletionTokenRange(const SourceLocation start,
+   const SourceLocation end) {
+CodeCompletionTokenRange = {start, end};
+  }
+  SourceRange getCodeCompletionTokenRange() const {
+return CodeCompletionTokenRange;
+  }
+
   /// Get the code completion token for filtering purposes.
   StringRef getCodeCompletionFilter() {
 if (CodeCompletionII)


Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -868,6 +868,7 @@
   if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
 // Remember the identifier before code completion token.
 setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+setCodeCompletionTokenRange(Result.getLocation(), Result.getEndLoc());
 // Set IdenfitierInfo to null to avoid confusing code that handles both
 // identifiers and completion tokens.
 Result.setIdentifierInfo(nullptr);
Index: include/clang/Lex/Preprocessor.h
===
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -310,6 +310,9 @@
   /// on the stem that is to be code completed.
   IdentifierInfo *CodeCompletionII = nullptr;
 
+  /// Range for the code completion taken.
+  SourceRange CodeCompletionTokenRange;
+
   /// The directory that the main file should be considered to occupy,
   /// if it does not correspond to a real file (as happens when building a
   /// module).
@@ -1131,6 +1134,16 @@
 CodeCompletionII = Filter;
   }
 
+  /// Set the code completion token range for detecting replacement range later
+  /// on.
+  void setCodeCompletionTokenRange(const SourceLocation start,
+   const SourceLocation end) {
+CodeCompletionTokenRange = {start, end};
+  }
+  SourceRange getCodeCompletionTokenRange() const {
+return CodeCompletionTokenRange;
+  }
+
   /// Get the code completion token for filtering purposes.
   StringRef getCodeCompletionFilter() {
 if (CodeCompletionII)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50443: [clang] Store code completion token range in preprocessor.

2018-08-08 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 159703.
kadircet marked an inline comment as done.
kadircet added a comment.

- Resolve discussions.


Repository:
  rC Clang

https://reviews.llvm.org/D50443

Files:
  include/clang/Lex/Preprocessor.h
  lib/Lex/Preprocessor.cpp


Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -868,6 +868,7 @@
   if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
 // Remember the identifier before code completion token.
 setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+setCodeCompletionTokenRange(Result.getLocation(), Result.getEndLoc());
 // Set IdenfitierInfo to null to avoid confusing code that handles both
 // identifiers and completion tokens.
 Result.setIdentifierInfo(nullptr);
Index: include/clang/Lex/Preprocessor.h
===
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -310,6 +310,9 @@
   /// on the stem that is to be code completed.
   IdentifierInfo *CodeCompletionII = nullptr;
 
+  /// Range for the code completion taken.
+  SourceRange CodeCompletionTokenRange;
+
   /// The directory that the main file should be considered to occupy,
   /// if it does not correspond to a real file (as happens when building a
   /// module).
@@ -1131,6 +1134,16 @@
 CodeCompletionII = Filter;
   }
 
+  /// Set the code completion token range for detecting replacement range later
+  /// on.
+  void setCodeCompletionTokenRange(const SourceLocation Start,
+   const SourceLocation End) {
+CodeCompletionTokenRange = {Start, End};
+  }
+  SourceRange getCodeCompletionTokenRange() const {
+return CodeCompletionTokenRange;
+  }
+
   /// Get the code completion token for filtering purposes.
   StringRef getCodeCompletionFilter() {
 if (CodeCompletionII)


Index: lib/Lex/Preprocessor.cpp
===
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -868,6 +868,7 @@
   if (Result.is(tok::code_completion) && Result.getIdentifierInfo()) {
 // Remember the identifier before code completion token.
 setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+setCodeCompletionTokenRange(Result.getLocation(), Result.getEndLoc());
 // Set IdenfitierInfo to null to avoid confusing code that handles both
 // identifiers and completion tokens.
 Result.setIdentifierInfo(nullptr);
Index: include/clang/Lex/Preprocessor.h
===
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -310,6 +310,9 @@
   /// on the stem that is to be code completed.
   IdentifierInfo *CodeCompletionII = nullptr;
 
+  /// Range for the code completion taken.
+  SourceRange CodeCompletionTokenRange;
+
   /// The directory that the main file should be considered to occupy,
   /// if it does not correspond to a real file (as happens when building a
   /// module).
@@ -1131,6 +1134,16 @@
 CodeCompletionII = Filter;
   }
 
+  /// Set the code completion token range for detecting replacement range later
+  /// on.
+  void setCodeCompletionTokenRange(const SourceLocation Start,
+   const SourceLocation End) {
+CodeCompletionTokenRange = {Start, End};
+  }
+  SourceRange getCodeCompletionTokenRange() const {
+return CodeCompletionTokenRange;
+  }
+
   /// Get the code completion token for filtering purposes.
   StringRef getCodeCompletionFilter() {
 if (CodeCompletionII)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-17 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet marked an inline comment as done.
kadircet added inline comments.



Comment at: clangd/ClangdLSPServer.cpp:621
+  std::lock_guard Lock(TaskHandlesMutex);
+  const auto  = TaskHandles.find(Params.ID);
+  if (it != TaskHandles.end()) {

ilya-biryukov wrote:
> Wouldn't it work incorrectly for string IDs?
> When normalizing `json::Value` from `getRequestID`, we simply print out json. 
> For strings, this should result in quoted output, e.g. `"req"`. However, when 
> parsing `CancelParams`, we parse this json. So we'll end up inserting with a 
> key `"req"` and erasing with a key 'req' (without the quotes).
You are right, that's exactly the case, thanks!


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502



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


[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-17 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161261.
kadircet marked 10 inline comments as done.
kadircet added a comment.

- Resolve discussions & Delete enclosing quotes when normalizing.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,79 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "Threading.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  TaskHandle TH = TaskHandle::create();
+  WithContext ContextWithCancellation(
+  setCurrentCancellationToken(TH.createCancellationToken()));
+  EXPECT_FALSE(isCancelled());
+  TH.cancel();
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+auto CancellableTaskHandle = TaskHandle::create();
+ContextWithCancellation.emplace(setCurrentCancellationToken(
+CancellableTaskHandle.createCancellationToken()));
+EXPECT_FALSE(isCancelled());
+CancellableTaskHandle.cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleContextDiesHandleLives) {
+  auto CancellableTaskHandle = TaskHandle::create();
+  {
+WithContext ContextWithCancellation(setCurrentCancellationToken(
+CancellableTaskHandle.createCancellationToken()));
+EXPECT_FALSE(isCancelled());
+CancellableTaskHandle.cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  // Still should be able to cancel without any problems.
+  CancellableTaskHandle.cancel();
+}
+
+TEST(CancellationTest, CancellationToken) {
+  auto CancellableTaskHandle = TaskHandle::create();
+  WithContext ContextWithCancellation(setCurrentCancellationToken(
+  CancellableTaskHandle.createCancellationToken()));
+  const auto  = getCurrentCancellationToken();
+  EXPECT_FALSE(CT);
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(CT);
+}
+
+TEST(CancellationTest, AsynCancellationTest) {
+  std::atomic HasCancelled(false);
+  Notification Cancelled;
+  auto TaskToBeCancelled = [&](CancellationToken CT) {
+WithContext ContextGuard(setCurrentCancellationToken(std::move(CT)));
+Cancelled.wait();
+HasCancelled = isCancelled();
+  };
+  TaskHandle TH = TaskHandle::create();
+  std::thread AsyncTask(TaskToBeCancelled, TH.createCancellationToken());
+  TH.cancel();
+  Cancelled.notify();
+  AsyncTask.join();
+
+  EXPECT_TRUE(HasCancelled);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -867,6 +867,16 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  /// The request id to cancel.
+  /// This can be either a number or string, if it is a number simply print it
+  /// out and always use a string.
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream 

[PATCH] D50898: Suggest code-completions for overriding base class virtual methods.

2018-08-17 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added reviewers: ilya-biryukov, hokein, ioeric.
Herald added subscribers: cfe-commits, arphaman, jkorous.

Whenever a code-completion is triggered within a class/struct/union looks at
base classes and figures out non-overriden virtual functions. Than suggests
completions for those.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50898

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -61,6 +61,7 @@
 MATCHER(InsertInclude, "") { return bool(arg.HeaderInsertion); }
 MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
 MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
+MATCHER(IsOverride, "") { return bool(arg.IsOverride); }
 
 // Shorthand for Contains(Named(Name)).
 Matcher &> Has(std::string Name) {
@@ -1648,6 +1649,58 @@
 SigDoc("Doc from sema";
 }
 
+TEST(CompletionTest, SuggestOverrides) {
+  constexpr const char *const Text(R"cpp(
+  class A {
+   public:
+virtual void vfunc(bool param);
+virtual void vfunc(bool param, int p);
+void func(bool param);
+  };
+  class B : public A {
+  virtual void ttt(bool param);
+  void vfunc(bool param, int p) override;
+  };
+  class C : public B {
+   public:
+void vfunc(bool param) override;
+^
+  };
+  )cpp");
+  const auto Results = completions(Text);
+  EXPECT_THAT(Results.Completions,
+  AllOf(Contains(AllOf(Named("vfunc"), IsOverride(),
+   Labeled("vfunc(bool param, int p)"))),
+Contains(AllOf(Named("ttt"), IsOverride(),
+   Labeled("ttt(bool param)"))),
+Not(Contains(AllOf(Named("vfunc"), IsOverride(),
+   Labeled("vfunc(bool param)"));
+}
+
+TEST(CompletionTest, RenderOverride) {
+  CodeCompletion C;
+  C.Name = "x";
+  C.Signature = "(bool) const";
+  C.SnippetSuffix = "(${0:bool})";
+  C.ReturnType = "int";
+  C.Documentation = "This is x().";
+  C.Kind = CompletionItemKind::Method;
+  C.Score.Total = 1.0;
+  C.Origin = SymbolOrigin::AST;
+  C.IsOverride = true;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeIndicator.NoInsert = "";
+  auto R = C.render(Opts);
+  EXPECT_EQ(R.label, "int x(bool) const override");
+  EXPECT_EQ(R.insertText, "int x(bool) const override");
+  EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  EXPECT_EQ(R.filterText, "x");
+  EXPECT_EQ(R.detail, "int");
+  EXPECT_EQ(R.documentation, "This is x().");
+  EXPECT_THAT(R.additionalTextEdits, IsEmpty());
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -127,6 +127,9 @@
   /// Holds the range of the token we are going to replace with this completion.
   Range CompletionTokenRange;
 
+  /// Whether this completion is for overriding a virtual method.
+  bool IsOverride = false;
+
   // Scores are used to rank completion items.
   struct Scores {
 // The score that items are ranked by.
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -188,6 +188,58 @@
   return HeaderFile{std::move(*Resolved), /*Verbatim=*/false};
 }
 
+// First traverses all method definitions inside current class/struct/union
+// definition. Than traverses base classes to find virtual methods that haven't
+// been overriden within current context.
+// FIXME(kadircet): Currently we cannot see declarations below completion point.
+// It is because Sema gets run only upto completion point. Need to find a
+// solution to run it for the whole class/struct/union definition.
+static std::vector
+getVirtualNonOverridenMethods(const DeclContext *DC, Sema *S) {
+  const auto *CR = llvm::dyn_cast(DC);
+  // If not inside a class/struct/union return empty.
+  if (!CR)
+return {};
+  // First store overrides within current class.
+  // These are stored by name to make querying fast in the later step.
+  llvm::StringMap> Overrides;
+  for (auto *Method : dyn_cast(DC)->methods()) {
+if (!Method->isVirtual())
+  continue;
+const std::string Name = Method->getNameAsString();
+const auto it = Overrides.find(Name);
+if (it == Overrides.end())
+  Overrides.insert({Name, {Method}});
+else
+  it->second.push_back(Method);
+  }
+
+  std::vector Results;
+  for (const auto  : CR->bases()) {
+const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
+for (auto *Method : BR->methods()) {
+  if (!Method->isVirtual())
+continue;
+  const 

[PATCH] D50835: [clangd] Add parantheses while auto-completing functions.

2018-08-17 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/CodeComplete.cpp:1381
+  // Check whether function has any parameters or not.
+  LSP.textEdit->newText += SnippetSuffix.size() > 2 ? "(${0})" : "()";
+}

ioeric wrote:
> I think we are missing one case here: `!EnableFunctionArgSnippets && ( function or method>)`?
> 
> I think we could do something like:
> ```
> if (!EnableFunctionArgSnippets && ())
>   // Truncate parameter template
> else
>   // append snippet like before
> 
> ```
Thanks!


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50835



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


[PATCH] D50835: [clangd] Add parantheses while auto-completing functions.

2018-08-17 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161265.
kadircet marked 3 inline comments as done.
kadircet added a comment.

- Resolve discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50835

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1590,6 +1590,58 @@
   ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
 }
 
+TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) {
+  CodeCompleteOptions Opts;
+  Opts.EnableFunctionArgSnippets = true;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  }
+
+  Opts.EnableSnippets = true;
+  Opts.EnableFunctionArgSnippets = false;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+C.Kind = CompletionItemKind::Method;
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x()");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "(${0:bool})";
+C.Kind = CompletionItemKind::Function;
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -82,6 +82,10 @@
   /// Include completions that require small corrections, e.g. change '.' to
   /// '->' on member access etc.
   bool IncludeFixIts = false;
+
+  /// Whether to generate snippets for function arguments on code-completion.
+  /// Needs snippets to be enabled as well.
+  bool EnableFunctionArgSnippets = true;
 };
 
 // Semi-structured representation of a code-complete suggestion for our C++ API.
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -1371,8 +1371,17 @@
   LSP.additionalTextEdits.push_back(FixIt);
 }
   }
-  if (Opts.EnableSnippets)
-LSP.textEdit->newText += SnippetSuffix;
+  if (Opts.EnableSnippets && !SnippetSuffix.empty()) {
+if (!Opts.EnableFunctionArgSnippets &&
+((Kind == CompletionItemKind::Function) ||
+ (Kind == CompletionItemKind::Method)) &&
+(SnippetSuffix.front() == '(') && (SnippetSuffix.back() == ')'))
+  // Check whether function has any parameters or not.
+  LSP.textEdit->newText += SnippetSuffix.size() > 2 ? "(${0})" : "()";
+else
+  LSP.textEdit->newText += SnippetSuffix;
+  }
+
   // FIXME(kadircet): Do not even fill insertText after making sure textEdit is
   // compatible with most of the editors.
   LSP.insertText = LSP.textEdit->newText;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50835: [clangd] Add parantheses while auto-completing functions.

2018-08-17 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161243.
kadircet added a comment.

- Change option name.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50835

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  unittests/clangd/CodeCompleteTests.cpp


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1590,6 +1590,56 @@
   ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
 }
 
+TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) {
+  CodeCompleteOptions Opts;
+  Opts.EnableFunctionArgSnippets = true;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  }
+
+  Opts.EnableSnippets = true;
+  Opts.EnableFunctionArgSnippets = false;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x()");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "(${0:bool})";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -82,6 +82,10 @@
   /// Include completions that require small corrections, e.g. change '.' to
   /// '->' on member access etc.
   bool IncludeFixIts = false;
+
+  /// Whether to generate snippets for function arguments on code-completion.
+  /// Needs snippets to be enabled as well.
+  bool EnableFunctionArgSnippets = true;
 };
 
 // Semi-structured representation of a code-complete suggestion for our C++ 
API.
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -1371,8 +1371,14 @@
   LSP.additionalTextEdits.push_back(FixIt);
 }
   }
-  if (Opts.EnableSnippets)
-LSP.textEdit->newText += SnippetSuffix;
+  if (Opts.EnableSnippets && !SnippetSuffix.empty()) {
+if (Opts.EnableFunctionArgSnippets)
+  LSP.textEdit->newText += SnippetSuffix;
+else
+  // Check whether function has any parameters or not.
+  LSP.textEdit->newText += SnippetSuffix.size() > 2 ? "(${0})" : "()";
+  }
+
   // FIXME(kadircet): Do not even fill insertText after making sure textEdit is
   // compatible with most of the editors.
   LSP.insertText = LSP.textEdit->newText;


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1590,6 +1590,56 @@
   ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
 }
 
+TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) {
+  CodeCompleteOptions Opts;
+  Opts.EnableFunctionArgSnippets = true;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  }
+
+  Opts.EnableSnippets = true;
+  Opts.EnableFunctionArgSnippets = false;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x()");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "(${0:bool})";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- 

[PATCH] D50835: [clangd] Add parantheses while auto-completing functions.

2018-08-17 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet marked 3 inline comments as done.
kadircet added inline comments.



Comment at: clangd/CodeComplete.cpp:1377
+  // Check whether function has any parameters or not.
+  LSP.textEdit->newText += SnippetSuffix.size() > 2 ? "(${0})" : "()";
+else

ioeric wrote:
> There seems to be no guarantee on whether the snippet is function arg 
> template when `SnippetSuffix.size() > 2`. A heuristic we could use is 
> probably checking that the template starts with `(` and ends with `)`? 
> Alternatively, we could try to avoid generating the proper snippet according 
> to the flag when we still have the function declaration around. Not sure if 
> this is feasible for index results though.
Actually I was first trying to directly look at function argument count as you 
mentioned, but unfortunately Symbols coming from index don't have any 
declarations. Therefore it turns back to looking at Signature in this case, 
which is same with this one. Apart from that, IIUC, SnippetSuffix contains 
anything only when completion item is a function otherwise it is empty. So IMO 
this check should be OK.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50835



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


[PATCH] D50835: [clangd] Add parantheses while auto-completing functions.

2018-08-17 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161256.
kadircet added a comment.

- Only append to snippets of type function or method.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50835

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1590,6 +1590,58 @@
   ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
 }
 
+TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) {
+  CodeCompleteOptions Opts;
+  Opts.EnableFunctionArgSnippets = true;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  }
+
+  Opts.EnableSnippets = true;
+  Opts.EnableFunctionArgSnippets = false;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+C.Kind = CompletionItemKind::Method;
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x()");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "(${0:bool})";
+C.Kind = CompletionItemKind::Function;
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -82,6 +82,10 @@
   /// Include completions that require small corrections, e.g. change '.' to
   /// '->' on member access etc.
   bool IncludeFixIts = false;
+
+  /// Whether to generate snippets for function arguments on code-completion.
+  /// Needs snippets to be enabled as well.
+  bool EnableFunctionArgSnippets = true;
 };
 
 // Semi-structured representation of a code-complete suggestion for our C++ API.
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -1371,8 +1371,17 @@
   LSP.additionalTextEdits.push_back(FixIt);
 }
   }
-  if (Opts.EnableSnippets)
-LSP.textEdit->newText += SnippetSuffix;
+  if (Opts.EnableSnippets && !SnippetSuffix.empty()) {
+if (Opts.EnableFunctionArgSnippets)
+  LSP.textEdit->newText += SnippetSuffix;
+else if ((Kind == CompletionItemKind::Function ||
+  Kind == CompletionItemKind::Method) &&
+ SnippetSuffix.front() == '(' && SnippetSuffix.back() == ')') {
+  // Check whether function has any parameters or not.
+  LSP.textEdit->newText += SnippetSuffix.size() > 2 ? "(${0})" : "()";
+}
+  }
+
   // FIXME(kadircet): Do not even fill insertText after making sure textEdit is
   // compatible with most of the editors.
   LSP.insertText = LSP.textEdit->newText;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50835: [clangd] Add parantheses while auto-completing functions.

2018-08-17 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL340040: [clangd] Add parantheses while auto-completing 
functions. (authored by kadircet, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D50835?vs=161265=161267#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D50835

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

Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
@@ -1648,6 +1648,58 @@
 SigDoc("Doc from sema";
 }
 
+TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) {
+  CodeCompleteOptions Opts;
+  Opts.EnableFunctionArgSnippets = true;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  }
+
+  Opts.EnableSnippets = true;
+  Opts.EnableFunctionArgSnippets = false;
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "";
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "()";
+C.Kind = CompletionItemKind::Method;
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x()");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+
+  {
+CodeCompletion C;
+C.RequiredQualifier = "Foo::";
+C.Name = "x";
+C.SnippetSuffix = "(${0:bool})";
+C.Kind = CompletionItemKind::Function;
+
+auto R = C.render(Opts);
+EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
+EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/trunk/clangd/CodeComplete.cpp
===
--- clang-tools-extra/trunk/clangd/CodeComplete.cpp
+++ clang-tools-extra/trunk/clangd/CodeComplete.cpp
@@ -1413,8 +1413,17 @@
   LSP.additionalTextEdits.push_back(FixIt);
 }
   }
-  if (Opts.EnableSnippets)
-LSP.textEdit->newText += SnippetSuffix;
+  if (Opts.EnableSnippets && !SnippetSuffix.empty()) {
+if (!Opts.EnableFunctionArgSnippets &&
+((Kind == CompletionItemKind::Function) ||
+ (Kind == CompletionItemKind::Method)) &&
+(SnippetSuffix.front() == '(') && (SnippetSuffix.back() == ')'))
+  // Check whether function has any parameters or not.
+  LSP.textEdit->newText += SnippetSuffix.size() > 2 ? "(${0})" : "()";
+else
+  LSP.textEdit->newText += SnippetSuffix;
+  }
+
   // FIXME(kadircet): Do not even fill insertText after making sure textEdit is
   // compatible with most of the editors.
   LSP.insertText = LSP.textEdit->newText;
Index: clang-tools-extra/trunk/clangd/CodeComplete.h
===
--- clang-tools-extra/trunk/clangd/CodeComplete.h
+++ clang-tools-extra/trunk/clangd/CodeComplete.h
@@ -82,6 +82,10 @@
   /// Include completions that require small corrections, e.g. change '.' to
   /// '->' on member access etc.
   bool IncludeFixIts = false;
+
+  /// Whether to generate snippets for function arguments on code-completion.
+  /// Needs snippets to be enabled as well.
+  bool EnableFunctionArgSnippets = true;
 };
 
 // Semi-structured representation of a code-complete suggestion for our C++ API.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50962: [clangd] Speculative code completion index request before Sema is run.

2018-08-20 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: unittests/clangd/CodeCompleteTests.cpp:1710
+  $bol^
+  ab$ab^
+  x.ab$dot^

Maybe an EXPECT for this one as well?


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50962



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


[PATCH] D50898: [clangd] Suggest code-completions for overriding base class virtual methods.

2018-08-21 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161683.
kadircet marked 3 inline comments as done.
kadircet added a comment.

- Put overrides through scoring and resolve nits.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50898

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -61,6 +61,7 @@
 MATCHER(InsertInclude, "") { return bool(arg.HeaderInsertion); }
 MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
 MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
+MATCHER(IsOverride, "") { return bool(arg.IsOverride); }
 
 // Shorthand for Contains(Named(Name)).
 Matcher &> Has(std::string Name) {
@@ -1648,6 +1649,58 @@
 SigDoc("Doc from sema";
 }
 
+TEST(CompletionTest, SuggestOverrides) {
+  constexpr const char *const Text(R"cpp(
+  class A {
+   public:
+virtual void vfunc(bool param);
+virtual void vfunc(bool param, int p);
+void func(bool param);
+  };
+  class B : public A {
+  virtual void ttt(bool param);
+  void vfunc(bool param, int p) override;
+  };
+  class C : public B {
+   public:
+void vfunc(bool param) override;
+^
+  };
+  )cpp");
+  const auto Results = completions(Text);
+  EXPECT_THAT(Results.Completions,
+  AllOf(Contains(AllOf(Named("vfunc"), IsOverride(),
+   Labeled("vfunc(bool param, int p)"))),
+Contains(AllOf(Named("ttt"), IsOverride(),
+   Labeled("ttt(bool param)"))),
+Not(Contains(AllOf(Named("vfunc"), IsOverride(),
+   Labeled("vfunc(bool param)"));
+}
+
+TEST(CompletionTest, RenderOverride) {
+  CodeCompletion C;
+  C.Name = "x";
+  C.Signature = "(bool) const";
+  C.SnippetSuffix = "(${0:bool})";
+  C.ReturnType = "int";
+  C.Documentation = "This is x().";
+  C.Kind = CompletionItemKind::Method;
+  C.Score.Total = 1.0;
+  C.Origin = SymbolOrigin::AST;
+  C.IsOverride = true;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeIndicator.NoInsert = "";
+  auto R = C.render(Opts);
+  EXPECT_EQ(R.label, "int x(bool) const override");
+  EXPECT_EQ(R.insertText, "int x(bool) const override");
+  EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  EXPECT_EQ(R.filterText, "x");
+  EXPECT_EQ(R.detail, "int");
+  EXPECT_EQ(R.documentation, "This is x().");
+  EXPECT_THAT(R.additionalTextEdits, IsEmpty());
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -127,6 +127,9 @@
   /// Holds the range of the token we are going to replace with this completion.
   Range CompletionTokenRange;
 
+  /// Whether this completion is for overriding a virtual method.
+  bool IsOverride = false;
+
   // Scores are used to rank completion items.
   struct Scores {
 // The score that items are ranked by.
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -188,14 +188,67 @@
   return HeaderFile{std::move(*Resolved), /*Verbatim=*/false};
 }
 
+// First traverses all method definitions inside current class/struct/union
+// definition. Than traverses base classes to find virtual methods that haven't
+// been overriden within current context.
+// FIXME(kadircet): Currently we cannot see declarations below completion point.
+// It is because Sema gets run only upto completion point. Need to find a
+// solution to run it for the whole class/struct/union definition.
+static std::vector
+getVirtualNonOverridenMethods(const DeclContext *DC, Sema *S) {
+  const auto *CR = llvm::dyn_cast(DC);
+  // If not inside a class/struct/union return empty.
+  if (!CR)
+return {};
+  // First store overrides within current class.
+  // These are stored by name to make querying fast in the later step.
+  llvm::StringMap> Overrides;
+  for (auto *Method : CR->methods()) {
+if (!Method->isVirtual())
+  continue;
+const std::string Name = Method->getNameAsString();
+Overrides[Name].push_back(Method);
+  }
+
+  std::vector Results;
+  for (const auto  : CR->bases()) {
+const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
+if (!BR)
+  continue;
+for (auto *Method : BR->methods()) {
+  if (!Method->isVirtual())
+continue;
+  const std::string Name = Method->getNameAsString();
+  const auto it = Overrides.find(Name);
+  bool IsOverriden = false;
+  if (it != Overrides.end())
+for (auto *MD : it->second) {
+  // If the method in current body is not an overload of 

[PATCH] D50898: [clangd] Suggest code-completions for overriding base class virtual methods.

2018-08-21 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet marked an inline comment as done.
kadircet added inline comments.



Comment at: clangd/CodeComplete.cpp:1233
+// struct/class/union definition.
+const auto Overrides = getVirtualNonOverridenMethods(
+Recorder->CCSema->CurContext, Recorder->CCSema);

hokein wrote:
> It seems that we treat it as a special case, the code path here runs out of 
> the `ranking` path.
Put override suggestions to ranking system.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50898



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


[PATCH] D51039: [clangd] Add unittests for D51038

2018-08-21 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added reviewers: ilya-biryukov, ioeric, hokein.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay.

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51039

Files:
  unittests/clangd/CodeCompleteTests.cpp


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1590,6 +1590,56 @@
   ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
 }
 
+TEST(SignatureHelpTest, InsideArgument) {
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1+^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^0); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int bar(int x, int y);
+  int main() { bar(foo(2, 3^)); }
+)cpp");
+EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo(int x, int y) -> 
void",
+{"int x", "int y"})));
+EXPECT_EQ(1, Results.activeParameter);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1590,6 +1590,56 @@
   ElementsAre(Sig("foo(T, U) -> void", {"T", "U"})));
 }
 
+TEST(SignatureHelpTest, InsideArgument) {
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1+^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^0); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int bar(int x, int y);
+  int main() { bar(foo(2, 3^)); }
+)cpp");
+EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo(int x, int y) -> void",
+{"int x", "int y"})));
+EXPECT_EQ(1, Results.activeParameter);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50898: [clangd] Suggest code-completions for overriding base class virtual methods.

2018-08-21 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added a comment.

After today's offline discussion I suppose we are not going to implement it 
within Sema. And also I think getVirtualNonOverridenMethods is a pretty generic 
function that has no ties to clangd, so it can be easily moved into Sema. 
Should we still move it into a separate file or leave it there?


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50898



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


[PATCH] D51163: [clangd] Check for include overlapping looks for only the line now.

2018-08-23 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added reviewers: ilya-biryukov, hokein, ioeric.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay.

Currently we match an include only if we are inside filename, with this patch we
will match whenever we are on the starting line of the include.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51163

Files:
  clangd/XRefs.cpp
  unittests/clangd/XRefsTests.cpp


Index: unittests/clangd/XRefsTests.cpp
===
--- unittests/clangd/XRefsTests.cpp
+++ unittests/clangd/XRefsTests.cpp
@@ -1014,11 +1014,13 @@
 
   Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("5"));
   ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
-  EXPECT_THAT(*Locations, IsEmpty());
+  EXPECT_THAT(*Locations,
+  ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
 
   Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("7"));
   ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
-  EXPECT_THAT(*Locations, IsEmpty());
+  EXPECT_THAT(*Locations,
+  ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
 }
 
 TEST(GoToDefinition, WithPreamble) {
Index: clangd/XRefs.cpp
===
--- clangd/XRefs.cpp
+++ clangd/XRefs.cpp
@@ -211,7 +211,7 @@
   std::vector Result;
   // Handle goto definition for #include.
   for (auto  : AST.getIncludeStructure().MainFileIncludes) {
-if (!Inc.Resolved.empty() && Inc.R.contains(Pos))
+if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.line)
   Result.push_back(Location{URIForFile{Inc.Resolved}, {}});
   }
   if (!Result.empty())


Index: unittests/clangd/XRefsTests.cpp
===
--- unittests/clangd/XRefsTests.cpp
+++ unittests/clangd/XRefsTests.cpp
@@ -1014,11 +1014,13 @@
 
   Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("5"));
   ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
-  EXPECT_THAT(*Locations, IsEmpty());
+  EXPECT_THAT(*Locations,
+  ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
 
   Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("7"));
   ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
-  EXPECT_THAT(*Locations, IsEmpty());
+  EXPECT_THAT(*Locations,
+  ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
 }
 
 TEST(GoToDefinition, WithPreamble) {
Index: clangd/XRefs.cpp
===
--- clangd/XRefs.cpp
+++ clangd/XRefs.cpp
@@ -211,7 +211,7 @@
   std::vector Result;
   // Handle goto definition for #include.
   for (auto  : AST.getIncludeStructure().MainFileIncludes) {
-if (!Inc.Resolved.empty() && Inc.R.contains(Pos))
+if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.line)
   Result.push_back(Location{URIForFile{Inc.Resolved}, {}});
   }
   if (!Result.empty())
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D51163: [clangd] Check for include overlapping looks for only the line now.

2018-08-23 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL340539: [clangd] Check for include overlapping looks for 
only the line now. (authored by kadircet, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D51163

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


Index: clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp
@@ -1014,11 +1014,13 @@
 
   Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("5"));
   ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
-  EXPECT_THAT(*Locations, IsEmpty());
+  EXPECT_THAT(*Locations,
+  ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
 
   Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("7"));
   ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
-  EXPECT_THAT(*Locations, IsEmpty());
+  EXPECT_THAT(*Locations,
+  ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
 }
 
 TEST(GoToDefinition, WithPreamble) {
Index: clang-tools-extra/trunk/clangd/XRefs.cpp
===
--- clang-tools-extra/trunk/clangd/XRefs.cpp
+++ clang-tools-extra/trunk/clangd/XRefs.cpp
@@ -211,7 +211,7 @@
   std::vector Result;
   // Handle goto definition for #include.
   for (auto  : AST.getIncludeStructure().MainFileIncludes) {
-if (!Inc.Resolved.empty() && Inc.R.contains(Pos))
+if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.line)
   Result.push_back(Location{URIForFile{Inc.Resolved}, {}});
   }
   if (!Result.empty())


Index: clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/XRefsTests.cpp
@@ -1014,11 +1014,13 @@
 
   Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("5"));
   ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
-  EXPECT_THAT(*Locations, IsEmpty());
+  EXPECT_THAT(*Locations,
+  ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
 
   Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("7"));
   ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error";
-  EXPECT_THAT(*Locations, IsEmpty());
+  EXPECT_THAT(*Locations,
+  ElementsAre(Location{FooHUri, HeaderAnnotations.range()}));
 }
 
 TEST(GoToDefinition, WithPreamble) {
Index: clang-tools-extra/trunk/clangd/XRefs.cpp
===
--- clang-tools-extra/trunk/clangd/XRefs.cpp
+++ clang-tools-extra/trunk/clangd/XRefs.cpp
@@ -211,7 +211,7 @@
   std::vector Result;
   // Handle goto definition for #include.
   for (auto  : AST.getIncludeStructure().MainFileIncludes) {
-if (!Inc.Resolved.empty() && Inc.R.contains(Pos))
+if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.line)
   Result.push_back(Location{URIForFile{Inc.Resolved}, {}});
   }
   if (!Result.empty())
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-24 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/Protocol.h:883
+/// converts it into a string.
+bool parseNumberOrString(const llvm::json::Value , std::string ,
+ const std::string );

ilya-biryukov wrote:
> Maybe simplify the signature to: `Optional parseNumberOrString(const 
> llvm::json::Value&);`
> And call as `parseNumberOrString(obj["id"])` instead of 
> `parseNumberOrString(obj, "id")`?
> 
> Also, maybe call it `normalizeRequestId`? 
LSP has a few more places that can have paremeters of type number | string so I 
believe this one could be used with them as well. Therefore I think it is 
better to keep the name that way. The normalizeRequestID is a sepcial case and 
handled within ClangdLSPServer.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502



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


[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-24 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 162354.
kadircet marked 2 inline comments as done.
kadircet added a comment.

- Change helper for normalizing Number | String.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,74 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "Threading.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  TaskHandle TH = Task::createHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  EXPECT_FALSE(isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+TaskHandle TH = Task::createHandle();
+ContextWithCancellation.emplace(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskContextDiesHandleLives) {
+  TaskHandle TH = Task::createHandle();
+  {
+WithContext ContextWithCancellation(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  // Still should be able to cancel without any problems.
+  TH->cancel();
+}
+
+TEST(CancellationTest, CancellationToken) {
+  TaskHandle TH = Task::createHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  const auto  = getCurrentTask();
+  EXPECT_FALSE(CT.isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(CT.isCancelled());
+}
+
+TEST(CancellationTest, AsynCancellationTest) {
+  std::atomic HasCancelled(false);
+  Notification Cancelled;
+  auto TaskToBeCancelled = [&](ConstTaskHandle CT) {
+WithContext ContextGuard(setCurrentTask(std::move(CT)));
+Cancelled.wait();
+HasCancelled = isCancelled();
+  };
+  TaskHandle TH = Task::createHandle();
+  std::thread AsyncTask(TaskToBeCancelled, TH);
+  TH->cancel();
+  Cancelled.notify();
+  AsyncTask.join();
+
+  EXPECT_TRUE(HasCancelled);
+}
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -867,6 +867,20 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  /// The request id to cancel.
+  /// This can be either a number or string, if it is a number simply print it
+  /// out and always use a string.
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
+/// Param can be either of type string or number. Returns the result as a
+/// string.
+llvm::Optional parseNumberOrString(const llvm::json::Value *Param);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Protocol.cpp
===
--- clangd/Protocol.cpp

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-24 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 162342.
kadircet marked 3 inline comments as done.
kadircet added a comment.

- Change a few comments.
- Add some assertions.
- Fix a data race.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,74 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "Threading.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  TaskHandle TH = Task::createHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  EXPECT_FALSE(isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+TaskHandle TH = Task::createHandle();
+ContextWithCancellation.emplace(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskContextDiesHandleLives) {
+  TaskHandle TH = Task::createHandle();
+  {
+WithContext ContextWithCancellation(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  // Still should be able to cancel without any problems.
+  TH->cancel();
+}
+
+TEST(CancellationTest, CancellationToken) {
+  TaskHandle TH = Task::createHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  const auto  = getCurrentTask();
+  EXPECT_FALSE(CT.isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(CT.isCancelled());
+}
+
+TEST(CancellationTest, AsynCancellationTest) {
+  std::atomic HasCancelled(false);
+  Notification Cancelled;
+  auto TaskToBeCancelled = [&](ConstTaskHandle CT) {
+WithContext ContextGuard(setCurrentTask(std::move(CT)));
+Cancelled.wait();
+HasCancelled = isCancelled();
+  };
+  TaskHandle TH = Task::createHandle();
+  std::thread AsyncTask(TaskToBeCancelled, TH);
+  TH->cancel();
+  Cancelled.notify();
+  AsyncTask.join();
+
+  EXPECT_TRUE(HasCancelled);
+}
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -867,6 +867,22 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  /// The request id to cancel.
+  /// This can be either a number or string, if it is a number simply print it
+  /// out and always use a string.
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
+/// Parses the Field in Params into Parsed. Params[Field] can be either of type
+/// string or number. Returns true if parsing was succesful. In case of a number
+/// converts it into a string.
+bool parseNumberOrString(const llvm::json::Value , std::string ,
+ const std::string );
+

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-24 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet marked 2 inline comments as done.
kadircet added inline comments.



Comment at: clangd/ClangdLSPServer.cpp:351
+  [this](llvm::Expected List) {
+auto _ = llvm::make_scope_exit([this]() { CleanupTaskHandle(); });
+

ilya-biryukov wrote:
> CleanupTaskHandle() can run in a separate thread, so can potentially run 
> before the `StoreTaskHandle` call.
> To avoid memory leaks in that case, let's preallocate the entry **before** 
> calling `codeComplete`
Thanks!


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502



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


[PATCH] D51214: [clangd] Add options to enable/disable fixits and function argument snippets.

2018-08-24 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added reviewers: hokein, ioeric, ilya-biryukov.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay.

Currently LSP clients cannot directly change IncludeFixIts or
EnableFunctionArgSnippets parameters. This patch is to provide them with a way
to enable/disable that functionality.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51214

Files:
  clangd/tool/ClangdMain.cpp


Index: clangd/tool/ClangdMain.cpp
===
--- clangd/tool/ClangdMain.cpp
+++ clangd/tool/ClangdMain.cpp
@@ -194,6 +194,19 @@
 "'compile_commands.json' files")),
 llvm::cl::init(FilesystemCompileArgs), llvm::cl::Hidden);
 
+static llvm::cl::opt IncludeFixIts(
+"include-fixits",
+llvm::cl::desc(
+"Enables suggestion of completion items that needs additional changes. 
"
+"Like changing an arrow(->) member access to dot(.) member access."),
+llvm::cl::init(clangd::CodeCompleteOptions().IncludeFixIts));
+
+static llvm::cl::opt EnableFunctionArgSnippets(
+"enable-function-arg-snippets",
+llvm::cl::desc("Gives snippets for function arguments, when disabled only "
+   "gives parantheses for the call."),
+llvm::cl::init(clangd::CodeCompleteOptions().EnableFunctionArgSnippets));
+
 int main(int argc, char *argv[]) {
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
   llvm::cl::SetVersionPrinter([](llvm::raw_ostream ) {
@@ -309,6 +322,8 @@
 CCOpts.IncludeIndicator.NoInsert.clear();
   }
   CCOpts.SpeculativeIndexRequest = Opts.StaticIndex;
+  CCOpts.IncludeFixIts = IncludeFixIts;
+  CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
 
   // Initialize and run ClangdLSPServer.
   ClangdLSPServer LSPServer(


Index: clangd/tool/ClangdMain.cpp
===
--- clangd/tool/ClangdMain.cpp
+++ clangd/tool/ClangdMain.cpp
@@ -194,6 +194,19 @@
 "'compile_commands.json' files")),
 llvm::cl::init(FilesystemCompileArgs), llvm::cl::Hidden);
 
+static llvm::cl::opt IncludeFixIts(
+"include-fixits",
+llvm::cl::desc(
+"Enables suggestion of completion items that needs additional changes. "
+"Like changing an arrow(->) member access to dot(.) member access."),
+llvm::cl::init(clangd::CodeCompleteOptions().IncludeFixIts));
+
+static llvm::cl::opt EnableFunctionArgSnippets(
+"enable-function-arg-snippets",
+llvm::cl::desc("Gives snippets for function arguments, when disabled only "
+   "gives parantheses for the call."),
+llvm::cl::init(clangd::CodeCompleteOptions().EnableFunctionArgSnippets));
+
 int main(int argc, char *argv[]) {
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
   llvm::cl::SetVersionPrinter([](llvm::raw_ostream ) {
@@ -309,6 +322,8 @@
 CCOpts.IncludeIndicator.NoInsert.clear();
   }
   CCOpts.SpeculativeIndexRequest = Opts.StaticIndex;
+  CCOpts.IncludeFixIts = IncludeFixIts;
+  CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
 
   // Initialize and run ClangdLSPServer.
   ClangdLSPServer LSPServer(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-24 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL340607: [clangd] Initial cancellation mechanism for LSP 
requests. (authored by kadircet, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D50502?vs=162365=162366#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D50502

Files:
  clang-tools-extra/trunk/clangd/CMakeLists.txt
  clang-tools-extra/trunk/clangd/Cancellation.cpp
  clang-tools-extra/trunk/clangd/Cancellation.h
  clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
  clang-tools-extra/trunk/clangd/ClangdLSPServer.h
  clang-tools-extra/trunk/clangd/ClangdServer.cpp
  clang-tools-extra/trunk/clangd/ClangdServer.h
  clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
  clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
  clang-tools-extra/trunk/clangd/Protocol.cpp
  clang-tools-extra/trunk/clangd/Protocol.h
  clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp
  clang-tools-extra/trunk/clangd/ProtocolHandlers.h
  clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt
  clang-tools-extra/trunk/unittests/clangd/CancellationTests.cpp

Index: clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt
===
--- clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt
+++ clang-tools-extra/trunk/unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clang-tools-extra/trunk/unittests/clangd/CancellationTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/CancellationTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,74 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "Threading.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  TaskHandle TH = Task::createHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  EXPECT_FALSE(isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+TaskHandle TH = Task::createHandle();
+ContextWithCancellation.emplace(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskContextDiesHandleLives) {
+  TaskHandle TH = Task::createHandle();
+  {
+WithContext ContextWithCancellation(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  // Still should be able to cancel without any problems.
+  TH->cancel();
+}
+
+TEST(CancellationTest, CancellationToken) {
+  TaskHandle TH = Task::createHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  const auto  = getCurrentTask();
+  EXPECT_FALSE(CT.isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(CT.isCancelled());
+}
+
+TEST(CancellationTest, AsynCancellationTest) {
+  std::atomic HasCancelled(false);
+  Notification Cancelled;
+  auto TaskToBeCancelled = [&](ConstTaskHandle CT) {
+WithContext ContextGuard(setCurrentTask(std::move(CT)));
+Cancelled.wait();
+HasCancelled = isCancelled();
+  };
+  TaskHandle TH = Task::createHandle();
+  std::thread AsyncTask(TaskToBeCancelled, TH);
+  TH->cancel();
+  Cancelled.notify();
+  AsyncTask.join();
+
+  EXPECT_TRUE(HasCancelled);
+}
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: clang-tools-extra/trunk/clangd/Protocol.cpp
===
--- clang-tools-extra/trunk/clangd/Protocol.cpp
+++ clang-tools-extra/trunk/clangd/Protocol.cpp
@@ -616,5 +616,38 @@
  O.map("compilationDatabaseChanges", CCPC.compilationDatabaseChanges);
 }
 
+json::Value toJSON(const CancelParams ) {
+  return json::Object{{"id", CP.ID}};
+}
+
+llvm::raw_ostream <<(llvm::raw_ostream , const CancelParams ) {
+  O << toJSON(CP);
+  return O;
+}
+
+llvm::Optional parseNumberOrString(const json::Value *Params) {
+  if (!Params)
+return llvm::None;
+  // ID is either a number or a string, check for both.
+  if(const auto AsString = Params->getAsString())
+return AsString->str();
+
+  if(const auto AsNumber = Params->getAsInteger())
+return itostr(AsNumber.getValue());
+
+  return llvm::None;
+}
+
+bool fromJSON(const json::Value , CancelParams ) {
+  const auto ParamsAsObject = Params.getAsObject();
+  if (!ParamsAsObject)
+return false;
+  if (auto Parsed = parseNumberOrString(ParamsAsObject->get("id"))) {
+CP.ID = std::move(*Parsed);
+return true;
+  }
+  return false;
+}
+
 } // 

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-24 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 162365.
kadircet marked 2 inline comments as done.
kadircet added a comment.

- Resolve comments.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,74 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "Threading.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  TaskHandle TH = Task::createHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  EXPECT_FALSE(isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+TaskHandle TH = Task::createHandle();
+ContextWithCancellation.emplace(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskContextDiesHandleLives) {
+  TaskHandle TH = Task::createHandle();
+  {
+WithContext ContextWithCancellation(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  // Still should be able to cancel without any problems.
+  TH->cancel();
+}
+
+TEST(CancellationTest, CancellationToken) {
+  TaskHandle TH = Task::createHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  const auto  = getCurrentTask();
+  EXPECT_FALSE(CT.isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(CT.isCancelled());
+}
+
+TEST(CancellationTest, AsynCancellationTest) {
+  std::atomic HasCancelled(false);
+  Notification Cancelled;
+  auto TaskToBeCancelled = [&](ConstTaskHandle CT) {
+WithContext ContextGuard(setCurrentTask(std::move(CT)));
+Cancelled.wait();
+HasCancelled = isCancelled();
+  };
+  TaskHandle TH = Task::createHandle();
+  std::thread AsyncTask(TaskToBeCancelled, TH);
+  TH->cancel();
+  Cancelled.notify();
+  AsyncTask.join();
+
+  EXPECT_TRUE(HasCancelled);
+}
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -867,6 +867,20 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  /// The request id to cancel.
+  /// This can be either a number or string, if it is a number simply print it
+  /// out and always use a string.
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
+/// Param can be either of type string or number. Returns the result as a
+/// string.
+llvm::Optional parseNumberOrString(const llvm::json::Value *Param);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Protocol.cpp
===
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ 

[PATCH] D51311: (WIP) Type hierarchy

2018-08-28 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/ProtocolHandlers.cpp:70
   Register("textDocument/hover", ::onHover);
+  Register("textDocument/typeHierarchy", ::onTypeHierarchy);
   Register("textDocument/documentSymbol", 
::onDocumentSymbol);

LSP doesn't have such an entry, maybe we should use [[ 
https://microsoft.github.io/language-server-protocol/specification#workspace_executeCommand
 | workspace/executeCommand ]]. WDYT @ilya-biryukov 



Comment at: clangd/XRefs.cpp:669
+  const CXXMethodDecl *Candidate) {
+  // FIXME: How do I determine if Method overrides Candidate?
+

ilya-biryukov wrote:
> simark wrote:
> > kadircet wrote:
> > > https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaDecl.cpp
> > > 
> > > you can check this sample, which simply traverses all base classes and 
> > > gets methods with the same name, then checks whether one is overload of 
> > > the other. If it they are not overloads then one in the base classes gets 
> > > overriden by the other.
> > > 
> > > 
> > > Another approach could be to search for one method in others 
> > > overriden_methods.
> > > 
> > > But they are both inefficient, I would suggest calling these functions 
> > > only when one of them is defined in the base class of other then you can 
> > > just check for name equality and not being an overload.
> > > https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaDecl.cpp
> > 
> > Did you mean to link to a particular line?
> > 
> > > you can check this sample, which simply traverses all base classes and 
> > > gets methods with the same name, then checks whether one is overload of 
> > > the other. If it they are not overloads then one in the base classes gets 
> > > overriden by the other.
> > 
> > > Another approach could be to search for one method in others 
> > > overriden_methods.
> > 
> > I have tried using `overriden_methods`, but it only contains methods marked 
> > virtual.  For this feature, I would like to consider non-virtual methods 
> > too.
> > 
> > > But they are both inefficient, I would suggest calling these functions 
> > > only when one of them is defined in the base class of other then you can 
> > > just check for name equality and not being an overload.
> > 
> > I am not sure I understand, but maybe it will be clearer when I will see 
> > the sample.
> See the code that actually computes a list for `override_methods()`: 
> Sema::AddOverriddenMethods.
> Did you mean to link to a particular line?


Yeah sorry, I was trying to link the function ilya mentioned.
https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaDecl.cpp#L7615

Since you also mentioned checking non-virtual method as well you might wanna 
look at 
https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaDecl.cpp#L7555 as 
well.

Also I got the chance to look the rest of the patch, as I mentioned above you 
are already checking two methods iff one lies in the others base classes. So 
you can simply check for name equality and not being an overload case.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51311



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


[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-20 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161428.
kadircet marked 2 inline comments as done.
kadircet added a comment.

- Check cancellation earlier && Fix normalization difference between string and 
integer request ids.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,79 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "Threading.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  TaskHandle TH = TaskHandle::create();
+  WithContext ContextWithCancellation(
+  setCurrentCancellationToken(TH.createCancellationToken()));
+  EXPECT_FALSE(isCancelled());
+  TH.cancel();
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+auto CancellableTaskHandle = TaskHandle::create();
+ContextWithCancellation.emplace(setCurrentCancellationToken(
+CancellableTaskHandle.createCancellationToken()));
+EXPECT_FALSE(isCancelled());
+CancellableTaskHandle.cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskHandleContextDiesHandleLives) {
+  auto CancellableTaskHandle = TaskHandle::create();
+  {
+WithContext ContextWithCancellation(setCurrentCancellationToken(
+CancellableTaskHandle.createCancellationToken()));
+EXPECT_FALSE(isCancelled());
+CancellableTaskHandle.cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  // Still should be able to cancel without any problems.
+  CancellableTaskHandle.cancel();
+}
+
+TEST(CancellationTest, CancellationToken) {
+  auto CancellableTaskHandle = TaskHandle::create();
+  WithContext ContextWithCancellation(setCurrentCancellationToken(
+  CancellableTaskHandle.createCancellationToken()));
+  const auto  = getCurrentCancellationToken();
+  EXPECT_FALSE(CT);
+  CancellableTaskHandle.cancel();
+  EXPECT_TRUE(CT);
+}
+
+TEST(CancellationTest, AsynCancellationTest) {
+  std::atomic HasCancelled(false);
+  Notification Cancelled;
+  auto TaskToBeCancelled = [&](CancellationToken CT) {
+WithContext ContextGuard(setCurrentCancellationToken(std::move(CT)));
+Cancelled.wait();
+HasCancelled = isCancelled();
+  };
+  TaskHandle TH = TaskHandle::create();
+  std::thread AsyncTask(TaskToBeCancelled, TH.createCancellationToken());
+  TH.cancel();
+  Cancelled.notify();
+  AsyncTask.join();
+
+  EXPECT_TRUE(HasCancelled);
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -867,6 +867,16 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  /// The request id to cancel.
+  /// This can be either a number or string, if it is a number simply print it
+  /// out and always use a string.
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-20 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/ClangdLSPServer.cpp:75
+std::string NormalizeRequestID(const json::Value ) {
+  CancelParams CP;
+  fromJSON(json::Object{{"id", ID}}, CP);

ioeric wrote:
> Use `ID.getAsString()`?
Unfortunately id can be both a string or a number according to LSP specs 
therefore we normalize both cases into a string.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502



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


[PATCH] D51311: (WIP) Type hierarchy

2018-08-27 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/Protocol.h:889
+  // Does this node implement the method targeted by the request?
+  bool DeclaresMethod;
+

I think comment and the name is in contradiction here, do you mean 
DefinesMethod?



Comment at: clangd/XRefs.cpp:669
+  const CXXMethodDecl *Candidate) {
+  // FIXME: How do I determine if Method overrides Candidate?
+

https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaDecl.cpp

you can check this sample, which simply traverses all base classes and gets 
methods with the same name, then checks whether one is overload of the other. 
If it they are not overloads then one in the base classes gets overriden by the 
other.


Another approach could be to search for one method in others overriden_methods.

But they are both inefficient, I would suggest calling these functions only 
when one of them is defined in the base class of other then you can just check 
for name equality and not being an overload.



Comment at: clangd/XRefs.cpp:693
+
+std::cerr << " >>> A parent is " << ParentDecl->getName().str()
+  << std::endl;

If you plan to keep it for later debugging info, consider using {d,v}log



Comment at: unittests/clangd/XRefsTests.cpp:1075
+$ParentDef^struct Parent
+{
+  int a;

NIT: Maybe format test code as well.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51311



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


[PATCH] D51102: [clangd] Move function argument snippet disable mechanism from LSP rendering to internal clangd reprensentation.

2018-08-22 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added reviewers: ilya-biryukov, ioeric, hokein.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay.

We were handling the EnableFunctionArgSnippets only when we are producing LSP
response. Move that code into CompletionItem generation so that internal clients
can benefit from that as well.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51102

Files:
  clangd/CodeComplete.cpp
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1140,7 +1140,7 @@
   // For now we just return one of the doc strings arbitrarily.
   EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"),
  HasSubstr("Overload with bool")));
-  EXPECT_EQ(A.SnippetSuffix, "(${0})");
+  EXPECT_EQ(A.SnippetSuffix, "($0)");
 }
 
 TEST(CompletionTest, DocumentationFromChangedFileCrash) {
@@ -1648,55 +1648,35 @@
 SigDoc("Doc from sema";
 }
 
-TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) {
+TEST(CompletionTest, CompletionFunctionArgsDisabled) {
   CodeCompleteOptions Opts;
-  Opts.EnableFunctionArgSnippets = true;
-  {
-CodeCompletion C;
-C.RequiredQualifier = "Foo::";
-C.Name = "x";
-C.SnippetSuffix = "()";
-
-auto R = C.render(Opts);
-EXPECT_EQ(R.textEdit->newText, "Foo::x");
-EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
-  }
-
   Opts.EnableSnippets = true;
   Opts.EnableFunctionArgSnippets = false;
+  const std::string Header =
+  R"cpp(
+  void xfoo();
+  void xfoo(int x, int y);
+  void xbar();
+  void f() {
+)cpp";
   {
-CodeCompletion C;
-C.RequiredQualifier = "Foo::";
-C.Name = "x";
-C.SnippetSuffix = "";
-
-auto R = C.render(Opts);
-EXPECT_EQ(R.textEdit->newText, "Foo::x");
-EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+auto Results = completions(Header + "\nxfo^", {}, Opts);
+EXPECT_THAT(
+Results.Completions,
+UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")),
+ AllOf(Named("xfoo"), SnippetSuffix("($0)";
   }
-
   {
-CodeCompletion C;
-C.RequiredQualifier = "Foo::";
-C.Name = "x";
-C.SnippetSuffix = "()";
-C.Kind = CompletionItemKind::Method;
-
-auto R = C.render(Opts);
-EXPECT_EQ(R.textEdit->newText, "Foo::x()");
-EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+auto Results = completions(Header + "\nxba^", {}, Opts);
+EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
+ Named("xbar"), SnippetSuffix("()";
   }
-
   {
-CodeCompletion C;
-C.RequiredQualifier = "Foo::";
-C.Name = "x";
-C.SnippetSuffix = "(${0:bool})";
-C.Kind = CompletionItemKind::Function;
-
-auto R = C.render(Opts);
-EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
-EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+Opts.BundleOverloads = true;
+auto Results = completions(Header + "\nxfo^", {}, Opts);
+EXPECT_THAT(
+Results.Completions,
+UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)";
   }
 }
 
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -269,7 +269,8 @@
 CodeCompletionString *SemaCCS,
 const IncludeInserter , StringRef FileName,
 const CodeCompleteOptions )
-  : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments) {
+  : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments),
+EnableFunctionArgSnippets(Opts.EnableFunctionArgSnippets) {
 add(C, SemaCCS);
 if (C.SemaResult) {
   Completion.Origin |= SymbolOrigin::AST;
@@ -385,10 +386,17 @@
   }
 
   std::string summarizeSnippet() const {
-if (auto *Snippet = onlyValue<::SnippetSuffix>())
-  return *Snippet;
-// All bundles are function calls.
-return "(${0})";
+auto *Snippet = onlyValue<::SnippetSuffix>();
+if (!Snippet)
+  // All bundles are function calls.
+  return "($0)";
+if (!Snippet->empty() && !EnableFunctionArgSnippets &&
+((Completion.Kind == CompletionItemKind::Function) ||
+ (Completion.Kind == CompletionItemKind::Method)) &&
+(Snippet->front() == '(') && (Snippet->back() == ')'))
+  // Check whether function has any parameters or not.
+  return Snippet->size() > 2 ? "($0)" : "()";
+return *Snippet;
   }
 
   std::string summarizeSignature() const {
@@ -402,6 +410,7 @@
   CodeCompletion Completion;
   SmallVector Bundled;
   bool ExtractDocumentation;
+  bool EnableFunctionArgSnippets;
 };
 
 // Determine 

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-22 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161908.
kadircet marked 6 inline comments as done.
kadircet added a comment.

- Resolve discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,74 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "Threading.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  TaskHandle TH = Task::createHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  EXPECT_FALSE(isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+TaskHandle TH = Task::createHandle();
+ContextWithCancellation.emplace(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskContextDiesHandleLives) {
+  TaskHandle TH = Task::createHandle();
+  {
+WithContext ContextWithCancellation(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  // Still should be able to cancel without any problems.
+  TH->cancel();
+}
+
+TEST(CancellationTest, CancellationToken) {
+  TaskHandle TH = Task::createHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  const auto  = getCurrentTask();
+  EXPECT_FALSE(CT.isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(CT.isCancelled());
+}
+
+TEST(CancellationTest, AsynCancellationTest) {
+  std::atomic HasCancelled(false);
+  Notification Cancelled;
+  auto TaskToBeCancelled = [&](ConstTaskHandle CT) {
+WithContext ContextGuard(setCurrentTask(std::move(CT)));
+Cancelled.wait();
+HasCancelled = isCancelled();
+  };
+  TaskHandle TH = Task::createHandle();
+  std::thread AsyncTask(TaskToBeCancelled, TH);
+  TH->cancel();
+  Cancelled.notify();
+  AsyncTask.join();
+
+  EXPECT_TRUE(HasCancelled);
+}
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -867,6 +867,22 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  /// The request id to cancel.
+  /// This can be either a number or string, if it is a number simply print it
+  /// out and always use a string.
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
+/// Parses the Field in Params into Parsed. Params[Field] can be either of type
+/// string or number. Returns true if parsing was succesful. In case of a number
+/// converts it into a string.
+bool parseNumberOrString(const llvm::json::Value , std::string ,
+ const std::string );
+
 } // namespace clangd
 } // namespace 

[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-08-22 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161966.
kadircet marked 2 inline comments as done.
kadircet added a comment.

- Resolve discussions.
- Add tests.
- Fix a bug noticed by lit tests.


Repository:
  rC Clang

https://reviews.llvm.org/D51038

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseExpr.cpp
  test/CodeCompletion/function-overloads-inside-param.cpp
  test/CodeCompletion/function-overloads.cpp


Index: test/CodeCompletion/function-overloads.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:7 %s -o - | 
FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: test/CodeCompletion/function-overloads-inside-param.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads-inside-param.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(1
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:8 %s -o - | 
FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1657,10 +1657,21 @@
 
   if (OpKind == tok::l_paren || !LHS.isInvalid()) {
 if (Tok.isNot(tok::r_paren)) {
-  if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
-Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
- })) {
+  auto Completer = [&] {
+Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
+CalledOverloadCompletion = true;
+  };
+  if (ParseExpressionList(ArgExprs, CommaLocs, Completer)) {
 (void)Actions.CorrectDelayedTyposInExpr(LHS);
+// If we got an error when parsing expression list, we don't call
+// the CodeCompleteCall handler inside the parser. So call it here
+// to make sure we get overload suggestions even when we are in the
+// middle of a parameter. There is a different handling mechanism 
in
+// ObjC for that type of completion, so don't call completion and
+// let the parser do it instead.
+if (!getLangOpts().ObjC1 && PP.isCodeCompletionReached() &&
+!CalledOverloadCompletion)
+  Completer();
 LHS = ExprError();
   } else if (LHS.isInvalid()) {
 for (auto  : ArgExprs)
Index: include/clang/Parse/Parser.h
===
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -214,6 +214,10 @@
   /// should not be set directly.
   bool InMessageExpression;
 
+  /// Gets set to true after calling CodeCompleteCall, it is for a hack to make
+  /// signature help working even when it is triggered inside a token.
+  bool CalledOverloadCompletion = false;
+
   /// The "depth" of the template parameters currently being parsed.
   unsigned TemplateParameterDepth;
 


Index: test/CodeCompletion/function-overloads.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:7 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: test/CodeCompletion/function-overloads-inside-param.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads-inside-param.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(1
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1657,10 +1657,21 @@
 
   if (OpKind == tok::l_paren || !LHS.isInvalid()) {
 if (Tok.isNot(tok::r_paren)) {
-  if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
-Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
- })) {
+  auto 

[PATCH] D50898: [clangd] Suggest code-completions for overriding base class virtual methods.

2018-08-22 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161963.
kadircet marked 6 inline comments as done.
kadircet added a comment.

- Resolve discussions.
- Fix a bug inside summarizeOverride.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50898

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -61,6 +61,7 @@
 MATCHER(InsertInclude, "") { return bool(arg.HeaderInsertion); }
 MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
 MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
+MATCHER(IsOverride, "") { return bool(arg.IsOverride); }
 
 // Shorthand for Contains(Named(Name)).
 Matcher &> Has(std::string Name) {
@@ -1700,6 +1701,58 @@
   }
 }
 
+TEST(CompletionTest, SuggestOverrides) {
+  constexpr const char *const Text(R"cpp(
+  class A {
+   public:
+virtual void vfunc(bool param);
+virtual void vfunc(bool param, int p);
+void func(bool param);
+  };
+  class B : public A {
+  virtual void ttt(bool param);
+  void vfunc(bool param, int p) override;
+  };
+  class C : public B {
+   public:
+void vfunc(bool param) override;
+^
+  };
+  )cpp");
+  const auto Results = completions(Text);
+  EXPECT_THAT(Results.Completions,
+  AllOf(Contains(AllOf(Named("vfunc"), IsOverride(),
+   Labeled("vfunc(bool param, int p)"))),
+Contains(AllOf(Named("ttt"), IsOverride(),
+   Labeled("ttt(bool param)"))),
+Not(Contains(AllOf(Named("vfunc"), IsOverride(),
+   Labeled("vfunc(bool param)"));
+}
+
+TEST(CompletionTest, RenderOverride) {
+  CodeCompletion C;
+  C.Name = "x";
+  C.Signature = "(bool) const";
+  C.SnippetSuffix = "(${0:bool})";
+  C.ReturnType = "int";
+  C.Documentation = "This is x().";
+  C.Kind = CompletionItemKind::Method;
+  C.Score.Total = 1.0;
+  C.Origin = SymbolOrigin::AST;
+  C.IsOverride = true;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeIndicator.NoInsert = "";
+  auto R = C.render(Opts);
+  EXPECT_EQ(R.label, "int x(bool) const override");
+  EXPECT_EQ(R.insertText, "int x(bool) const override");
+  EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  EXPECT_EQ(R.filterText, "x");
+  EXPECT_EQ(R.detail, "int");
+  EXPECT_EQ(R.documentation, "This is x().");
+  EXPECT_THAT(R.additionalTextEdits, IsEmpty());
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -131,6 +131,9 @@
   /// Holds the range of the token we are going to replace with this completion.
   Range CompletionTokenRange;
 
+  /// Whether this completion is for overriding a virtual method.
+  bool IsOverride = false;
+
   // Scores are used to rank completion items.
   struct Scores {
 // The score that items are ranked by.
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -188,14 +188,67 @@
   return HeaderFile{std::move(*Resolved), /*Verbatim=*/false};
 }
 
+// First traverses all method definitions inside current class/struct/union
+// definition. Than traverses base classes to find virtual methods that haven't
+// been overriden within current context.
+// FIXME(kadircet): Currently we cannot see declarations below completion point.
+// It is because Sema gets run only upto completion point. Need to find a
+// solution to run it for the whole class/struct/union definition.
+static std::vector
+getNonOverridenMethodCompletionResults(const DeclContext *DC, Sema *S) {
+  const auto *CR = llvm::dyn_cast(DC);
+  // If not inside a class/struct/union return empty.
+  if (!CR)
+return {};
+  // First store overrides within current class.
+  // These are stored by name to make querying fast in the later step.
+  llvm::StringMap> Overrides;
+  for (auto *Method : CR->methods()) {
+if (!Method->isVirtual())
+  continue;
+const std::string Name = Method->getNameAsString();
+Overrides[Name].push_back(Method);
+  }
+
+  std::vector Results;
+  for (const auto  : CR->bases()) {
+const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
+if (!BR)
+  continue;
+for (auto *Method : BR->methods()) {
+  if (!Method->isVirtual())
+continue;
+  const auto it = Overrides.find(Method->getName());
+  bool IsOverriden = false;
+  if (it != Overrides.end()) {
+for (auto *MD : it->second) {
+  // If the method in current body is not an overload of this virtual
+  // function, that it overrides this one.
+ 

[PATCH] D51102: [clangd] Move function argument snippet disable mechanism from LSP rendering to internal clangd reprensentation.

2018-08-23 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL340527: [clangd] Move function argument snippet disable 
mechanism from LSP rendering toā€¦ (authored by kadircet, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D51102

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

Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
@@ -1140,7 +1140,7 @@
   // For now we just return one of the doc strings arbitrarily.
   EXPECT_THAT(A.Documentation, AnyOf(HasSubstr("Overload with int"),
  HasSubstr("Overload with bool")));
-  EXPECT_EQ(A.SnippetSuffix, "(${0})");
+  EXPECT_EQ(A.SnippetSuffix, "($0)");
 }
 
 TEST(CompletionTest, DocumentationFromChangedFileCrash) {
@@ -1648,55 +1648,35 @@
 SigDoc("Doc from sema";
 }
 
-TEST(CompletionTest, RenderWithSnippetsForFunctionArgsDisabled) {
+TEST(CompletionTest, CompletionFunctionArgsDisabled) {
   CodeCompleteOptions Opts;
-  Opts.EnableFunctionArgSnippets = true;
-  {
-CodeCompletion C;
-C.RequiredQualifier = "Foo::";
-C.Name = "x";
-C.SnippetSuffix = "()";
-
-auto R = C.render(Opts);
-EXPECT_EQ(R.textEdit->newText, "Foo::x");
-EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
-  }
-
   Opts.EnableSnippets = true;
   Opts.EnableFunctionArgSnippets = false;
+  const std::string Header =
+  R"cpp(
+  void xfoo();
+  void xfoo(int x, int y);
+  void xbar();
+  void f() {
+)cpp";
   {
-CodeCompletion C;
-C.RequiredQualifier = "Foo::";
-C.Name = "x";
-C.SnippetSuffix = "";
-
-auto R = C.render(Opts);
-EXPECT_EQ(R.textEdit->newText, "Foo::x");
-EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+auto Results = completions(Header + "\nxfo^", {}, Opts);
+EXPECT_THAT(
+Results.Completions,
+UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("()")),
+ AllOf(Named("xfoo"), SnippetSuffix("($0)";
   }
-
   {
-CodeCompletion C;
-C.RequiredQualifier = "Foo::";
-C.Name = "x";
-C.SnippetSuffix = "()";
-C.Kind = CompletionItemKind::Method;
-
-auto R = C.render(Opts);
-EXPECT_EQ(R.textEdit->newText, "Foo::x()");
-EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+auto Results = completions(Header + "\nxba^", {}, Opts);
+EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(
+ Named("xbar"), SnippetSuffix("()";
   }
-
   {
-CodeCompletion C;
-C.RequiredQualifier = "Foo::";
-C.Name = "x";
-C.SnippetSuffix = "(${0:bool})";
-C.Kind = CompletionItemKind::Function;
-
-auto R = C.render(Opts);
-EXPECT_EQ(R.textEdit->newText, "Foo::x(${0})");
-EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);
+Opts.BundleOverloads = true;
+auto Results = completions(Header + "\nxfo^", {}, Opts);
+EXPECT_THAT(
+Results.Completions,
+UnorderedElementsAre(AllOf(Named("xfoo"), SnippetSuffix("($0)";
   }
 }
 
Index: clang-tools-extra/trunk/clangd/CodeComplete.cpp
===
--- clang-tools-extra/trunk/clangd/CodeComplete.cpp
+++ clang-tools-extra/trunk/clangd/CodeComplete.cpp
@@ -269,7 +269,8 @@
 CodeCompletionString *SemaCCS,
 const IncludeInserter , StringRef FileName,
 const CodeCompleteOptions )
-  : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments) {
+  : ASTCtx(ASTCtx), ExtractDocumentation(Opts.IncludeComments),
+EnableFunctionArgSnippets(Opts.EnableFunctionArgSnippets) {
 add(C, SemaCCS);
 if (C.SemaResult) {
   Completion.Origin |= SymbolOrigin::AST;
@@ -385,10 +386,17 @@
   }
 
   std::string summarizeSnippet() const {
-if (auto *Snippet = onlyValue<::SnippetSuffix>())
-  return *Snippet;
-// All bundles are function calls.
-return "(${0})";
+auto *Snippet = onlyValue<::SnippetSuffix>();
+if (!Snippet)
+  // All bundles are function calls.
+  return "($0)";
+if (!Snippet->empty() && !EnableFunctionArgSnippets &&
+((Completion.Kind == CompletionItemKind::Function) ||
+ (Completion.Kind == CompletionItemKind::Method)) &&
+(Snippet->front() == '(') && (Snippet->back() == ')'))
+  // Check whether function has any parameters or not.
+  return Snippet->size() > 2 ? "($0)" : "()";
+return *Snippet;
   }
 
   std::string summarizeSignature() const {
@@ -402,6 +410,7 @@
   CodeCompletion Completion;
   SmallVector 

[PATCH] D50898: [clangd] Suggest code-completions for overriding base class virtual methods.

2018-08-23 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 162151.
kadircet added a comment.

- Resolve discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50898

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -61,6 +61,7 @@
 MATCHER(InsertInclude, "") { return bool(arg.HeaderInsertion); }
 MATCHER_P(SnippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }
 MATCHER_P(Origin, OriginSet, "") { return arg.Origin == OriginSet; }
+MATCHER(IsOverride, "") { return bool(arg.IsOverride); }
 
 // Shorthand for Contains(Named(Name)).
 Matcher &> Has(std::string Name) {
@@ -1700,6 +1701,58 @@
   }
 }
 
+TEST(CompletionTest, SuggestOverrides) {
+  constexpr const char *const Text(R"cpp(
+  class A {
+   public:
+virtual void vfunc(bool param);
+virtual void vfunc(bool param, int p);
+void func(bool param);
+  };
+  class B : public A {
+  virtual void ttt(bool param);
+  void vfunc(bool param, int p) override;
+  };
+  class C : public B {
+   public:
+void vfunc(bool param) override;
+^
+  };
+  )cpp");
+  const auto Results = completions(Text);
+  EXPECT_THAT(Results.Completions,
+  AllOf(Contains(AllOf(Named("vfunc"), IsOverride(),
+   Labeled("vfunc(bool param, int p)"))),
+Contains(AllOf(Named("ttt"), IsOverride(),
+   Labeled("ttt(bool param)"))),
+Not(Contains(AllOf(Named("vfunc"), IsOverride(),
+   Labeled("vfunc(bool param)"));
+}
+
+TEST(CompletionTest, RenderOverride) {
+  CodeCompletion C;
+  C.Name = "x";
+  C.Signature = "(bool) const";
+  C.SnippetSuffix = "(${0:bool})";
+  C.ReturnType = "int";
+  C.Documentation = "This is x().";
+  C.Kind = CompletionItemKind::Method;
+  C.Score.Total = 1.0;
+  C.Origin = SymbolOrigin::AST;
+  C.IsOverride = true;
+
+  CodeCompleteOptions Opts;
+  Opts.IncludeIndicator.NoInsert = "";
+  auto R = C.render(Opts);
+  EXPECT_EQ(R.label, "int x(bool) const override");
+  EXPECT_EQ(R.insertText, "int x(bool) const override");
+  EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
+  EXPECT_EQ(R.filterText, "x");
+  EXPECT_EQ(R.detail, "int");
+  EXPECT_EQ(R.documentation, "This is x().");
+  EXPECT_THAT(R.additionalTextEdits, IsEmpty());
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.h
===
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -131,6 +131,9 @@
   /// Holds the range of the token we are going to replace with this completion.
   Range CompletionTokenRange;
 
+  /// Whether this completion is for overriding a virtual method.
+  bool IsOverride = false;
+
   // Scores are used to rank completion items.
   struct Scores {
 // The score that items are ranked by.
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -188,14 +188,66 @@
   return HeaderFile{std::move(*Resolved), /*Verbatim=*/false};
 }
 
+// First traverses all method definitions inside current class/struct/union
+// definition. Than traverses base classes to find virtual methods that haven't
+// been overriden within current context.
+// FIXME(kadircet): Currently we cannot see declarations below completion point.
+// It is because Sema gets run only upto completion point. Need to find a
+// solution to run it for the whole class/struct/union definition.
+static std::vector
+getNonOverridenMethodCompletionResults(const DeclContext *DC, Sema *S) {
+  const auto *CR = llvm::dyn_cast(DC);
+  // If not inside a class/struct/union return empty.
+  if (!CR)
+return {};
+  // First store overrides within current class.
+  // These are stored by name to make querying fast in the later step.
+  llvm::StringMap> Overrides;
+  for (auto *Method : CR->methods()) {
+if (!Method->isVirtual())
+  continue;
+Overrides[Method->getName()].push_back(Method);
+  }
+
+  std::vector Results;
+  for (const auto  : CR->bases()) {
+const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
+if (!BR)
+  continue;
+for (auto *Method : BR->methods()) {
+  if (!Method->isVirtual())
+continue;
+  const auto it = Overrides.find(Method->getName());
+  bool IsOverriden = false;
+  if (it != Overrides.end()) {
+for (auto *MD : it->second) {
+  // If the method in current body is not an overload of this virtual
+  // function, that it overrides this one.
+  if (!S->IsOverload(MD, Method, false)) {
+IsOverriden = true;
+break;
+  }
+}
+ 

[PATCH] D50898: [clangd] Suggest code-completions for overriding base class virtual methods.

2018-08-23 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 162157.
kadircet added a comment.

- Resolve discussions.
- Move override generation logic from render to item generation so that 
internal clients can use it as well, also use a boolean for checking override 
status of a bundle to be more efficient.
- Change unittests accordingly, get rid of unused IsOverride field.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50898

Files:
  clangd/CodeComplete.cpp
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1680,6 +1680,31 @@
   }
 }
 
+TEST(CompletionTest, SuggestOverrides) {
+  constexpr const char *const Text(R"cpp(
+  class A {
+   public:
+virtual void vfunc(bool param);
+virtual void vfunc(bool param, int p);
+void func(bool param);
+  };
+  class B : public A {
+  virtual void ttt(bool param) const;
+  void vfunc(bool param, int p) override;
+  };
+  class C : public B {
+   public:
+void vfunc(bool param) override;
+^
+  };
+  )cpp");
+  const auto Results = completions(Text);
+  EXPECT_THAT(Results.Completions,
+  AllOf(Contains(Labeled("void vfunc(bool param, int p) override")),
+Contains(Labeled("void ttt(bool param) const override")),
+Not(Contains(Labeled("void vfunc(bool param) override");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -188,14 +188,66 @@
   return HeaderFile{std::move(*Resolved), /*Verbatim=*/false};
 }
 
+// First traverses all method definitions inside current class/struct/union
+// definition. Than traverses base classes to find virtual methods that haven't
+// been overriden within current context.
+// FIXME(kadircet): Currently we cannot see declarations below completion point.
+// It is because Sema gets run only upto completion point. Need to find a
+// solution to run it for the whole class/struct/union definition.
+static std::vector
+getNonOverridenMethodCompletionResults(const DeclContext *DC, Sema *S) {
+  const auto *CR = llvm::dyn_cast(DC);
+  // If not inside a class/struct/union return empty.
+  if (!CR)
+return {};
+  // First store overrides within current class.
+  // These are stored by name to make querying fast in the later step.
+  llvm::StringMap> Overrides;
+  for (auto *Method : CR->methods()) {
+if (!Method->isVirtual())
+  continue;
+Overrides[Method->getName()].push_back(Method);
+  }
+
+  std::vector Results;
+  for (const auto  : CR->bases()) {
+const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
+if (!BR)
+  continue;
+for (auto *Method : BR->methods()) {
+  if (!Method->isVirtual())
+continue;
+  const auto it = Overrides.find(Method->getName());
+  bool IsOverriden = false;
+  if (it != Overrides.end()) {
+for (auto *MD : it->second) {
+  // If the method in current body is not an overload of this virtual
+  // function, that it overrides this one.
+  if (!S->IsOverload(MD, Method, false)) {
+IsOverriden = true;
+break;
+  }
+}
+  }
+  if (!IsOverriden)
+Results.emplace_back(Method, 0);
+}
+  }
+
+  return Results;
+}
+
 /// A code completion result, in clang-native form.
 /// It may be promoted to a CompletionItem if it's among the top-ranked results.
 struct CompletionCandidate {
   llvm::StringRef Name; // Used for filtering and sorting.
   // We may have a result from Sema, from the index, or both.
   const CodeCompletionResult *SemaResult = nullptr;
   const Symbol *IndexResult = nullptr;
 
+  // States whether this item is an override suggestion.
+  bool IsOverride = false;
+
   // Returns a token identifying the overload set this is part of.
   // 0 indicates it's not part of any overload set.
   size_t overloadSet() const {
@@ -352,21 +404,30 @@
 Completion.Documentation = getDocComment(ASTCtx, *C.SemaResult,
  /*CommentsFromHeader=*/false);
 }
+if (C.IsOverride)
+  S.OverrideSuffix = true;
   }
 
   CodeCompletion build() {
 Completion.ReturnType = summarizeReturnType();
 Completion.Signature = summarizeSignature();
 Completion.SnippetSuffix = summarizeSnippet();
 Completion.BundleSize = Bundled.size();
+if (summarizeOverride()) {
+  Completion.Name = Completion.ReturnType + ' ' +
+std::move(Completion.Name) +
+std::move(Completion.Signature) + " override";
+  Completion.Signature.clear();
+}
 return std::move(Completion);
   }
 
 private:
   struct BundledEntry {
 std::string 

[PATCH] D50898: [clangd] Suggest code-completions for overriding base class virtual methods.

2018-08-23 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rCTE340530: [clangd] Suggest code-completions for overriding 
base class virtual methods. (authored by kadircet, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D50898?vs=162157=162158#toc

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50898

Files:
  clangd/CodeComplete.cpp
  unittests/clangd/CodeCompleteTests.cpp

Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1680,6 +1680,31 @@
   }
 }
 
+TEST(CompletionTest, SuggestOverrides) {
+  constexpr const char *const Text(R"cpp(
+  class A {
+   public:
+virtual void vfunc(bool param);
+virtual void vfunc(bool param, int p);
+void func(bool param);
+  };
+  class B : public A {
+  virtual void ttt(bool param) const;
+  void vfunc(bool param, int p) override;
+  };
+  class C : public B {
+   public:
+void vfunc(bool param) override;
+^
+  };
+  )cpp");
+  const auto Results = completions(Text);
+  EXPECT_THAT(Results.Completions,
+  AllOf(Contains(Labeled("void vfunc(bool param, int p) override")),
+Contains(Labeled("void ttt(bool param) const override")),
+Not(Contains(Labeled("void vfunc(bool param) override");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/CodeComplete.cpp
===
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -188,14 +188,66 @@
   return HeaderFile{std::move(*Resolved), /*Verbatim=*/false};
 }
 
+// First traverses all method definitions inside current class/struct/union
+// definition. Than traverses base classes to find virtual methods that haven't
+// been overriden within current context.
+// FIXME(kadircet): Currently we cannot see declarations below completion point.
+// It is because Sema gets run only upto completion point. Need to find a
+// solution to run it for the whole class/struct/union definition.
+static std::vector
+getNonOverridenMethodCompletionResults(const DeclContext *DC, Sema *S) {
+  const auto *CR = llvm::dyn_cast(DC);
+  // If not inside a class/struct/union return empty.
+  if (!CR)
+return {};
+  // First store overrides within current class.
+  // These are stored by name to make querying fast in the later step.
+  llvm::StringMap> Overrides;
+  for (auto *Method : CR->methods()) {
+if (!Method->isVirtual())
+  continue;
+Overrides[Method->getName()].push_back(Method);
+  }
+
+  std::vector Results;
+  for (const auto  : CR->bases()) {
+const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
+if (!BR)
+  continue;
+for (auto *Method : BR->methods()) {
+  if (!Method->isVirtual())
+continue;
+  const auto it = Overrides.find(Method->getName());
+  bool IsOverriden = false;
+  if (it != Overrides.end()) {
+for (auto *MD : it->second) {
+  // If the method in current body is not an overload of this virtual
+  // function, that it overrides this one.
+  if (!S->IsOverload(MD, Method, false)) {
+IsOverriden = true;
+break;
+  }
+}
+  }
+  if (!IsOverriden)
+Results.emplace_back(Method, 0);
+}
+  }
+
+  return Results;
+}
+
 /// A code completion result, in clang-native form.
 /// It may be promoted to a CompletionItem if it's among the top-ranked results.
 struct CompletionCandidate {
   llvm::StringRef Name; // Used for filtering and sorting.
   // We may have a result from Sema, from the index, or both.
   const CodeCompletionResult *SemaResult = nullptr;
   const Symbol *IndexResult = nullptr;
 
+  // States whether this item is an override suggestion.
+  bool IsOverride = false;
+
   // Returns a token identifying the overload set this is part of.
   // 0 indicates it's not part of any overload set.
   size_t overloadSet() const {
@@ -352,21 +404,30 @@
 Completion.Documentation = getDocComment(ASTCtx, *C.SemaResult,
  /*CommentsFromHeader=*/false);
 }
+if (C.IsOverride)
+  S.OverrideSuffix = true;
   }
 
   CodeCompletion build() {
 Completion.ReturnType = summarizeReturnType();
 Completion.Signature = summarizeSignature();
 Completion.SnippetSuffix = summarizeSnippet();
 Completion.BundleSize = Bundled.size();
+if (summarizeOverride()) {
+  Completion.Name = Completion.ReturnType + ' ' +
+std::move(Completion.Name) +
+std::move(Completion.Signature) + " override";
+  Completion.Signature.clear();
+}
 return std::move(Completion);
   }
 
 private:
   struct BundledEntry {
 std::string SnippetSuffix;
 std::string Signature;
 

[PATCH] D50502: [clangd] Initial cancellation mechanism for LSP requests.

2018-08-21 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 161716.
kadircet marked 4 inline comments as done.
kadircet added a comment.

- Get rid of CancellationToken && Resolve discussions.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D50502

Files:
  clangd/CMakeLists.txt
  clangd/Cancellation.cpp
  clangd/Cancellation.h
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/ClangdServer.cpp
  clangd/ClangdServer.h
  clangd/JSONRPCDispatcher.cpp
  clangd/JSONRPCDispatcher.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/ProtocolHandlers.cpp
  clangd/ProtocolHandlers.h
  unittests/clangd/CMakeLists.txt
  unittests/clangd/CancellationTests.cpp

Index: unittests/clangd/CancellationTests.cpp
===
--- /dev/null
+++ unittests/clangd/CancellationTests.cpp
@@ -0,0 +1,74 @@
+#include "Cancellation.h"
+#include "Context.h"
+#include "Threading.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+#include 
+#include 
+
+namespace clang {
+namespace clangd {
+namespace {
+
+TEST(CancellationTest, CancellationTest) {
+  TaskHandle TH = createTaskHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  EXPECT_FALSE(isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskTestHandleDiesContextLives) {
+  llvm::Optional ContextWithCancellation;
+  {
+TaskHandle TH = createTaskHandle();
+ContextWithCancellation.emplace(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  EXPECT_TRUE(isCancelled());
+}
+
+TEST(CancellationTest, TaskContextDiesHandleLives) {
+  TaskHandle TH = createTaskHandle();
+  {
+WithContext ContextWithCancellation(setCurrentTask(TH));
+EXPECT_FALSE(isCancelled());
+TH->cancel();
+EXPECT_TRUE(isCancelled());
+  }
+  // Still should be able to cancel without any problems.
+  TH->cancel();
+}
+
+TEST(CancellationTest, CancellationToken) {
+  TaskHandle TH = createTaskHandle();
+  WithContext ContextWithCancellation(setCurrentTask(TH));
+  const auto  = getCurrentTask();
+  EXPECT_FALSE(CT.isCancelled());
+  TH->cancel();
+  EXPECT_TRUE(CT.isCancelled());
+}
+
+TEST(CancellationTest, AsynCancellationTest) {
+  std::atomic HasCancelled(false);
+  Notification Cancelled;
+  auto TaskToBeCancelled = [&](ConstTaskHandle CT) {
+WithContext ContextGuard(setCurrentTask(std::move(CT)));
+Cancelled.wait();
+HasCancelled = isCancelled();
+  };
+  TaskHandle TH = createTaskHandle();
+  std::thread AsyncTask(TaskToBeCancelled, TH);
+  TH->cancel();
+  Cancelled.notify();
+  AsyncTask.join();
+
+  EXPECT_TRUE(HasCancelled);
+}
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: unittests/clangd/CMakeLists.txt
===
--- unittests/clangd/CMakeLists.txt
+++ unittests/clangd/CMakeLists.txt
@@ -10,6 +10,7 @@
 
 add_extra_unittest(ClangdTests
   Annotations.cpp
+  CancellationTests.cpp
   ClangdTests.cpp
   ClangdUnitTests.cpp
   CodeCompleteTests.cpp
Index: clangd/ProtocolHandlers.h
===
--- clangd/ProtocolHandlers.h
+++ clangd/ProtocolHandlers.h
@@ -55,6 +55,7 @@
   virtual void onDocumentHighlight(TextDocumentPositionParams ) = 0;
   virtual void onHover(TextDocumentPositionParams ) = 0;
   virtual void onChangeConfiguration(DidChangeConfigurationParams ) = 0;
+  virtual void onCancelRequest(CancelParams ) = 0;
 };
 
 void registerCallbackHandlers(JSONRPCDispatcher ,
Index: clangd/ProtocolHandlers.cpp
===
--- clangd/ProtocolHandlers.cpp
+++ clangd/ProtocolHandlers.cpp
@@ -75,4 +75,5 @@
   Register("workspace/didChangeConfiguration",
::onChangeConfiguration);
   Register("workspace/symbol", ::onWorkspaceSymbol);
+  Register("$/cancelRequest", ::onCancelRequest);
 }
Index: clangd/Protocol.h
===
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -867,6 +867,16 @@
 llvm::json::Value toJSON(const DocumentHighlight );
 llvm::raw_ostream <<(llvm::raw_ostream &, const DocumentHighlight &);
 
+struct CancelParams {
+  /// The request id to cancel.
+  /// This can be either a number or string, if it is a number simply print it
+  /// out and always use a string.
+  std::string ID;
+};
+llvm::json::Value toJSON(const CancelParams &);
+llvm::raw_ostream <<(llvm::raw_ostream &, const CancelParams &);
+bool fromJSON(const llvm::json::Value &, CancelParams &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clangd/Protocol.cpp
===
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -615,5 +615,30 @@
  O.map("compilationDatabaseChanges", CCPC.compilationDatabaseChanges);
 }
 
+json::Value toJSON(const 

[PATCH] D51038: [clangd] Make sure codecompletion is called for calls even when inside a token.

2018-08-21 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added reviewers: ilya-biryukov, ioeric, hokein.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay.

Currently CodeCompleteCall only gets called after a comma or parantheses. This
patch makes sure it is called even at the cases like:

  foo(1^);


Repository:
  rC Clang

https://reviews.llvm.org/D51038

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseExpr.cpp


Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1648,6 +1648,10 @@
 Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
  })) {
 (void)Actions.CorrectDelayedTyposInExpr(LHS);
+if (PP.isCodeCompletionReached() && !CalledOverloadCompletion) {
+  Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
+  CalledOverloadCompletion = true;
+}
 LHS = ExprError();
   } else if (LHS.isInvalid()) {
 for (auto  : ArgExprs)
@@ -2813,6 +2817,7 @@
 Completer();
   else
 Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
+  CalledOverloadCompletion = true;
   cutOffParsing();
   return true;
 }
Index: include/clang/Parse/Parser.h
===
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -2965,6 +2965,10 @@
   void CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo,
  unsigned ArgumentIndex) override;
   void CodeCompleteNaturalLanguage() override;
+
+  /// Gets set to true after calling CodeCompleteCall, it is for a hack to make
+  /// signature help working even when it is triggered inside a token.
+  bool CalledOverloadCompletion = false;
 };
 
 }  // end namespace clang


Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1648,6 +1648,10 @@
 Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
  })) {
 (void)Actions.CorrectDelayedTyposInExpr(LHS);
+if (PP.isCodeCompletionReached() && !CalledOverloadCompletion) {
+  Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs);
+  CalledOverloadCompletion = true;
+}
 LHS = ExprError();
   } else if (LHS.isInvalid()) {
 for (auto  : ArgExprs)
@@ -2813,6 +2817,7 @@
 Completer();
   else
 Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
+  CalledOverloadCompletion = true;
   cutOffParsing();
   return true;
 }
Index: include/clang/Parse/Parser.h
===
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -2965,6 +2965,10 @@
   void CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo,
  unsigned ArgumentIndex) override;
   void CodeCompleteNaturalLanguage() override;
+
+  /// Gets set to true after calling CodeCompleteCall, it is for a hack to make
+  /// signature help working even when it is triggered inside a token.
+  bool CalledOverloadCompletion = false;
 };
 
 }  // end namespace clang
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D51539: [clangd] Add symbol slab size to index memory consumption estimates

2018-08-31 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clang-tools-extra/clangd/index/dex/DexIndex.cpp:184
+  size_t Bytes = PairedSlabSize;
+  Bytes += LookupTable.size() * sizeof(std::pair);
   Bytes += SymbolQuality.size() * sizeof(std::pair);

Why not use `LookupTable.getMemorySize()` directly? Is it intentionally for not 
counting non-used but allocated buckets? Same for the below two as well.


https://reviews.llvm.org/D51539



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


[PATCH] D51539: [clangd] Add symbol slab size to index memory consumption estimates

2018-08-31 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clang-tools-extra/clangd/index/FileIndex.cpp:91
+  for (const auto  : FileToSlabs)
+Result += P.second->size();
+  return Result;

Why not `bytes` here as well?


https://reviews.llvm.org/D51539



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


[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-04 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 163971.
kadircet added a comment.

- Update comments.


Repository:
  rC Clang

https://reviews.llvm.org/D51038

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseExpr.cpp
  test/CodeCompletion/function-overloads-inside-param.cpp
  test/CodeCompletion/function-overloads.cpp
  test/Index/complete-block-property-assignment.m


Index: test/Index/complete-block-property-assignment.m
===
--- test/Index/complete-block-property-assignment.m
+++ test/Index/complete-block-property-assignment.m
@@ -60,13 +60,15 @@
 // RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck 
-check-prefix=CHECK-NO %s
-// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText 
onAction} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText 
onEventHandler} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText 
onReadonly} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText 
processEvent} (35)
 
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck 
-check-prefix=CHECK-NO1 %s
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO1-NEXT: FunctionDecl:{ResultType void}{TypedText func}{LeftParen 
(}{Placeholder int x}{RightParen )} (50)
 @end
Index: test/CodeCompletion/function-overloads.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:7 %s -o - | 
FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: test/CodeCompletion/function-overloads-inside-param.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads-inside-param.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(1
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:8 %s -o - | 
FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1658,11 +1658,21 @@
 
   if (OpKind == tok::l_paren || !LHS.isInvalid()) {
 if (Tok.isNot(tok::r_paren)) {
-  if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
-Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs,
- PT.getOpenLocation());
-  })) {
+  auto Completer = [&] {
+if (CalledOverloadCompletion)
+  return;
+Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs,
+ PT.getOpenLocation());
+CalledOverloadCompletion = true;
+  };
+  if (ParseExpressionList(ArgExprs, CommaLocs, Completer)) {
 (void)Actions.CorrectDelayedTyposInExpr(LHS);
+// If we got an error when parsing expression list, we don't call
+// the CodeCompleteCall handler inside the parser. So call it here
+// to make sure we get overload suggestions even when we are in the
+// middle of a parameter.
+if (PP.isCodeCompletionReached())
+  Completer();
 LHS = ExprError();
   } else if (LHS.isInvalid()) {
 for (auto  : ArgExprs)
Index: include/clang/Parse/Parser.h
===
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -214,6 +214,10 @@
   /// should not be set directly.
   bool InMessageExpression;
 
+  /// Gets set to true after calling CodeCompleteCall, it is for a workaround 
to
+  /// make sure CodeComleteCall is only called at the deepest level.
+  bool CalledOverloadCompletion = false;
+
   /// The "depth" of the template parameters currently being parsed.
   unsigned TemplateParameterDepth;
 


Index: test/Index/complete-block-property-assignment.m

[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-04 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 163970.
kadircet added a comment.

- Update tests.
- Update comment.
- Rebase.


Repository:
  rC Clang

https://reviews.llvm.org/D51038

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseExpr.cpp
  test/CodeCompletion/function-overloads-inside-param.cpp
  test/CodeCompletion/function-overloads.cpp
  test/Index/complete-block-property-assignment.m


Index: test/Index/complete-block-property-assignment.m
===
--- test/Index/complete-block-property-assignment.m
+++ test/Index/complete-block-property-assignment.m
@@ -60,13 +60,15 @@
 // RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck 
-check-prefix=CHECK-NO %s
-// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText 
onAction} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText 
onEventHandler} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText 
onReadonly} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText 
processEvent} (35)
 
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck 
-check-prefix=CHECK-NO1 %s
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO1-NEXT: FunctionDecl:{ResultType void}{TypedText func}{LeftParen 
(}{Placeholder int x}{RightParen )} (50)
 @end
Index: test/CodeCompletion/function-overloads.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:7 %s -o - | 
FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: test/CodeCompletion/function-overloads-inside-param.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads-inside-param.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(1
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:8 %s -o - | 
FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1658,11 +1658,21 @@
 
   if (OpKind == tok::l_paren || !LHS.isInvalid()) {
 if (Tok.isNot(tok::r_paren)) {
-  if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
-Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs,
- PT.getOpenLocation());
-  })) {
+  auto Completer = [&] {
+if (CalledOverloadCompletion)
+  return;
+Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs,
+ PT.getOpenLocation());
+CalledOverloadCompletion = true;
+  };
+  if (ParseExpressionList(ArgExprs, CommaLocs, Completer)) {
 (void)Actions.CorrectDelayedTyposInExpr(LHS);
+// If we got an error when parsing expression list, we don't call
+// the CodeCompleteCall handler inside the parser. So call it here
+// to make sure we get overload suggestions even when we are in the
+// middle of a parameter.
+if (PP.isCodeCompletionReached())
+  Completer();
 LHS = ExprError();
   } else if (LHS.isInvalid()) {
 for (auto  : ArgExprs)
Index: include/clang/Parse/Parser.h
===
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -214,6 +214,10 @@
   /// should not be set directly.
   bool InMessageExpression;
 
+  /// Gets set to true after calling CodeCompleteCall, it is for a hack to make
+  /// signature help working even when it is triggered inside a token.
+  bool CalledOverloadCompletion = false;
+
   /// The "depth" of the template parameters currently being parsed.
   unsigned TemplateParameterDepth;
 


Index: test/Index/complete-block-property-assignment.m

[PATCH] D51724: [clangd] Add "Deprecated" field to Symbol and CodeCompletion.

2018-09-06 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/index/Index.h:171
+  /// See also isIndexedForCodeCompletion().
+  IsIndexedForCodeCompletion = 1 << 0,
+  /// Indicates if the symbol is deprecated.

nit: rename to IndexedForCodeCompletion, since it is more of an attribute 
having is in the name doesn't seem so cool. Instead of the attributes 
themselves maybe the checkers below should have "is" prefix.



Comment at: clangd/index/Index.h:172
+  IsIndexedForCodeCompletion = 1 << 0,
+  /// Indicates if the symbol is deprecated.
+  Deprecated = 1 << 1,

nit: Add a comment similar to above one leading to Deprecated()?



Comment at: clangd/index/Index.h:268
+  /// FIXME: also add deprecation message and fixit?
+  bool Deprecated() const {
+return static_cast(Flags & SymbolFlag::Deprecated);

nit: rename to isDeprecated ?



Comment at: unittests/clangd/CodeCompleteTests.cpp:1359
   C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;
+  C.Deprecated = true;
 

Maybe do this on its own render so that we can have both code paths covered. 
Just before rendering with `Opts.EnableSnippets = true` below. We can simply 
set this one render again and check deprecated is set to true.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51724



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


[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-07 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 164477.
kadircet added a comment.

- Rebase and use new signature help.

Currently the problem is, there are again some tests out there that rely on
CodeCompeleteOrdinaryName to be called even when getting overloads at an unknown
parameter type. These tests are:

  Clang :: CodeCompletion/call.cpp
  Clang :: Index/code-completion.cpp
  Clang :: Index/complete-call.cpp
  Clang :: Index/complete-functor-call.cpp
  Clang :: Index/complete-optional-params.cpp
  Clang :: Index/complete-pointer-and-reference-to-functions.cpp

You can run something like this to check for the output(change ../clangd_bugs):

  ninja c-index-test && ./bin/c-index-test 
-code-completion-at=../clangd_bugs/tools/clang/test/Index/complete-call.cpp:53:12
 ../clan
  gd_bugs/tools/clang/test/Index/complete-call.cpp

As you can see current version generates only overloadcandidates, but tests
don't check them with a next loop, because they expect other completions, which
is not problematic but after checks for the items they also look for completion
context, which is not set as desired if CodeCompleteOrdinaryName or
CodeCompleteExpression is not called.

But for the first test case it is more complicated, it checks for code patterns
like dynamic_cast(EXPR); which is not generated if we don't call
CodeCompletionOrdinaryName or Expressions.


Repository:
  rC Clang

https://reviews.llvm.org/D51038

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseExpr.cpp
  test/CodeCompletion/function-overloads-inside-param.cpp
  test/CodeCompletion/function-overloads.cpp
  test/Index/complete-block-property-assignment.m

Index: test/Index/complete-block-property-assignment.m
===
--- test/Index/complete-block-property-assignment.m
+++ test/Index/complete-block-property-assignment.m
@@ -60,13 +60,20 @@
 // RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck -check-prefix=CHECK-NO %s
-// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
 
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO1 %s
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
+// CHECK-NO1-NEXT: OverloadCandidate:{ResultType void}{Text func}{LeftParen (}{CurrentParameter int x}{RightParen )} (1)
 @end
Index: test/CodeCompletion/function-overloads.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:7 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: test/CodeCompletion/function-overloads-inside-param.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads-inside-param.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(1
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1659,12 +1659,27 @@
 
   if (OpKind == tok::l_paren || !LHS.isInvalid()) {
 if (Tok.isNot(tok::r_paren)) {
-  if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
-

[PATCH] D51747: [clangd] Implement deprecation diagnostics with lower severity.

2018-09-06 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added reviewers: ioeric, sammccall, ilya-biryukov, hokein.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay.

Adds deprecation warnings to diagnostics. Also lowers the severity from
warning to notes to not to annoy people that work on big codebases.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51747

Files:
  clangd/ClangdServer.cpp
  clangd/Diagnostics.cpp
  unittests/clangd/ClangdUnitTests.cpp


Index: unittests/clangd/ClangdUnitTests.cpp
===
--- unittests/clangd/ClangdUnitTests.cpp
+++ unittests/clangd/ClangdUnitTests.cpp
@@ -38,6 +38,13 @@
   return arg.Range == Range && arg.Message == Message;
 }
 
+MATCHER_P3(Diag, Range, Message, Severity,
+   "Diag at " + llvm::to_string(Range) + " = [" + Message +
+   "] with Severity:" + llvm::to_string(Severity)) {
+  return arg.Range == Range && arg.Message == Message &&
+ arg.Severity == Severity;
+}
+
 MATCHER_P3(Fix, Range, Replacement, Message,
"Fix " + llvm::to_string(Range) + " => " +
testing::PrintToString(Replacement) + " = [" + Message + "]") {
@@ -220,6 +227,48 @@
   }
 }
 
+TEST(DiagnosticsTest, DiagnosticDeprecated) {
+  Annotations Test(R"cpp(
+void foo() __attribute__(($foodeprecation[[deprecated]]));
+class A {
+public:
+  int x __attribute__(($xdeprecation[[deprecated]]));
+};
+int main() {
+  $foo[[foo]]();
+  return A().$x[[x]];
+}
+  )cpp");
+  EXPECT_THAT(
+  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  ElementsAre(
+  AllOf(Diag(Test.range("foo"), "'foo' is deprecated",
+ DiagnosticsEngine::Note),
+WithNote(
+Diag(Test.range("foodeprecation"),
+ "'foo' has been explicitly marked deprecated here"))),
+  AllOf(Diag(Test.range("x"), "'x' is deprecated",
+ DiagnosticsEngine::Note),
+WithNote(
+Diag(Test.range("xdeprecation"),
+ "'x' has been explicitly marked deprecated here");
+}
+
+TEST(DiagnosticsTest, DiagnosticDeprecatedWithFix) {
+  Annotations Test(R"cpp(
+void bar();
+void foo() __attribute__((deprecated("", "bar")));
+int main() {
+  $deprecated[[foo]]();
+}
+  )cpp");
+  EXPECT_THAT(
+  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  ElementsAre(
+  WithFix(Fix(Test.range("deprecated"), "bar", "change 'foo' to 
'bar'"))
+  ));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/Diagnostics.cpp
===
--- clangd/Diagnostics.cpp
+++ clangd/Diagnostics.cpp
@@ -292,10 +292,11 @@
 D.Message = Message.str();
 D.InsideMainFile = InsideMainFile;
 D.File = Info.getSourceManager().getFilename(Info.getLocation());
-D.Severity = DiagLevel;
 D.Category = DiagnosticIDs::getCategoryNameFromID(
  DiagnosticIDs::getCategoryNumberForDiag(Info.getID()))
  .str();
+D.Severity =
+D.Category == "Deprecations" ? DiagnosticsEngine::Note : DiagLevel;
 return D;
   };
 
Index: clangd/ClangdServer.cpp
===
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -534,6 +534,7 @@
   // Inject the resource dir.
   // FIXME: Don't overwrite it if it's already there.
   C->CommandLine.push_back("-resource-dir=" + ResourceDir);
+  C->CommandLine.push_back("-Wdeprecated-declarations");
   return std::move(*C);
 }
 


Index: unittests/clangd/ClangdUnitTests.cpp
===
--- unittests/clangd/ClangdUnitTests.cpp
+++ unittests/clangd/ClangdUnitTests.cpp
@@ -38,6 +38,13 @@
   return arg.Range == Range && arg.Message == Message;
 }
 
+MATCHER_P3(Diag, Range, Message, Severity,
+   "Diag at " + llvm::to_string(Range) + " = [" + Message +
+   "] with Severity:" + llvm::to_string(Severity)) {
+  return arg.Range == Range && arg.Message == Message &&
+ arg.Severity == Severity;
+}
+
 MATCHER_P3(Fix, Range, Replacement, Message,
"Fix " + llvm::to_string(Range) + " => " +
testing::PrintToString(Replacement) + " = [" + Message + "]") {
@@ -220,6 +227,48 @@
   }
 }
 
+TEST(DiagnosticsTest, DiagnosticDeprecated) {
+  Annotations Test(R"cpp(
+void foo() __attribute__(($foodeprecation[[deprecated]]));
+class A {
+public:
+  int x __attribute__(($xdeprecation[[deprecated]]));
+};
+int main() {
+  $foo[[foo]]();
+  return A().$x[[x]];
+}
+  )cpp");
+  EXPECT_THAT(
+  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  ElementsAre(
+  AllOf(Diag(Test.range("foo"), "'foo' is deprecated",
+

[PATCH] D51724: [clangd] Add "Deprecated" field to Symbol and CodeCompletion.

2018-09-06 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: unittests/clangd/SymbolCollectorTests.cpp:1020
+  const std::string Header = R"(
+void TestClangc() __attribute__((deprecated("", "")));
+void TestClangd();

No need for the optional parameters,  
```
void TestClangc() __attribute__((deprecated));
```
should work as well


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51724



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


[PATCH] D51747: [clangd] Implement deprecation diagnostics with lower severity.

2018-09-06 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 164268.
kadircet added a comment.

- Formatting.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51747

Files:
  clangd/ClangdServer.cpp
  clangd/Diagnostics.cpp
  unittests/clangd/ClangdUnitTests.cpp


Index: unittests/clangd/ClangdUnitTests.cpp
===
--- unittests/clangd/ClangdUnitTests.cpp
+++ unittests/clangd/ClangdUnitTests.cpp
@@ -38,6 +38,13 @@
   return arg.Range == Range && arg.Message == Message;
 }
 
+MATCHER_P3(Diag, Range, Message, Severity,
+   "Diag at " + llvm::to_string(Range) + " = [" + Message +
+   "] with Severity:" + llvm::to_string(Severity)) {
+  return arg.Range == Range && arg.Message == Message &&
+ arg.Severity == Severity;
+}
+
 MATCHER_P3(Fix, Range, Replacement, Message,
"Fix " + llvm::to_string(Range) + " => " +
testing::PrintToString(Replacement) + " = [" + Message + "]") {
@@ -220,6 +227,46 @@
   }
 }
 
+TEST(DiagnosticsTest, DiagnosticDeprecated) {
+  Annotations Test(R"cpp(
+void foo() __attribute__(($foodeprecation[[deprecated]]));
+class A {
+public:
+  int x __attribute__(($xdeprecation[[deprecated]]));
+};
+int main() {
+  $foo[[foo]]();
+  return A().$x[[x]];
+}
+  )cpp");
+  EXPECT_THAT(
+  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  ElementsAre(
+  AllOf(Diag(Test.range("foo"), "'foo' is deprecated",
+ DiagnosticsEngine::Note),
+WithNote(
+Diag(Test.range("foodeprecation"),
+ "'foo' has been explicitly marked deprecated here"))),
+  AllOf(Diag(Test.range("x"), "'x' is deprecated",
+ DiagnosticsEngine::Note),
+WithNote(
+Diag(Test.range("xdeprecation"),
+ "'x' has been explicitly marked deprecated here");
+}
+
+TEST(DiagnosticsTest, DiagnosticDeprecatedWithFix) {
+  Annotations Test(R"cpp(
+void bar();
+void foo() __attribute__((deprecated("", "bar")));
+int main() {
+  $deprecated[[foo]]();
+}
+  )cpp");
+  EXPECT_THAT(TestTU::withCode(Test.code()).build().getDiagnostics(),
+  ElementsAre(WithFix(Fix(Test.range("deprecated"), "bar",
+  "change 'foo' to 'bar'";
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/Diagnostics.cpp
===
--- clangd/Diagnostics.cpp
+++ clangd/Diagnostics.cpp
@@ -292,10 +292,11 @@
 D.Message = Message.str();
 D.InsideMainFile = InsideMainFile;
 D.File = Info.getSourceManager().getFilename(Info.getLocation());
-D.Severity = DiagLevel;
 D.Category = DiagnosticIDs::getCategoryNameFromID(
  DiagnosticIDs::getCategoryNumberForDiag(Info.getID()))
  .str();
+D.Severity =
+D.Category == "Deprecations" ? DiagnosticsEngine::Note : DiagLevel;
 return D;
   };
 
Index: clangd/ClangdServer.cpp
===
--- clangd/ClangdServer.cpp
+++ clangd/ClangdServer.cpp
@@ -534,6 +534,7 @@
   // Inject the resource dir.
   // FIXME: Don't overwrite it if it's already there.
   C->CommandLine.push_back("-resource-dir=" + ResourceDir);
+  C->CommandLine.push_back("-Wdeprecated-declarations");
   return std::move(*C);
 }
 


Index: unittests/clangd/ClangdUnitTests.cpp
===
--- unittests/clangd/ClangdUnitTests.cpp
+++ unittests/clangd/ClangdUnitTests.cpp
@@ -38,6 +38,13 @@
   return arg.Range == Range && arg.Message == Message;
 }
 
+MATCHER_P3(Diag, Range, Message, Severity,
+   "Diag at " + llvm::to_string(Range) + " = [" + Message +
+   "] with Severity:" + llvm::to_string(Severity)) {
+  return arg.Range == Range && arg.Message == Message &&
+ arg.Severity == Severity;
+}
+
 MATCHER_P3(Fix, Range, Replacement, Message,
"Fix " + llvm::to_string(Range) + " => " +
testing::PrintToString(Replacement) + " = [" + Message + "]") {
@@ -220,6 +227,46 @@
   }
 }
 
+TEST(DiagnosticsTest, DiagnosticDeprecated) {
+  Annotations Test(R"cpp(
+void foo() __attribute__(($foodeprecation[[deprecated]]));
+class A {
+public:
+  int x __attribute__(($xdeprecation[[deprecated]]));
+};
+int main() {
+  $foo[[foo]]();
+  return A().$x[[x]];
+}
+  )cpp");
+  EXPECT_THAT(
+  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  ElementsAre(
+  AllOf(Diag(Test.range("foo"), "'foo' is deprecated",
+ DiagnosticsEngine::Note),
+WithNote(
+Diag(Test.range("foodeprecation"),
+ "'foo' has been explicitly marked deprecated here"))),
+  

[PATCH] D51747: [clangd] Implement deprecation diagnostics with lower severity.

2018-09-06 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clangd/Diagnostics.cpp:299
+D.Severity =
+D.Category == "Deprecations" ? DiagnosticsEngine::Note : DiagLevel;
 return D;

Couldn't find a better way to check for this one. Category types are coming 
from tablegen file 
https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/DiagnosticGroups.td#L128
 which does not expose category id, at least I couldn't find even if it does.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51747



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


[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-06 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: test/Index/complete-block-property-assignment.m:71
 
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck 
-check-prefix=CHECK-NO1 %s
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)

ilya-biryukov wrote:
> ilya-biryukov wrote:
> > Any idea why behavior changed in that case?
> Looked at it more thoroughly now...
> So we're now showing both the signature help and the completion, right?
> If that the case, LG, but can we include the rest of completion items from 
> CHECK-N0? 
> 
> Maybe also add a comment that the last item is from overload set completion, 
> rather than the ordinary code completion? (To avoid confusion and make it 
> clear why we need an extra check there)
Yes, c-index-test binary collects results from both ProcessOverloadCandidate 
and ProcessCodeCompleteResults. Therefore they are merged. Adding the same set 
of results on the above is not enough for that particular case, due to the 
clever nature of CodeCompleteOverloadResult at 
https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaCodeComplete.cpp#L4439.

It doesn't just try to tell you the overloads of that particular function but 
also tries to complete the current argument. Therefore the list simply gets 
huge by expansion of all the macros and other stuff.

But when looking into it I found out I was checking for wrong return values 
fixing that with the new diff.


Repository:
  rC Clang

https://reviews.llvm.org/D51038



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


[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-06 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 164307.
kadircet added a comment.

- Fix tests.


Repository:
  rC Clang

https://reviews.llvm.org/D51038

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseExpr.cpp
  test/CodeCompletion/function-overloads-inside-param.cpp
  test/CodeCompletion/function-overloads.cpp
  test/Index/complete-block-property-assignment.m


Index: test/Index/complete-block-property-assignment.m
===
--- test/Index/complete-block-property-assignment.m
+++ test/Index/complete-block-property-assignment.m
@@ -60,13 +60,14 @@
 // RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck 
-check-prefix=CHECK-NO %s
-// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck 
-check-prefix=CHECK-NO %s
 // CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText 
onAction} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText 
onEventHandler} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText 
onReadonly} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText 
processEvent} (35)
 
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck 
-check-prefix=CHECK-NO1 %s
+// CHECK-NO1: OverloadCandidate:{ResultType void}{Text func}{LeftParen 
(}{CurrentParameter int x}{RightParen )} (1)
 @end
Index: test/CodeCompletion/function-overloads.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:7 %s -o - | 
FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: test/CodeCompletion/function-overloads-inside-param.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads-inside-param.cpp
@@ -0,0 +1,8 @@
+void f(int i, int j = 2, int k = 5);
+void f(float x, float y...);
+
+void test() {
+  ::f(1
+  // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:5:8 %s -o - | 
FileCheck -check-prefix=CHECK-CC1 %s
+  // CHECK-CC1: f(<#int i#>{#, <#int j = 2#>{#, <#int k = 5#>#}#})
+  // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1658,11 +1658,21 @@
 
   if (OpKind == tok::l_paren || !LHS.isInvalid()) {
 if (Tok.isNot(tok::r_paren)) {
-  if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
-Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs,
- PT.getOpenLocation());
-  })) {
+  auto Completer = [&] {
+if (CalledOverloadCompletion)
+  return;
+Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs,
+ PT.getOpenLocation());
+CalledOverloadCompletion = true;
+  };
+  if (ParseExpressionList(ArgExprs, CommaLocs, Completer)) {
 (void)Actions.CorrectDelayedTyposInExpr(LHS);
+// If we got an error when parsing expression list, we don't call
+// the CodeCompleteCall handler inside the parser. So call it here
+// to make sure we get overload suggestions even when we are in the
+// middle of a parameter.
+if (PP.isCodeCompletionReached())
+  Completer();
 LHS = ExprError();
   } else if (LHS.isInvalid()) {
 for (auto  : ArgExprs)
Index: include/clang/Parse/Parser.h
===
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -214,6 +214,10 @@
   /// should not be set directly.
   bool InMessageExpression;
 
+  /// Gets set to true after calling CodeCompleteCall, it is for a workaround 
to
+  /// make sure CodeComleteCall is only called at the deepest level.
+  bool CalledOverloadCompletion = false;
+
   /// The "depth" of the template parameters currently being parsed.
   unsigned TemplateParameterDepth;
 


Index: test/Index/complete-block-property-assignment.m
===
--- test/Index/complete-block-property-assignment.m

[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 164659.
kadircet added a comment.

- Inline completers.


Repository:
  rC Clang

https://reviews.llvm.org/D51038

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseExpr.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseOpenMP.cpp
  lib/Sema/CodeCompleteConsumer.cpp
  test/CodeCompletion/function-overloads.cpp
  test/Index/complete-block-property-assignment.m

Index: test/Index/complete-block-property-assignment.m
===
--- test/Index/complete-block-property-assignment.m
+++ test/Index/complete-block-property-assignment.m
@@ -60,13 +60,20 @@
 // RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck -check-prefix=CHECK-NO %s
-// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
 
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO1 %s
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
+// CHECK-NO1-NEXT: OverloadCandidate:{ResultType void}{Text func}{LeftParen (}{CurrentParameter int x}{RightParen )} (1)
 @end
Index: test/CodeCompletion/function-overloads.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,27 @@
+int f(int i, int j = 2, int k = 5);
+int f(float x, float y...);
+
+class A {
+ public:
+  A(int, int, int);
+};
+
+void test() {
+  A a(f(1, 2, 3, 4), 2, 3);
+}
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:10 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:17 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:19 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:20 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y)
+// CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>)
+// CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A(
+// CHECK-CC2: OVERLOAD: [#int#]f(float x, float y)
+// CHECK-CC2-NOT: OVERLOAD: [#int#]f(int i)
+// CHECK-CC3: OVERLOAD: A(<#int#>, int, int)
+// CHECK-CC3: OVERLOAD: A(<#const A 

[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 164649.
kadircet marked 2 inline comments as done.
kadircet added a comment.

- Resolve discussions.


Repository:
  rC Clang

https://reviews.llvm.org/D51038

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseExpr.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseOpenMP.cpp
  lib/Sema/CodeCompleteConsumer.cpp
  test/CodeCompletion/function-overloads.cpp
  test/Index/complete-block-property-assignment.m

Index: test/Index/complete-block-property-assignment.m
===
--- test/Index/complete-block-property-assignment.m
+++ test/Index/complete-block-property-assignment.m
@@ -60,13 +60,20 @@
 // RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck -check-prefix=CHECK-NO %s
-// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
 
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO1 %s
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
+// CHECK-NO1-NEXT: OverloadCandidate:{ResultType void}{Text func}{LeftParen (}{CurrentParameter int x}{RightParen )} (1)
 @end
Index: test/CodeCompletion/function-overloads.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,27 @@
+int f(int i, int j = 2, int k = 5);
+int f(float x, float y...);
+
+class A {
+ public:
+  A(int, int, int);
+};
+
+void test() {
+  A a(f(1, 2, 3, 4), 2, 3);
+}
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:10 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:17 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:19 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:20 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y)
+// CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>)
+// CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A(
+// CHECK-CC2: OVERLOAD: [#int#]f(float x, float y)
+// CHECK-CC2-NOT: OVERLOAD: [#int#]f(int i)
+// CHECK-CC3: OVERLOAD: A(<#int#>, int, int)
+// CHECK-CC3: OVERLOAD: A(<#const A 

[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added a comment.

In https://reviews.llvm.org/D51038#1228618, @ilya-biryukov wrote:

> > Currently the problem is, there are again some tests out there that rely on
> >  CodeCompeleteOrdinaryName to be called even when getting overloads at an 
> > unknown
> >  parameter type
>
> CodeCompleteExpression works just fine there. Unknown parameter type should 
> not block code completion.
>  The idea is that anywhere except the start of the argument expression, we 
> need to call **only** signature help. At the start of the argument, we have 
> to call both signature help and code completion.


Yeah you are right, I thought I could check whether I am inside a parameter or 
not by looking at qual type, which was apparently wrong :D

But, unfortunately, there were still tests failing which was caused by printing 
of completion strings for overloaded methods with optional parameters. It was 
trying to access Text field, which is not defined for Optional parameters.
Since it didn't print optional parameters in the original behavior I kept it 
that way. Can send it as a different patch if need be.


Repository:
  rC Clang

https://reviews.llvm.org/D51038



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


[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 164639.
kadircet marked an inline comment as done.
kadircet added a comment.

- Change "inside parameter" checking and fix completion string printing for 
optional parameters.
- Update tests.


Repository:
  rC Clang

https://reviews.llvm.org/D51038

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseExpr.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseOpenMP.cpp
  lib/Sema/CodeCompleteConsumer.cpp
  test/CodeCompletion/function-overloads.cpp
  test/Index/complete-block-property-assignment.m

Index: test/Index/complete-block-property-assignment.m
===
--- test/Index/complete-block-property-assignment.m
+++ test/Index/complete-block-property-assignment.m
@@ -60,13 +60,20 @@
 // RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck -check-prefix=CHECK-NO %s
-// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
 
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO1 %s
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
+// CHECK-NO1-NEXT: OverloadCandidate:{ResultType void}{Text func}{LeftParen (}{CurrentParameter int x}{RightParen )} (1)
 @end
Index: test/CodeCompletion/function-overloads.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,27 @@
+int f(int i, int j = 2, int k = 5);
+int f(float x, float y...);
+
+class A {
+ public:
+  A(int, int, int);
+};
+
+void test() {
+  A a(f(1, 2, 3, 4), 2, 3);
+}
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:10 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:17 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:19 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:20 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y)
+// CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>)
+// CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A(
+// CHECK-CC2: OVERLOAD: [#int#]f(float x, float y)
+// CHECK-CC2-NOT: OVERLOAD: [#int#]f(int i)
+// CHECK-CC3: OVERLOAD: A(<#int#>, int, int)
+// CHECK-CC3: OVERLOAD: A(<#const A 

[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 164661.
kadircet marked an inline comment as done.
kadircet added a comment.

- One last completer


Repository:
  rC Clang

https://reviews.llvm.org/D51038

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseExpr.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseOpenMP.cpp
  lib/Sema/CodeCompleteConsumer.cpp
  test/CodeCompletion/function-overloads.cpp
  test/Index/complete-block-property-assignment.m

Index: test/Index/complete-block-property-assignment.m
===
--- test/Index/complete-block-property-assignment.m
+++ test/Index/complete-block-property-assignment.m
@@ -60,13 +60,20 @@
 // RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck -check-prefix=CHECK-NO %s
-// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
 
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO1 %s
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
+// CHECK-NO1-NEXT: OverloadCandidate:{ResultType void}{Text func}{LeftParen (}{CurrentParameter int x}{RightParen )} (1)
 @end
Index: test/CodeCompletion/function-overloads.cpp
===
--- /dev/null
+++ test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,27 @@
+int f(int i, int j = 2, int k = 5);
+int f(float x, float y...);
+
+class A {
+ public:
+  A(int, int, int);
+};
+
+void test() {
+  A a(f(1, 2, 3, 4), 2, 3);
+}
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:10 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:17 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:19 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:20 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y)
+// CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>)
+// CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A(
+// CHECK-CC2: OVERLOAD: [#int#]f(float x, float y)
+// CHECK-CC2-NOT: OVERLOAD: [#int#]f(int i)
+// CHECK-CC3: OVERLOAD: A(<#int#>, int, int)
+// CHECK-CC3: OVERLOAD: A(<#const A 

[PATCH] D51038: [clang] Make sure codecompletion is called for calls even when inside a token.

2018-09-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL341824: [clang] Make sure codecompletion is called for calls 
even when inside a token. (authored by kadircet, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D51038

Files:
  cfe/trunk/include/clang/Parse/Parser.h
  cfe/trunk/lib/Parse/ParseDecl.cpp
  cfe/trunk/lib/Parse/ParseExpr.cpp
  cfe/trunk/lib/Parse/ParseExprCXX.cpp
  cfe/trunk/lib/Parse/ParseOpenMP.cpp
  cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
  cfe/trunk/test/CodeCompletion/function-overloads.cpp
  cfe/trunk/test/Index/complete-block-property-assignment.m

Index: cfe/trunk/include/clang/Parse/Parser.h
===
--- cfe/trunk/include/clang/Parse/Parser.h
+++ cfe/trunk/include/clang/Parse/Parser.h
@@ -214,6 +214,11 @@
   /// should not be set directly.
   bool InMessageExpression;
 
+  /// Gets set to true after calling ProduceSignatureHelp, it is for a
+  /// workaround to make sure ProduceSignatureHelp is only called at the deepest
+  /// function call.
+  bool CalledSignatureHelp = false;
+
   /// The "depth" of the template parameters currently being parsed.
   unsigned TemplateParameterDepth;
 
Index: cfe/trunk/test/Index/complete-block-property-assignment.m
===
--- cfe/trunk/test/Index/complete-block-property-assignment.m
+++ cfe/trunk/test/Index/complete-block-property-assignment.m
@@ -60,13 +60,20 @@
 // RUN: c-index-test -code-completion-at=%s:51:16 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:52:23 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:53:12 %s | FileCheck -check-prefix=CHECK-NO %s
-// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // RUN: c-index-test -code-completion-at=%s:56:15 %s | FileCheck -check-prefix=CHECK-NO %s
 // CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
 // CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
 
+// RUN: c-index-test -code-completion-at=%s:54:15 %s | FileCheck -check-prefix=CHECK-NO1 %s
+// CHECK-NO1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
+// CHECK-NO1-NEXT: ObjCPropertyDecl:{ResultType int (^)(int)}{TypedText processEvent} (35)
+// CHECK-NO1-NEXT: OverloadCandidate:{ResultType void}{Text func}{LeftParen (}{CurrentParameter int x}{RightParen )} (1)
 @end
Index: cfe/trunk/test/CodeCompletion/function-overloads.cpp
===
--- cfe/trunk/test/CodeCompletion/function-overloads.cpp
+++ cfe/trunk/test/CodeCompletion/function-overloads.cpp
@@ -0,0 +1,27 @@
+int f(int i, int j = 2, int k = 5);
+int f(float x, float y...);
+
+class A {
+ public:
+  A(int, int, int);
+};
+
+void test() {
+  A a(f(1, 2, 3, 4), 2, 3);
+}
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:10 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:17 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:19 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:20 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y)
+// CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>)
+// CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A(
+// CHECK-CC2: OVERLOAD: [#int#]f(float x, float y)
+// CHECK-CC2-NOT: OVERLOAD: [#int#]f(int i)
+// CHECK-CC3: OVERLOAD: A(<#int#>, int, int)
+// CHECK-CC3: OVERLOAD: A(<#const A 

[PATCH] D51039: [clangd] Add unittests for D51038

2018-09-10 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL341830: [clangd] Add unittests for D51038 (authored by 
kadircet, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D51039?vs=163968=164668#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D51039

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


Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
@@ -1917,6 +1917,56 @@
AllOf(Named("TestClangc"), Deprecated(;
 }
 
+TEST(SignatureHelpTest, InsideArgument) {
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1+^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^0); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int bar(int x, int y);
+  int main() { bar(foo(2, 3^)); }
+)cpp");
+EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo(int x, int y) -> 
void",
+{"int x", "int y"})));
+EXPECT_EQ(1, Results.activeParameter);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang


Index: clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
===
--- clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/CodeCompleteTests.cpp
@@ -1917,6 +1917,56 @@
AllOf(Named("TestClangc"), Deprecated(;
 }
 
+TEST(SignatureHelpTest, InsideArgument) {
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1+^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^0); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int bar(int x, int y);
+  int main() { bar(foo(2, 3^)); }
+)cpp");
+EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo(int x, int y) -> void",
+{"int x", "int y"})));
+EXPECT_EQ(1, Results.activeParameter);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D51747: [clangd] Implement deprecation diagnostics with lower severity.

2018-09-07 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added a comment.

In https://reviews.llvm.org/D51747#1227089, @ilya-biryukov wrote:

> Not sure if it's fine to hijack our own diagnostic-specific flags in to clang 
> command args.
>
> Cons that I see:
>
> 1. There is no way for the users to turn them off if they find them 
> non-useful. If we add a way, it would be more config parameters which overlap 
> with other mechanism that we have - compiler flags.
> 2. Users who are used to having them as warnings will now see them as notes. 
> Again, no way to tweak this behavior.
>
>   What's our use-case? Maybe we should ask the clients to add -Wdeprecated if 
> they care about those?
>
>   PS In case I'm missing the context here, please let me know.


Agree with you, I think it would be better to provide it as an option. 
https://reviews.llvm.org/D51724 with this one we added a way to show deprecated 
symbols on code completion responses and wanted to move forward with showing 
the ones that are already in existing code.




Comment at: clangd/Diagnostics.cpp:299
+D.Severity =
+D.Category == "Deprecations" ? DiagnosticsEngine::Note : DiagLevel;
 return D;

ioeric wrote:
> kadircet wrote:
> > Couldn't find a better way to check for this one. Category types are coming 
> > from tablegen file 
> > https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/DiagnosticGroups.td#L128
> >  which does not expose category id, at least I couldn't find even if it 
> > does.
> Have you tried the Diagnostic ID (i.e. `Info.getID()`)? It matches the diag 
> kinds defined in `DiagnosticSemaKinds.inc` (e.g. `warn_deprecated`).
Unfortunately these are also internal, 
https://github.com/llvm-mirror/clang/blob/master/lib/Basic/DiagnosticIDs.cpp#L97


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51747



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


[PATCH] D51039: [clangd] Add unittests for D51038

2018-09-04 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 163968.
kadircet added a comment.

Rebase


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51039

Files:
  unittests/clangd/CodeCompleteTests.cpp


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1882,6 +1882,56 @@
   AllOf(Named("Func"), HasInclude("\"foo.h\""), 
Not(InsertInclude();
 }
 
+TEST(SignatureHelpTest, InsideArgument) {
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1+^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^0); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int bar(int x, int y);
+  int main() { bar(foo(2, 3^)); }
+)cpp");
+EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo(int x, int y) -> 
void",
+{"int x", "int y"})));
+EXPECT_EQ(1, Results.activeParameter);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang


Index: unittests/clangd/CodeCompleteTests.cpp
===
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -1882,6 +1882,56 @@
   AllOf(Named("Func"), HasInclude("\"foo.h\""), Not(InsertInclude();
 }
 
+TEST(SignatureHelpTest, InsideArgument) {
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1+^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int main() { foo(1^0); }
+)cpp");
+EXPECT_THAT(
+Results.signatures,
+ElementsAre(Sig("foo(int x) -> void", {"int x"}),
+Sig("foo(int x, int y) -> void", {"int x", "int y"})));
+EXPECT_EQ(0, Results.activeParameter);
+  }
+  {
+const auto Results = signatures(R"cpp(
+  void foo(int x);
+  void foo(int x, int y);
+  int bar(int x, int y);
+  int main() { bar(foo(2, 3^)); }
+)cpp");
+EXPECT_THAT(Results.signatures, ElementsAre(Sig("foo(int x, int y) -> void",
+{"int x", "int y"})));
+EXPECT_EQ(1, Results.activeParameter);
+  }
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D51917: [CodeCompletion] Enable signature help when initializing class/struct/union members.

2018-09-11 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added reviewers: sammccall, ilya-biryukov, ioeric.
Herald added a subscriber: cfe-commits.

Factors out member decleration gathering and uses it in parsing to call 
signature
help. Doesn't support signature help for base class constructors, the code was 
too
coupled with diagnostic handling, but still can be factored out but just needs
more afford.


Repository:
  rC Clang

https://reviews.llvm.org/D51917

Files:
  include/clang/Sema/Sema.h
  lib/Parse/ParseDeclCXX.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeCompletion/ctor-initializer.cpp

Index: test/CodeCompletion/ctor-initializer.cpp
===
--- test/CodeCompletion/ctor-initializer.cpp
+++ test/CodeCompletion/ctor-initializer.cpp
@@ -64,3 +64,26 @@
   // CHECK-CC8: COMPLETION: Pattern : member2(<#args#>
   int member1, member2;
 };
+
+struct Base2 {
+  Base2(int);
+};
+
+struct Composition1 {
+  Composition1() : b2_elem() {}
+  // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:73:28 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:73:28 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+  // CHECK-CC9: OVERLOAD: Base2(<#int#>)
+  // CHECK-CC9: OVERLOAD: Base2(<#const Base2 

[PATCH] D51297: [docs] Create a guide for Vim users on how to set up Clangd

2018-09-11 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added a comment.

In https://reviews.llvm.org/D51297#1228725, @ioeric wrote:

> I also support having some instructions/pointers on editor integration. That 
> said, I think we should have a section "Editor integration" with a list of 
> editor clients that are known to work with clangd, instead of having a 
> section just for vim. Something like:
>
>   #Editor (or client?) integration
>  
>   ##Vim
>   Some LSP clients that are known to work with clangd:
>- nvim, LanguageClient-neovim ..
>- ...
>  
>   ## vscode
>  
>   ## emacs?
>  
>
>
> What do you think?


Sorry I am trespassing, just wanted to say +1 to this.


https://reviews.llvm.org/D51297



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


[PATCH] D51214: [clangd] Add options to enable/disable fixits and function argument snippets.

2018-09-11 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 164830.
kadircet marked 5 inline comments as done.
kadircet added a comment.

- Change flag's name and rebase.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51214

Files:
  clangd/tool/ClangdMain.cpp


Index: clangd/tool/ClangdMain.cpp
===
--- clangd/tool/ClangdMain.cpp
+++ clangd/tool/ClangdMain.cpp
@@ -168,6 +168,19 @@
 "'compile_commands.json' files")),
 llvm::cl::init(FilesystemCompileArgs), llvm::cl::Hidden);
 
+static llvm::cl::opt IncludeFixIts(
+"completions-with-fixes",
+llvm::cl::desc(
+"Enables suggestion of completion items that needs additional changes. 
"
+"Like changing an arrow(->) member access to dot(.) member access."),
+llvm::cl::init(clangd::CodeCompleteOptions().IncludeFixIts));
+
+static llvm::cl::opt EnableFunctionArgSnippets(
+"enable-function-arg-snippets",
+llvm::cl::desc("Gives snippets for function arguments, when disabled only "
+   "gives parantheses for the call."),
+llvm::cl::init(clangd::CodeCompleteOptions().EnableFunctionArgSnippets));
+
 int main(int argc, char *argv[]) {
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
   llvm::cl::SetVersionPrinter([](llvm::raw_ostream ) {
@@ -295,6 +308,8 @@
 CCOpts.IncludeIndicator.NoInsert.clear();
   }
   CCOpts.SpeculativeIndexRequest = Opts.StaticIndex;
+  CCOpts.IncludeFixIts = IncludeFixIts;
+  CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
 
   // Initialize and run ClangdLSPServer.
   ClangdLSPServer LSPServer(


Index: clangd/tool/ClangdMain.cpp
===
--- clangd/tool/ClangdMain.cpp
+++ clangd/tool/ClangdMain.cpp
@@ -168,6 +168,19 @@
 "'compile_commands.json' files")),
 llvm::cl::init(FilesystemCompileArgs), llvm::cl::Hidden);
 
+static llvm::cl::opt IncludeFixIts(
+"completions-with-fixes",
+llvm::cl::desc(
+"Enables suggestion of completion items that needs additional changes. "
+"Like changing an arrow(->) member access to dot(.) member access."),
+llvm::cl::init(clangd::CodeCompleteOptions().IncludeFixIts));
+
+static llvm::cl::opt EnableFunctionArgSnippets(
+"enable-function-arg-snippets",
+llvm::cl::desc("Gives snippets for function arguments, when disabled only "
+   "gives parantheses for the call."),
+llvm::cl::init(clangd::CodeCompleteOptions().EnableFunctionArgSnippets));
+
 int main(int argc, char *argv[]) {
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
   llvm::cl::SetVersionPrinter([](llvm::raw_ostream ) {
@@ -295,6 +308,8 @@
 CCOpts.IncludeIndicator.NoInsert.clear();
   }
   CCOpts.SpeculativeIndexRequest = Opts.StaticIndex;
+  CCOpts.IncludeFixIts = IncludeFixIts;
+  CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
 
   // Initialize and run ClangdLSPServer.
   ClangdLSPServer LSPServer(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D51917: [CodeCompletion] Enable signature help when initializing class/struct/union members.

2018-09-11 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 164844.
kadircet marked 3 inline comments as done.
kadircet added a comment.

- Move ValueDecl extraction to a helper.
- Call completion handlers as well.


Repository:
  rC Clang

https://reviews.llvm.org/D51917

Files:
  include/clang/Sema/Sema.h
  lib/Parse/ParseDeclCXX.cpp
  lib/Sema/SemaCodeComplete.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeCompletion/ctor-initializer.cpp

Index: test/CodeCompletion/ctor-initializer.cpp
===
--- test/CodeCompletion/ctor-initializer.cpp
+++ test/CodeCompletion/ctor-initializer.cpp
@@ -64,3 +64,26 @@
   // CHECK-CC8: COMPLETION: Pattern : member2(<#args#>
   int member1, member2;
 };
+
+struct Base2 {
+  Base2(int);
+};
+
+struct Composition1 {
+  Composition1() : b2_elem() {}
+  // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:73:28 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+  // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:73:28 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+  // CHECK-CC9: OVERLOAD: Base2(<#int#>)
+  // CHECK-CC9: OVERLOAD: Base2(<#const Base2 

  1   2   3   4   5   6   7   8   9   10   >